2017-05-31 32 views
6

Tôi có đơn giản C++ mã sau:"tên các nhà xây dựng, không phải là loại" trong G ++ 4.4.7

#include <cstdio> 

class A 
{ 
public: 
    A(int y) : x(y) {} 
    A& operator=(const A& rhs); 
    int x; 
}; 

A::A& A::operator=(const A& rhs) { this->x = rhs.x; return *this; } 

int main(int, char**) 
{ 
    A a1(5); 
    A a2(4); 

    printf("a2.x == %d\n", a2.x); 

    a2 = a1; 

    printf("a2.x == %d\n", a2.x); 

    return 0; 
} 

Dòng 11, nơi mà các định nghĩa của operator=() chức năng A 's là lúc, bị thay đổi. ..hoặc, ít nhất, tôi tin như vậy. Đúng như dự đoán, G ++ 4.7.4, cũng như tất cả các phiên bản mới hơn của GCC mà tôi đã cố gắng, ném các lỗi sau:

main.cpp:11:1: error: ‘A::A’ names the constructor, not the type 

Nhưng kỳ lạ, tuy nhiên, G ++ 4.4.7 biên dịch chương trình này thành công, không có cảnh báo và thậm chí in 4 và 5 như mong đợi nếu dòng 11 được viết chính xác (nghĩa là chỉ với A& thay vì A::A&).

Ai đó có thể giúp tôi giải mã chính xác những gì đang xảy ra ở đó với G ++ 4.4.7 không? Đây có phải chỉ là một lỗi trong bản phát hành đó (mặc dù là một bản phát hành cực kỳ cũ, và xấu hổ với chúng tôi vì vẫn còn sử dụng nó)? Tôi nghĩ rằng tiêu chuẩn sẽ nêu rõ cách chức năng operator=() phải được khai báo và xác định.

+1

Không có sự xấu hổ trong việc sử dụng một trình biên dịch cũ để hỗ trợ một codebase di sản. Thật khó để có được tài trợ để nâng cấp chuỗi công cụ cho một sản phẩm đang hoạt động. – user4581301

Trả lời

5

Có một số related bug in g++. Nó đã được sửa trong phiên bản 4.5.0, vì vậy 4.4.7 vẫn có nó.

Dưới đây là mô tả lỗi:

cc1plus does not implement the class name injection correctly. In particular the snipped below should be rejected on the basis that A::A does not name a type (it designates a constructor)

struct A { }; 

int main() 
{ 
    A::A a;  // should be an ERROR 
} 

Mặc dù các triệu chứng của lỗi này là không giống với những gì bạn mô tả, trong cả hai trường hợp, biên dịch xử lý A::A như một tên loại, khi nó thực sự tên một constructor. Tôi khá chắc chắn rằng hai hành vi có cùng một nguyên nhân gốc rễ, đó là thực hiện nghèo của độ phân giải phạm vi trước khi phiên bản 4.5.0.

1

Mở rộng trên dasblinkenlight của correct answer --Thư tiêu chuẩn C++ 03 rõ ràng Outlaws của mình và mã của tôi trong [class.qual]:

If the nested-name-specifier nominates a class C, and the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (clause 9), the name is instead considered to name the constructor of class C. Such a constructor name shall be used only in the declarator-id of a constructor definition that appears outside of the class definition. [Example:

struct A { A(); }; 
struct B: public A { B(); }; 

A::A() { } 
B::B() { } 

B::A ba; // object of type A 
A::A a; // error, A::A is not a type name 

—end example]

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