Например, uninitialized_copy
определяется в стандарте как:
Эффекты:
for (; first! = last; + + результат, ++ первый) :: новый (static_cast
(& * результат)) typename iterator_traits :: value_type (* first);
Если понимать буквально, это требование для вызова оператора , (ForwardIterator, InputIterator)
. И на самом деле этот код печатает Hello world!
десять раз:
#include <memory>
#include <iterator>
#include <iostream>
using namespace std;
namespace N {
struct X : iterator<forward_iterator_tag, int> {
pointer _p;
X(pointer p) : _p(p) {}
X& operator++() { ++_p; return *this; }
X operator++(int) { X r(*this); ++_p; return r; }
reference operator*() const { return *_p; }
pointer operator->() const { return _p; }
};
bool operator==(X a, X b) { return a._p == b._p; }
bool operator!=(X a, X b) { return !(a == b); }
void operator,(X a, X b) { cout << "Hello world!\n"; }
}
int a[10], b[10];
int main()
{
using N::X;
uninitialized_copy(X(a), X(a+10), X(b));
}
Однако для большинства других алгоритмов стандарт дает описание в прозе. Например. для копии
нет необходимости вызывать операторы ,
. Но если я заменю
uninitialized_copy(X(a), X(a+10), X(b));
в приведенном выше коде на
copy(X(a), X(a+10), X(b));
, то Привет, мир!
по-прежнему печатается десять раз . Указанные результаты наблюдаются как в VS2005, так и в GCC 4.3.4. Однако, если я напишу вместо этого
mismatch(X(a), X(a+10), X(b));
, тогда VS2005 напечатает Hello world!
десять раз, но GCC - нет.
К сожалению, я не смог найти, где стандарт запрещает оператор,
перегрузку для типов итераторов. Напротив, он запрещает реализациям выполнять вызовы, как указано выше [global.functions]:
Если не указано иное, глобальные функции и функции, не являющиеся членами в стандартной библиотеке, не должны использовать функции из другого пространства имен, которые обнаруживаются с помощью зависимых от аргументов поиск имени (3.4.2).
Так кто из четырех виноват: MSVC, GCC, ISO или я? (Выберите один)
Отличный улов. Я считаю, что, по моему скромному мнению, комитет ИСО намеревался следовать §3.4.2. Предложенная семантика из uninitialized_copy
неверно истолкована так, как будто требует вызова запятой. И реализации не должны его использовать (я бы сообщил об ошибке в gcc btw).