Контейнер STL с указанным типом c в качестве аргумента обобщенного c - PullRequest
25 голосов
/ 19 февраля 2020

Можно ли как-нибудь создать функцию, которая принимает контейнер с указанным типом c (скажем, std::string) в качестве параметра

void foo(const std::container<std::string> &cont)
{
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

и вызывает его для каждого типа STL контейнер в качестве ввода? как выше?

std::set<std::string> strset;
std::vector<std::string> strvec;
std::list<std::string> strlist;

foo(strset);
foo(strvec);
foo(strlist);

Ответы [ 4 ]

21 голосов
/ 19 февраля 2020

Вы можете сделать foo шаблоном функции, приняв параметр шаблона шаблона для типа контейнера.

например

template<template<typename...> typename C>
void foo(const C<std::string> &cont)
{
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

LIVE

6 голосов
/ 19 февраля 2020

В зависимости от того, хотите ли вы перегрузить foo для других случаев или нет

// Doesn't participate in overload resolution when not applicable
template<typename Container, typename = std::enable_if_t<std::is_same_v<typename Container::value_type, std::string>>>
void foo(const Container &cont) {
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

// simpler
template<typename Container>
void foo(const Container &cont) {
   static_assert(std::is_same_v<typename Container::value_type, std::string>, "Container must contain std::string")
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

Вы можете использовать другой тест для std::is_same, например std::is_convertible для разрешения

std::vector<char *> c_strings;
foo(c_strings);
0 голосов
/ 25 февраля 2020

Возможно, вы захотите использовать итераторы. Промежуточный результат может выглядеть следующим образом:

template<typename Iter>
void foo(Iter begin, Iter end) {
  using T = decltype(*begin);
  std::for_each(begin, end, [] (cons T & t) {
    std::out << t << '\n';
  }
}

Теперь используется вызываемый шаблон:

template<typename Iter, typename Callable>
void foo(Iter begin, Iter end, Callable & c) {
  std::for_each(begin, end, c);
}

Мы только что научились использовать то, что уже предлагает STL.

0 голосов
/ 19 февраля 2020

Добавляя к ответу @ songyuanyao, я думаю, что мы можем обобщить его следующим образом:

template<template<typename...> typename C, typename ... D>
void foo(const C<D...> &cont)
{
   for(const auto& val: cont) {
      std::cout << val << std::endl;
   }
}
...