2012-01-03 30 views
26

Ví dụ uninitialized_copy được định nghĩa trong tiêu chuẩn như:Có nên bảo vệ thực thi chính nó chống lại quá tải dấu phẩy không?

Effects:

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

Nếu hiểu theo nghĩa đen, đây là một yêu cầu để gọi operator ,(ForwardIterator, InputIterator). Và trên thực tế, mã này in Hello world! mười lần:

#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)); 
} 

Tuy nhiên, đối với hầu hết các thuật toán khác, tiêu chuẩn cho mô tả bằng văn xuôi. Ví dụ. cho copy không yêu cầu nhà điều hành , được gọi. Nhưng nếu tôi thay đổi

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

trong đoạn code trên để

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

sau đó Hello world! được vẫn in gấp mười lần. Kết quả cho thấy có thể quan sát được ở cả hai, VS2005 và GCC 4.3.4. Tuy nhiên, nếu tôi viết

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

thay vào đó, sau đó VS2005 in Hello world! mười lần nhưng GCC thì không.

Rất tiếc, tôi không thể tìm thấy nơi tiêu chuẩn cấm quá tải operator, cho các loại trình lặp. Ngược lại, nó cấm triển khai thực hiện các cuộc gọi như trên [global.functions]:

Trừ khi có quy định khác, chức năng toàn cầu và không phải thành viên trong thư viện chuẩn sẽ không sử dụng các chức năng từ một không gian tên khác được tìm thấy qua tra cứu tên phụ thuộc vào đối số (3.4.2).

Vậy ai trong số bốn bên là sai: MSVC, GCC, ISO hoặc tôi? (Chọn một)

+3

Tôi nghĩ Visual C++, gcc và ISO đều sai: Visual C++ và gcc không nên sử dụng toán tử dấu phẩy và đặc tả (ISO) không được sử dụng dấu phẩy trong mã mẫu của nó. Tôi có thể sai; đó chỉ là suy nghĩ đầu tiên của tôi về vấn đề này. (Hãy xem xét việc mở một lỗi Visual C++ trên [Microsoft Connect] (https://connect.microsoft.com/VisualStudio); ít nhất cũng đáng để chú ý đến chúng.) –

+2

Cho rằng ngay cả một cái gì đó giống như 'Kích thước' là một loại templated , Tôi sẽ biến đối số trên đầu của nó và nói rằng tiêu chuẩn muốn * chính xác * những gì nó nói, và nếu bạn thấy lý do để cung cấp toán tử dấu phẩy tùy chỉnh, thì bạn được mời làm như vậy và bạn sẽ nhận được hành vi được chỉ định . –

+0

@JamesMcNellis KerrekSB: Cảm ơn bạn. Tôi hy vọng ai đó có thể tìm thấy một nơi mà nó được cho là hành vi không xác định, nếu không chúng tôi có ba báo cáo lỗi để mở. – ybungalobill

Trả lời

3

Rất thú vị. Tôi nghĩ theo ý kiến ​​khiêm tốn của tôi rằng ý định của ủy ban ISO là §3.4.2 nên được tuân theo. Các ngữ nghĩa được đề xuất của uninitialized_copy được hiểu sai như thể yêu cầu dấu phẩy được gọi. Và triển khai không nên sử dụng nó (tôi sẽ báo cáo lỗi cho gcc btw).

+3

Đây cũng là cách giải thích của tôi. Quá tải dấu phẩy là điên rồ và tôi nghĩ rằng nó chỉ trượt qua sự chú ý của các thành viên commitee của chúng tôi. –

+0

Vâng, kể từ đó tôi đã gửi PR và AFAIK họ đã sửa các tiêu chuẩn và triển khai phổ biến sau khi xóa các cuộc gọi toán tử không mong muốn. – ybungalobill

Các vấn đề liên quan