实现是否应该防止逗号重载?

ybu*_*ill 26 c++ comma-operator language-lawyer

例如uninitialized_copy,在标准中定义为:

功效:

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

如果从字面上理解,这是要求打电话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));
}
Run Code Online (Sandbox Code Playgroud)

但是,对于大多数其他算法,该标准在散文中给出了描述.例如,copy因为不需要,调用运算符.但如果我改变

    uninitialized_copy(X(a), X(a+10), X(b));
Run Code Online (Sandbox Code Playgroud)

在上面的代码中

    copy(X(a), X(a+10), X(b));
Run Code Online (Sandbox Code Playgroud)

然后Hello world!静止印刷十次.VS2005和GCC 4.3.4都可以观察到上述结果.但是,如果我写的话

    mismatch(X(a), X(a+10), X(b));
Run Code Online (Sandbox Code Playgroud)

相反,然后VS2005打印Hello world!十次但GCC没打印.

不幸的是我无法找到标准禁止operator,迭代器类型重载的位置.相反,它禁止实现如上所述进行调用[global.functions]:

除非另有说明,否则标准库中的全局函数和非成员函数不得使用通过参数依赖名称查找(3.4.2)找到的另一个命名空间中的函数.

那么四方中谁是错的:MSVC,GCC,ISO还是我?(选一个)

Gio*_*hal 4

不错的收获。我认为以我的拙见,ISO 委员会的意图是应该遵循 \xc2\xa73.4.2。建议的语义uninitialized_copy被错误地解释为好像需要调用逗号。并且实现不应该使用它(顺便说一句,我会向 gcc 报告错误)。

\n

  • 这也是我的解读。逗号超载是疯狂的,我认为它只是忽略了我们委员会成员的注意。 (3认同)