Как я могу вызвать функцию шаблона в другой функции шаблона - PullRequest
0 голосов
/ 23 апреля 2020

Я пытался написать обобщенную c функцию печати на C ++ 14. Но функция шаблона printItem не может быть создана.

template <class T>
void printItem(T t)
{
    std::cout << t << std::endl;
}

template <class T>
void printVector(T t)
{
    for_each(t.begin(), t.end(), printItem);
}

int main()
{
    std::vector<std::string> vs = {"word1", "word2"};

    printVector(vs);
}

Этот код вызывает ошибку компилятора:

no matching function for call to 
'for_each(std::vector<std::__cxx11::basic_string<char> >::iterator, std::vector<std::__cxx11::basic_string<char> >::iterator, <unresolved overloaded function type>)'

Ответы [ 2 ]

4 голосов
/ 23 апреля 2020

printItem является шаблоном функции, и он не может определить тип аргумента, поэтому вам нужно указать его следующим образом:

for_each(t.begin(), t.end(), printItem<typename T::value_type>);

Кроме того, в printItem имеется опечатка , Вам вообще не нужно разыменовывать t.

Если вы не используете эту функцию где-либо еще, вы можете определить ее встроенно с помощью лямбды, например:

for_each(t.begin(), t.end(), [](auto s) { std::cout << s << std::endl; });

Обратите внимание, что лямбда operator() также является шаблонной в этом случае, однако тип может быть выведен, так что все в порядке.

Также, на мой взгляд, std::for_each часто является запахом кода. Его можно заменить гораздо более читабельным:

for (auto const &s : t)
    std::cout << s << std::endl; 
1 голос
/ 23 апреля 2020

Компилятор не может узнать, какую специализацию printItem вы хотели, с информацией, доступной ему в соответствии со стандартом на тот момент.

Таким образом, этот синтаксис здесь недоступен.

Это то, что вам нужно:

for_each(t.begin(), t.end(), printItem<typename T::value_type>);

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

Ограничение в языке? Может быть. Но это помогает избежать угловых случаев.

Необходимость использования typename здесь, безусловно, раздражение .


Ваш код, если честно, было бы намного проще и понятнее, если бы вы просто использовали al oop:

for (const auto& item : t)
   printItem(item);

Во времена дальнего радиуса и всего такого прекрасного, for_each не так уж полезен для обычных случаев. подробнее.


Кроме того, возьмите аргументы по ссылке на const и удалите ошибочную разыменование. Я также удалю повторное std::endl, которое выполняет очистку потока, в котором вы не нуждаетесь.

template <class T>
void printItem(const T& t)
{
    std::cout << t << '\n';
}

template <class T>
void printVector(const T& t)
{
    for (const auto& item : t)
       printItem(t);
}

int main()
{
    std::vector<std::string> vs = {"word1", "word2"};
    printVector(vs);
}

Наконец, неплохо бы, чтобы такие функции, как printItem, брали ссылку на поток вы хотите использовать, чтобы вы могли выбрать (скажем) std::stringstream вместо только std::cout.

...