They do introduce 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 additional overloads
template<class container, class funct>
void do_something(container, funct);
the compiler will have some trouble figuring out what do_something(x, y)
means. If x
and y
are of the same type
, it will match both iterator = type
and container = type, funct = type
.*)
C++11 tried to solve this with "concepts" that could recognize the difference between a container and an iterator. However, these "concepts" turned out to be too complicated to make it into the standard, so neither did these overloads.
*) compilers disagree here, the Comeau compiler claims that it is ambiguous, g++ 4.5 and MSVC 10 calls the first function.
After an extremely long discussion in the comments, here is one example where it doesn't work as expected - using a container adapter that can also double as a predicate.
#include <iostream>
#include <vector>
template<class iterator>
void test(iterator, iterator)
{
std::cout << "test iterator
";
}
template<class iterator, class predicate>
void test(iterator, iterator, predicate)
{
std::cout << "test iterator, predicate
";
}
template<class container, class predicate>
void test(const container& cont, predicate compare)
{
std::cout << "test container, predicate
";
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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…