Подтвердить что ты не робот

Должна ли реализация защититься от перегрузки запятой?

Например, uninitialized_copy определяется в стандарте как:

Эффекты:

for (; first != last; ++result, ++first)
  ::new (static_cast<void*>(&*result))
    typename iterator_traits<ForwardIterator>::value_type(*first);

Если понимать буквально, это требование для вызова operator ,(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));
}

Однако для большинства других алгоритмов стандарт дает описание в прозе. Например. для copy не требуется требование для оператора ,. Но если я изменю

    uninitialized_copy(X(a), X(a+10), X(b));

в приведенном выше коде на

    copy(X(a), X(a+10), X(b));

то Hello world! все еще печатается десять раз. Указанные результаты наблюдаются как в VS2005, так и в GCC 4.3.4. Однако, если я пишу

    mismatch(X(a), X(a+10), X(b));

вместо этого, тогда VS2005 печатает Hello world! десять раз, но GCC не делает.

К сожалению, я не мог найти, где стандарт запрещает перегрузку operator, для типов итераторов. Напротив, он запрещает реализациям делать вызовы, как указано выше [global.functions]:

Если не указано иное, глобальные и нечленовские функции в стандартной библиотеке не должны использовать функции из другого пространства имен, которые обнаруживаются путем поиска зависимых от аргументов (3.4.2).

Итак, кто из четырех сторон ошибается: MSVC, GCC, ISO или я? (Выберите один)

4b9b3361

Ответ 1

Хороший улов. Я считаю своим скромным мнением, что намерение комитета ИСО состояло в том, чтобы следовать п. 3.4.4. Предложенная семантика uninitialized_copy ошибочно интерпретируется так, как если бы она требовала вызова запятой. И реализация не должна его использовать (я бы сообщал об ошибке gcc btw).