2010-01-19 11 views
6

Ho codice che compila bene con VC9 (Microsoft Visual C++ 2008 SP1) ma non con GCC 4.2 (su Mac, se questo è importante). Se accumulo abbastanza qualificatori e parole chiave, posso forzarlo a lavorare in GCC, ma questo non sembra giusto.Sintassi C++ migliore per i typedef e le funzioni della classe base del modello?

Ecco un esempio di codice minima esporre i miei problemi:

template< typename N > 
struct B { 
    typedef N n_type;      // can derived class access typedef? 
    void foo() {}       // can derived class access function? 
}; 

template< typename N > 
struct D : public B<N> { 

    typedef B<N> b_type; 
    typedef typename b_type::n_type bn_type; 

    void f1(n_type) {}     // ERROR: 'n_type' has not been 
              // declared 

    void f2(typename B<N>::n_type) {} // OK, verbose 

    void f3(b_type::n_type) {}   // ERROR: 'struct B<N>::n_type' is 
              // not a type 

    void f4(typename b_type::n_type) {} // OK, verbose 

    void f5(bn_type) {}     // OK, verbose typedefs 

    void f6() { foo(); }     // ERROR: there are no arguments to 
              // 'foo' that depend on a template 
              // parameter, so a declaration of 
              // 'foo' must be available 

    void f7() { b_type::foo(); }   // OK, verbose 

}; 

sono io sbagliato aspettarsi una classe template derivata da un'altra classe template per essere in grado di utilizzare typedef e funzioni ereditate direttamente? C'è un modo migliore per farlo rispetto a quello che ho inventato finora?

+0

Qual è il punto di 'typedef N n_type'? puoi semplicemente usare 'N' direttamente – Trent

+3

typedef non è ereditato, Visual C++ non è conforme agli standard spesso. è possibile accedere alle funzioni ereditate utilizzando la risoluzione dell'ambito, IE base :: f o questo-> f. puoi anche usare "using base :: f" per portare la funzione in ambito locale. – Anycorn

+0

Funziona per me tranne per il caso di f3. –

risposta

9

Mi sbaglio se una classe template derivata da un'altra classe template sia in grado di utilizzare direttamente typedef e funzioni ereditate?

Sì, questo in genere non funziona come previsto. Le regole di ricerca del nome C++ specificano che un nome viene ricercato solo in classi di base basate su modelli se dipende da un parametro di modello (se si tratta di un "nome dipendente"). Se un nome non dipende da un parametro del modello non viene cercato lì. (Vedi anche this C++ FAQ Lite entry)

per richiamare le funzioni da una classe base dipende il modo più semplice è quello di utilizzare this->, dal momento che this è sempre implicitamente un nome dipendente:

void f6() { this->foo(); } 
+1

'questo' non aiuta con 'n_type', ma oh, va bene, è così. – ephemient

+1

Si potrebbe aggiungere 'typedef typename B :: n_type n_type;' per ottenere un tipo 'n_type' che si riferisce alla cosa corretta, ma forse è meglio essere espliciti lì. – sth

2

Non esiste il tipo n_type. C'è (o potrebbe essere) un tipo con quel nome che dipende da N. Quindi no, non puoi fare quello che vuoi.

3

Vedere C++ FAQ Lite § 35.18-20 e C++ Templates FAQ.

La ricerca del nome in due fasi è una parte difficile del C++ che molti compilatori (e programmatori) si sbagliano. Basti dire che GCC è più corretto (secondo la specifica C++) di MSVC è qui, e no, non c'è modo migliore di fare quello che vuoi.

Problemi correlati