2009-07-01 17 views
9

Qualcuno sa perché le dichiarazioni di utilizzo non sembrano funzionare per l'importazione di nomi di tipi da classi di base dipendenti? Funzionano per variabili membro e funzioni, ma almeno in GCC 4.3, sembrano essere ignorati per i tipi.Accesso ai tipi da classi di base dipendenti

template <class T> 
struct Base 
{ 
    typedef T value_type; 
}; 

template <class T> 
struct Derived : Base<T> 
{ 
    // Version 1: error on conforming compilers 
    value_type get(); 

    // Version 2: OK, but unwieldy for repeated references 
    typename Base<T>::value_type get(); 

    // Version 3: OK, but unwieldy for many types or deep inheritance 
    typedef typename Base<T>::value_type value_type; 
    value_type get(); 

    // Version 4: why doesn't this work? 
    using typename Base<T>::value_type; 
    value_type get(); // GCC: `value_type' is not a type 
}; 

Ho una classe di base con una serie di typedef allocator in stile che mi piacerebbe ereditare tutto diversi livelli di eredità. La soluzione migliore che ho trovato finora è la versione 3, ma sono curioso del perché la versione 4 non sembra funzionare. GCC accetta la dichiarazione d'uso, ma sembra ignorarlo.

Ho controllato lo standard C++, C++ Prog. Lang. 3a ed. [Stroustrup] e C++ Templates [Vandevoorde, Josuttis], ma nessuno sembra indicare se l'uso di dichiarazioni possa essere applicato a tipi di classi di base dipendenti.

Nel caso in cui aiuti a vedere un altro esempio, here is the same question being asked, ma non risponde realmente, sulla mailing list GCC. Il richiedente indica che ha visto "usare typename" altrove, ma che GCC non sembra supportarlo. Non ho un altro compilatore conforme disponibile per testarlo.

+0

Invia un codice che dovrebbe essere compilato (secondo te) per i compilatori conformi, ma non lo fa. E pubblica come stai usando il modello. –

+0

Credo che tutte le informazioni pertinenti siano sopra. Le versioni 1-4 funzionano su MSVC 9, che ha una risoluzione del nome a uno stadio non conforme (ad esempio al momento dell'istanziazione). Solo le versioni 2 e 3 funzionano su GCC 4.3. Non conosco alcun motivo per cui la Versione 4 dovrebbe essere non valida, ma GCC non lo accetterà. Per quanto riguarda l'utilizzo, non importa quanto sia stato istanziato. Sto solo cercando di ottenere la dichiarazione del modello da compilare. Il codice sopra riportato è una semplificazione di un adattatore contenitore molto più complesso. –

+0

Quando postate il codice qui, non aspettatevi che le persone debbano modificarlo per farlo compilare. –

risposta

8

Come Richard Corden fa notare, la questione è stata affrontata nel C++ Standard Core Language Defect Reports dopo lo standard 2003 è stato ratificato: How do the keywords typename/template interact with using-declarations?

Proposta di delibera (aprile 2003 rivisto ottobre 2003):

Aggiungi un nuovo paragrafo in fondo a 7.3.3 [namespace.udecl]:

Se una dichiarazione di utilizzo utilizza il nome di parola chiave e specifica unNome dipendente(14.7.2 [temp.dep]), il nome introdotto dalla dichiarazione d'uso viene considerato come un typedef-name (7.1.3 [dcl.typedef]).

Questo testo non sembra comparire nello standard Seconda edizione dal 15 ottobre, 2003.

GCC non ha ancora attuare questa risoluzione, come spiegato in bug 14258:

- ----- Commento # 3 di Giovanni Bajo 2004-02-27 12:47 [risposta] ------- Il problema è che il nostro USING_DECL non registra il "typename", ovvero lo fatto che è un tipo che è importato attraverso di esso. Funzionava così grazie al nome implicito del tipo estensione, credo.

Duplicato bug 21484 indica che "using typename" funziona su compilatori Comeau e Intel. Poiché MSVC considera tutti i nomi come dipendenti, il costrutto non è necessario (ma consentito) per quel compilatore.


Fixed in GCC 4.7 il 13 dicembre 2011!

+1

Questo è un bug, ma solo relativamente di recente, quindi penso che non dovresti essere troppo duro con gcc. Il seguente problema principale evidenzia la modifica della dicitura "http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#11". Questo è entrato nello standard C++ '03. –

+0

Grazie, Richard, questo è il link esatto che stavo cercando! –

-1

Non è stato incluso un identificatore di accesso (pubblico/protetto/privato) nel modello per Base prima di dichiarare il typedef per Base :: value_type. Di conseguenza, il valore predefinito è privato e non è accessibile nelle classi derivate da Base.

+5

Ha definito i suoi tipi Base/Derivati ​​come strutture, quindi i loro membri sono * pubblici * per impostazione predefinita, non privati. – luke

Problemi correlati