模板有一些奇怪的问题。当试图传递参数化迭代器时,它抱怨没有找到任何函数。代码片段在这里,忘记了功能,它使用了对我感兴趣的模板化迭代器的引用
#include <list>
#include <iostream>
template<typename T>
void print_list_element(typename std::list<T>::iterator& it){
std::cout << *it << std::endl;
}
int main() {
std::list<int> theList;
theList.push_back(1);
std::list<int>::iterator it = theList.begin();
print_list_element(it);
return 0;
}
如果你试图用g ++ v4.3.2编译它,它会抱怨说:
main.cpp:14: error: no matching function for call to 'print_list_element(std::_List_iterator<int>&)'
我写的代码有什么问题,或者g ++需要更多信息吗?
答案 0 :(得分:9)
g ++无法确定它应该使用print_list_element
的哪个模板重载。如果明确指定模板参数,则可以使用:
print_list_element<int>(it);
答案 1 :(得分:5)
更好的方法是编写如下函数:
template<typename Iter>
void print_element(Iter it){
std::cout << *it << std::endl;
}
这将适用于任何类型的迭代器,而不仅仅是std::list<T>::iterator
。此外,模板类型将从参数中正确推导出来。
我意识到这是一个人为的例子,但几乎总是你可能不想将list<T>::iterator
传递给函数。在最坏的情况下,至少是ListType上的模板,这样您的代码就可以使用带有自定义分配器的列表。
答案 2 :(得分:4)
这是非法的,因为std :: list&lt; T&gt; :: iterator不是标准所称的适当的推导上下文
答案 3 :(得分:4)
其他答案都是正确的,但为了完整起见,我只想补充一点,按照设计,C ++只能在某些情况下自动推断模板参数 ,而这不是其中之一。 / p>
当你考虑它时,你会发现在这种情况下自动扣除会导致不良情况。 std::list<T>::iterator
不是真正的类型,它只是真实类型的typedef
别名(例如,它可能是T*
),它立即被翻译,因此编译器必须构建一些一种“反向索引”,以便将T*
映射回std::list<T>::iterator
,以自动扣除T
在此工作。但是这个映射会在创建另一个类模板后立即中断,该模板具有一个名为iterator
的类型成员,typedef
编译为T*
- 然后编译器将有两个选择将T*
翻译为,并且无法在它们之间进行选择。显然,任何在不相关的类添加特定typedef
类型成员时中断的自动扣减政策都太脆弱了。