2015-08-14 22 views
19

Considerate questo codice:iniettato nome della classe del compilatore discrepanza

struct foo{}; 

int main() { 
    foo::foo a; 
} 

mi aspetto che questo sia ben formato, dichiarando una variabile di tipo foo dalla norma in [class]/2 (N4140, sottolineatura mia) :

Una classe nomeviene inserito nel campo di applicazione in cui è dichiarata immediatamente dopo la classe nomeè visto. Il nome è inoltre inserito nell'ambito della classe stessa; questo è noto come nome-classe iniettata. Ai fini del controllo dell'accesso, il nome della classe immessa viene trattato come se fosse un nome membro pubblico.

clang 3.6.0 concorda con me, compilando il codice sopra senza avvertenze applicabili con -Wall -pedantic.

gcc 5.2.0 non è d'accordo, fornendo il seguente messaggio di errore:

main.cpp: In function 'int main()': 
main.cpp:5:5: error: 'foo::foo' names the constructor, not the type 
    foo::foo a; 

È possibile che questo detiene, non importa quanto sia profonda la nidificazione dei nomi delle classi iniettati, per esempio foo::foo::foo::foo.

Esiste una regola che impone che il costrutto venga interpretato come costruttore in quel contesto o si tratta di un bug gcc? O sto interpretando erroneamente la citazione degli standard?

+3

Clang ha un numero di bug con la sua gestione dei nomi delle classi immesse. Questo è uno di loro. –

+1

Molto strettamente correlati: http://stackoverflow.com/questions/29681449/program-being-compiled-differently-in-3-major-c-compilers-which-one-is-right –

risposta

10

Sembra che in questo caso sia clang. L'eccezione rilevante che cercavo è in [class.qual]/2:

2 In una ricerca in cui i nomi delle funzioni non vengono ignorati e il nested-nome-specificatore nomina un Classe C:

  • (2,1) se il nome specificato dopo il nested-nome-identificatore, quando alzò gli occhi in C, è la classe nome iniettato di C, o

  • [...]

il nome viene invece considerato per citarne costruttore di classe C.

Lo standard ha un (non normativo, ovviamente) esempio quasi equivalente:

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 
struct A::A a2;// object of type A 

Tuttavia, clang invia effettivamente una diagnostica corretta in questo caso:

error: qualified reference to 'A' is a constructor name rather than a type wherever a constructor can be declared 

Forse clang interpreta la riga In a lookup in which function names are not ignored come In a lookup in which a constructor declaration is valid, ma non sembra essere un'interpretazione corretta.

C'è un existing bug per questo nel bugzilla clang.

+1

Il mio rapporto è precedente ed è valido per gli scarti: https://llvm.org/bugs/show_bug.cgi?id=8263: p –

0

penso che questo è oggetto di language defect #147 che contiene questo esempio

class B { }; 
class A: public B { 
    A::B ab;  // B is the inherited injected B 
    A::A aa;  // Error: A::A is the constructor 
}; 

Almeno gcc sembra credere che. :-)

+0

Ah, quindi l'eccezione rilevante è [class.qual] /2.2 e questo è in realtà un bug in 'clang'? – TartanLlama

+0

Non ne sono sicuro. Questo esempio usa 'A :: A' all'interno di una classe, mentre il tuo uso è all'interno di' main'. Potrebbe esserci regole diverse lì. (Ho appena avuto un debole ricordo delle regole che sono state modificate e ho cercato il rapporto sui difetti). –

6

Pertinente, ma non una risposta: la gente del GCC ha discusso esattamente questo for years e ha calcolato che non dovrebbe essere accettato. Hanno esplicitamente reso questo un errore in GCC 4.5 e più recente - in 4.4.7 è stato accettato.

BTW: Probabilmente si desidera utilizzare Clang -Weverything anziché -Wall -pedantic quando si analizzano tali elementi.

Problemi correlati