They do ambiguity for many algorithms. A lot of <algorithm> looks like
template<class iterator> void do_something(iterator, iterator); template<class iterator, class funct> void do_something(iterator, iterator, funct);
If you add extra overloads
template<class container, class funct> void do_something(container, funct);
the compiler will have some trouble understanding what do_something(x, y) means. If x and y have the same type , it will match both iterator = type and container = type, funct = type . *)
C ++ 11 tried to solve this problem with βconceptsβ that could recognize the difference between a container and an iterator. However, these "concepts" turned out to be too complex to turn it into a standard, therefore, these overloads were not.
*) the compilers do not agree with this, the Comeau compiler claims that it is ambiguous, g ++ 4.5 and MSVC 10 calls the first function.
After an extremely lengthy discussion of comments, here is one example where it does not work as expected - using a container adapter, which can also be double as a predicate.
#include <iostream> #include <vector> template<class iterator> void test(iterator, iterator) { std::cout << "test iterator\n"; } template<class iterator, class predicate> void test(iterator, iterator, predicate) { std::cout << "test iterator, predicate\n"; } template<class container, class predicate> void test(const container& cont, predicate compare) { std::cout << "test container, predicate\n"; test(cont.begin(), cont.end(), compare); } template<class container> class adapter { public: typedef typename container::iterator iterator; adapter(container* cont) : cont(cont) { } iterator begin() const { return cont->begin(); } iterator end() const { return cont->end(); } bool operator()(const iterator& one, const iterator& two) { return *one < *two; } private: container* cont; }; int main() { std::vector<int> v; adapter<std::vector<int>> a(&v); test(a, a); }
Output:
test iterator
http://ideone.com/wps2tZ