Luca
Luca

Reputation: 1776

function template and iterators

I have this simple function template that's supposed to take a container as its template argument and print the contents:

template <typename T>
void print(typename T::iterator &it1,typename T::iterator &it2)
{
  while (it1 != it2) {
    std::cout<<*it1<<" ";
    ++it1;
  }
}

I'm passing an iterator range (tipically the first and the off-the-end iterators) and I added the typename keyword to the function parameters because the compiler needs to know that I'm talking about a type and not a static member.

but when I pass a vector to the function the compiler says it can't find any match for the call (the closest match being the function itself) How can it be?

vector<double> dvec;
vector<double>::iterator it_b=dvec.begin();
vector<double>::iterator it_e=dvec.end();
print_it2(it_b,it_e);

the compiler says :

template argument deduction/substitution failed
                    could not deduce template parameter T

Upvotes: 2

Views: 423

Answers (1)

TartanLlama
TartanLlama

Reputation: 65770

typename T::iterator is a non-deduced context. The compiler has no way of knowing which T should be deduced because it doesn't understand the semantic connection between the type member iterator and a given T. It would need to search through all types to find a match and be able to somehow disambiguate collisions. This is unreasonable, so the standard doesn't allow it.

You could supply the type explicitly:

print<vector<double>>(it_b, it_e);
print<decltype(dvec)>(it_b, it_e); //c++11

But it would probably be easier to forget about the container from which the iterator came and let the compiler deduce the iterator type:

template <typename It>
void print (It& it1, It& it2);

Maybe you have a reason to pass the iterators by reference, but it seems like you should pass by value instead:

template <typename It>
void print (It it1, It it2);    

Upvotes: 3

Related Questions