Search code examples
c++templatesfunction-templatestype-deduction

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

Solution

  • 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);