I have the following simple C++ code:
#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;
}
Line 11, where the definition of A
's operator=()
function is at, is malformed...or, at least, I believe so. As expected, G++ 4.7.4, as well as every newer version of GCC that I've tried, throws the following error:
main.cpp:11:1: error: ‘A::A’ names the constructor, not the type
Oddly, though, G++ 4.4.7 compiles this program successfully, with no warnings, and even prints 4 and 5 as would be expected if line 11 were written correctly (i.e. with just A&
instead of A::A&
).
Can someone help me decipher what exactly is going on there with G++ 4.4.7? Is this just a bug in that release (albeit an extremely old one, and shame on us for still using it)? I'd think the standard would explicitly state how the operator=()
function must be declared and defined.
There was a related bug in g++. It was fixed in version 4.5.0, so 4.4.7 still has it.
Here is the bug description:
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 }
Although the symptoms of this bug are not identical to what you describe, in both cases the compiler treats A::A
as a type name, when it actually names a constructor. I am pretty certain that the two behaviors have the same root cause, which is poor implementation of scope resolution prior to version 4.5.0.
Expanding on dasblinkenlight's correct answer--the C++03 standard explicitly outlaws his and my code in [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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With