2017-05-31 5 views
6

ich folgenden einfachen C++ Code habe:"Name des Konstruktor, nicht der Typ" in 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; 
} 

Zeile 11, wo die Definition von A ‚s operator=() Funktion an ist, ist falsch formatiert. ..oder zumindest glaube ich es. Wie erwartet, G ++ 4.7.4, sowie jede neuere Version von GCC, die ich versucht habe, führt den folgenden Fehler:

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

Merkwürdig ist, obwohl, G ++ 4.4.7 dieses Programm kompiliert ohne Warnungen erfolgreich, und druckt sogar 4 und 5, wie es zu erwarten wäre, wenn Zeile 11 korrekt geschrieben wäre (dh mit nur A& anstelle von A::A&).

Kann mir jemand helfen zu entziffern, was genau dort mit G ++ 4.4.7 vor sich geht? Ist das nur ein Fehler in dieser Version (wenn auch ein extrem alter, und schade uns, ihn immer noch zu benutzen)? Ich würde denken, der Standard würde explizit angeben, wie die operator=()-Funktion deklariert und definiert werden muss.

+1

Es ist keine Schande einen alten Compiler bei der Verwendung eines Legacy-Code-Basis zu unterstützen. Es ist verdammt schwer, Mittel zu bekommen, um die Werkzeugkette für ein funktionierendes Produkt zu verbessern. – user4581301

Antwort

5

Es gab eine related bug in g++. Es wurde in Version 4.5.0 behoben, 4.4.7 hat es also immer noch.

Hier ist der Fehler Beschreibung:

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 
} 

Obwohl die Symptome dieser Fehler nicht identisch sind, was Sie beschreiben, in beiden Fällen wird der Compiler behandelt A::A als Typnamen, wenn sie Namen tatsächlich einen Konstruktor. Ich bin ziemlich sicher, dass die beiden Verhaltensweisen die gleiche Ursache haben, was eine schlechte Implementierung der Bereichsauflösung vor Version 4.5.0 ist.

1

Erweiterung auf dasblinkenlight der correct answer --die C++ 03-Standard explizit verbietet seinen und meinen 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]

Verwandte Themen