Они вводят неоднозначность для многих алгоритмов. Многие
выглядят как
template
void do_something(iterator, iterator);
template
void do_something(iterator, iterator, funct);
Если вы добавите дополнительные перегрузки
template
void do_something(container, funct);
, компилятор будет иметь некоторые проблемы с выяснением того, что означает do_something(x, y)
. Если x
и y
имеют одинаковый type
, он будет соответствовать как iterator = type
, так и container = type, funct = type
. *)
C ++ 11 попытался решить эту проблему с помощью " концепций ", которые могли бы распознать разницу между контейнером и итератором. Однако эти «концепции» оказались слишком сложными, чтобы превратить их в стандарт, поэтому и эти перегрузки.
*) компиляторы не согласны с этим, компилятор Comeau утверждает, что он неоднозначен, g ++ 4.5 и MSVC 10 вызывает первую функцию.
После чрезвычайно продолжительного обсуждения комментариев, вот один пример, когда он не работает должным образом - с помощью адаптера контейнера который также может удваиваться как предикат.
#include
#include
template
void test(iterator, iterator)
{
std::cout << "test iterator\n";
}
template
void test(iterator, iterator, predicate)
{
std::cout << "test iterator, predicate\n";
}
template
void test(const container& cont, predicate compare)
{
std::cout << "test container, predicate\n";
test(cont.begin(), cont.end(), compare);
}
template
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 v;
adapter> a(&v);
test(a, a);
}
Выход:
test iterator
blockquote>