27

例如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 还是我?(选一个)

4

1 回答 1

4

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

于 2012-01-03T23:32:34.013 回答