如何在另一个模板函数中调用模板函数?

问题描述 投票:0回答:1

我试图用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>)'
c++ c++14
1个回答
4
投票

printItem 是一个函数模板,它不能推断出参数类型,所以你需要指定,比如这样。

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

另外,似乎有一个错别字在 printItem. 你不需要取消引用。t 完全不使用。

如果你没有在其他地方使用这个函数,那么你可以使用一个lambda来内联定义它,就像这样。

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

注意这个lambda operator() 在这种情况下也是模板化的,不过类型可以推导出来,所以就可以了。

另外。std::for_each 在我看来,这往往是一种代码的味道。可以用可读性更强的来代替。

for (auto const &s : t)
    std::cout << s << std::endl; 

1
投票

编译器没有办法知道哪些是... printItem 你想要的专门化,根据当时的标准,它可以得到的信息。

所以,这个语法在这里是没有的。

这就是你所需要的。

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

能够做这样的事情正是容器被要求定义类型别名的原因,比如说: value_type;你最终需要他们所有的地方。

语言的限制?也许是吧。但它确实有助于避免角落的情况。

不得不使用 typename 这里当然 烦心事不过,你的代码


你的代码,说实话,如果你只用一个循环,会更简单,更清晰。

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

In the time of ranged -for and all that lovely stuff. - 如果你只用一个循环: 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.

© www.soinside.com 2019 - 2024. All rights reserved.