Reputation: 4795
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:
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?
Upvotes: 3
Views: 916
Reputation: 36459
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
. 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. At worst, at least template on ListType so that your code would work with lists with custom allocators.
Upvotes: 5
Reputation: 51326
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.
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 (e.g. 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. 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. Clearly, any automatic deduction policy that breaks when an unrelated class adds a particular typedef
type member is much too fragile to work.
Upvotes: 4
Reputation: 229934
g++ can't figure out which template overload of print_list_element
it should use. If you explicitly specify the template parameter it works:
print_list_element<int>(it);
Upvotes: 9
Reputation: 2984
That is illegal because std::list< T >::iterator is not what the standard calls a proper deduced context
Upvotes: 4