2015-05-13 11 views
12

Il seguente codice viene compilato correttamente in g ++ e clang:E '"typename" permesso/richiesto in C++ 11 using-declaration?

template<typename T> 
struct foo 
{ 
    class iterator; 
    using bar = foo::iterator; 
}; 

int main() {} 

tuttavia MSVC 2013 dà i seguenti errori:

foo.cpp(9): error C2061: syntax error : identifier 'iterator' 
      foo.cpp(10) : see reference to class template instantiation 'foo<T>' being compiled 
foo.cpp(9): error C2238: unexpected token(s) preceding ';' 

Se cambio quella linea a:

using bar = typename foo::iterator; 

poi tutto tre compilatori lo compilano con successo. La versione originale è corretta? (Cioè è un baco MSVC, o un'estensione gcc/clang)

+1

Consentito, sì. Richiesto, no. 'foo :: iterator' assegna un nome all'attuale istanza. –

risposta

7

[temp.res]/p3:

Quando un qualificata id è inteso riferirsi ad un tipo che non è un membro della istanziazione corrente (14.6.2.1) e la sua nested-nome-specificatore riferisce ad un tipo dipendente, esso è preceduto dalla parola chiave typename, formando una typename-specificatore.

[temp.dep.type]/p1:

Un nome si riferisce al esemplificazione corrente se è

  • nella definizione di un modello di classe, un nidificato classe di un modello di classe, un membro di un modello di classe o un membro di una classe nidificata di un modello di classe, il nome di classe immessa (clausola 9) del modello classe o classe nidificata,
  • [...]

[temp.dep.type]/p4:

un nome è un membro della l'istanza corrente se è

  • Un nome non qualificato che, quando viene cercato, fa riferimento ad almeno un membro di una classe che rappresenta l'istanza corrente o una classe di base non dipendente. [Nota: ciò può verificarsi solo quando si cerca un nome in un ambito racchiuso dalla definizione di un modello di classe. - fine nota]
  • A qualificata-id in cui il nested-nome-specificatore riferisce alla istanziazione corso e che, quando guardato, si riferisce ad almeno una membro di una classe che è l'istanza corrente o una classe di base non dipendente. [Nota: se non viene rilevato alcun membro e l'istanza corrente ha qualsiasi classe di base dipendente, l'ID qualificato è un membro di una specializzazione sconosciuta; vedi sotto. - fine nota]
  • [...]

foo è l'istanza corrente. id qualificato in cui lo specificatore di nome nidificato (foo::) si riferisce all'istanziazione corrente e, quando viene cercato, "si riferisce ad almeno un membro di una classe che è l'istanza corrente o non -la sua classe base indipendente "; quindi è un membro dell'attuale istanza. Pertanto, [temp.res]/p3 non si applica e non è richiesto typename. Puoi ancora aggiungere uno - o semplicemente usare iterator non qualificato direttamente.

+0

Penso che questo lo faccia, l'hai trovato più veloce, +1 :) – vsoftco

2

dalla norma:

14.6.2.1 tipi dipendenti [temp.dep.type]

1 A nome si riferisce alla istanziazione corrente se è

__ nel definizione di un modello di classe, una classe nidificata di un modello di classe, un membro di un modello di classe o un membro di una classe nidificata di un modello di classe, il nome di classe immesso (Clausola 9) del modello di classe o nidificato classe,

Il nome foo si riferisce all'attuale istanza, è ovvio.

Poiché iterator è dichiarato come classe nidificata nella definizione del modello, iterator fa riferimento al nome nell'istanza corrente di foo. foo::iterator corrisponde a iterator.

using bar = foo::iterator; 

così come

using bar = iterator; 

dovrebbe funzionare.

Mi sembra che si sia imbattuto in un difetto MSVC.