2015-11-06 3 views
7

Il seguente codicela ricerca del nome per typedef è buggata nel compilatore GNU?

#include <iostream> 

typedef double A; // a global typedef 

template <class Z> struct B // a template class... 
{ 
    A i{22.2}; // global typedef is in scope 
    typedef int A; // now a local typedef with the same name is introduced 
    A b{24}; // now the local typedef is in scope 
    Z c{36}; // a simple member of the template type 
}; 

template <class Z> struct C : B<Z> // a template struct inheriting B 
{ 
    A a; // global typedef is in scope because we are in a template struct 
    C() : a(2.2){ } 
}; 

int main() 
{ 
    C<int> c; 
    std::cout << "c's members: " 
      << c.a << ' ' 
      << c.i << ' ' 
      << c.b << ' ' 
      << c.c << std::endl; 
    std::cout << "their sizeof: " 
      << sizeof(c.a) << ' ' 
      << sizeof(c.i) << ' ' 
      << sizeof(c.b) << ' ' 
      << sizeof(c.c) << std::endl; 
} 

non è compilato da GNU-g++ 4.9.2 mentre è da clang 3.5.0 e si comporta come ho cercato di spiegare nei commenti incorporati e come può essere visto da l'output prodotto. Si tratta di un bug nel compilatore GNU? Il diagnostica dice che la linea typedef int A; nel campo d'applicazione della struct B

error: changes meaning of ‘A’ from ‘typedef double A’

noti che quando la gerarchia non è fatta di template (e naturalmente la dichiarazione Z c{36}; viene rimossa) la ricerca eseguita da clang nell'ambito di C (correttamente, come suppongo) trova lo typedef nell'ambito di B e considera il membro a di tipo int; poi emette un avvertimento circa il restringimento della inizializzazione double costante 2.2 ...

+0

Simile a [Interazione tra decltype e nome membro della classe che ombreggia un nome esterno] (http://stackoverflow.com/q/26681873/1708801) –

+0

È possibile formattare e abbreviare il codice in modo appropriato? – Columbo

+0

Cos'è la bizzarra indentazione? –

risposta

9

Dalla C++ progetto di norma (N4140)

§3.3.7 [basic.scope.class]

2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

A i{22.2} inizialmente si riferisce allo ::A globale. Tuttavia, dopo che lo B::A è stato dichiarato, se rivalutato nell'ambito di applicazione di B, fare riferimento a B::A. Questo viola la regola di cui sopra.

Per risolvere il problema, utilizzare il nome completo: ::A i{22.2}. ::A fa sempre riferimento allo A globale anche dopo che è stato dichiarato B::A, quindi non viola la regola.

Questo non è un bug in g ++; è solo un programma mal formato. Non è richiesto che il compilatore non ti dia una diagnosi per la violazione della regola, ma non è nemmeno necessario accettarlo.

Problemi correlati