[英]How do you pass a reference when using a typename as a function argument in C++?
I have some weird problem with templates. 模板有一些奇怪的问题。 When trying to pass a parameterised iterator it complains that no function can be found.
当试图传递参数化迭代器时,它抱怨没有找到任何函数。 The code snippet is here, forget about the functionality, it's using the reference to the templatized iterator what interests me
代码片段在这里,忘记了功能,它使用了对模板化迭代器的引用我感兴趣的是什么
#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;
}
If you try to compile this with g++ v4.3.2 it complains with a message saying that: 如果您尝试使用g ++ v4.3.2编译它,它会抱怨说:
main.cpp:14: error: no matching function for call to 'print_list_element(std::_List_iterator<int>&)'
Is there something wrong with the code I wrote or is that g++ needs more information? 我写的代码有什么问题,或者g ++需要更多信息吗?
g++ can't figure out which template overload of print_list_element
it should use. g ++无法确定应该使用哪个模板重载
print_list_element
。 If you explicitly specify the template parameter it works: 如果您明确指定模板参数,它可以工作:
print_list_element<int>(it);
A better way is to write the function like this: 更好的方法是编写这样的函数:
template<typename Iter>
void print_element(Iter it){
std::cout << *it << std::endl;
}
This will now work for any type of iterator, not just std::list<T>::iterator
. 这将适用于任何类型的迭代器,而不仅仅是
std::list<T>::iterator
。 Also, the template type will be deduced correctly from the argument. 此外,将从参数中正确推导出模板类型。
I realize that it was a contrived example, but almost always you probably didnt want to pass in list<T>::iterator
to a function anyways. 我意识到这是一个人为的例子,但几乎总是你可能不想将
list<T>::iterator
传递给函数。 At worst, at least template on ListType so that your code would work with lists with custom allocators. 在最坏的情况下,至少是ListType上的模板,以便您的代码可以使用带有自定义分配器的列表。
这是非法的,因为std :: list <T> :: iterator不是标准所称的适当的推导上下文
The other responses are correct, but for completeness I'll just add that, by design, C++ can only deduce template arguments automatically in certain cases , and this isn't one of them. 其他响应是正确的,但为了完整性,我只想补充一点,按照设计,C ++只能在某些情况下自动推导出模板参数,而这不是其中之一。
When you think about it, you'll realise that automatic deduction in this case would lead to an undesirable situation. 当你考虑它时,你会发现在这种情况下自动扣除会导致不良情况。
std::list<T>::iterator
is not a real type, it's just a typedef
alias for a real type (eg it might be T*
) to which it is immediately translated, so the compiler would have to build some sort of "reverse index" in order to map T*
back to std::list<T>::iterator
for automatic deduction of T
to work here. std::list<T>::iterator
不是一个真正的类型,它只是一个真正类型的typedef
别名(例如它可能是T*
),它立即被翻译,因此编译器必须构建某种类型的“反向索引”,以便将T*
映射回std::list<T>::iterator
以自动扣除T
在这里工作。 But this mapping would break as soon as another class template was created that had a type member called iterator
that was typedef
ed to T*
-- then the compiler would have two choices of what to translate T*
to, and no way to choose between them. 但是,这个映射将尽快为另一个类模板创建了一种名为成员打破
iterator
,这是typedef
版,以T*
那么编译器将有什么翻译两种选择- T*
到了,没办法之间作出选择他们。 Clearly, any automatic deduction policy that breaks when an unrelated class adds a particular typedef
type member is much too fragile to work. 显然,任何在不相关的类添加特定
typedef
类型成员时中断的自动扣除策略都太脆弱而无法工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.