我试图用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>)'
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;
编译器没有办法知道哪些是... 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
.