villapx
villapx

Reputation: 1873

"names the constructor, not the type" in G++ 4.4.7

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.

Upvotes: 6

Views: 4770

Answers (2)

villapx
villapx

Reputation: 1873

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]

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726809

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.

Upvotes: 5

Related Questions