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

Например, 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 или я? (Выберите один)

26
задан ybungalobill 3 January 2012 в 22:56
поделиться

1 ответ

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

3
ответ дан 28 November 2019 в 17:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: