La propagazione ‘typedef’ da base per la classe derivata per ‘modello’

Sto cercando di definire la classe di base, che contiene typedef solo.

template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
private:
    Vec_t v;  //fails - Vec_t is not recognized
};

Perché in B visualizzato un messaggio di errore che Vec_t non viene riconosciuto e ho bisogno di scrivere in modo esplicito?

typename A<T>::Vec_t v;
  • Esatto duplicato: stackoverflow.com/questions/1567730/…
  • Beh, non proprio un duplicato esatto dal post si parla si parla di un metodo, mentre questo si parla di un tipo.
  • typename Un::Vec_t v; è bene. Nessun bisogno di <T> c’
InformationsquelleAutor dimba | 2009-10-29

 

7 Replies
  1. 43

    Credo che questa domanda è duplicato, ma non riesco a trovarlo ora. C++ Standard dice che si dovrebbero qualificare completamente nome secondo 14.6.2/3:

    Nella definizione di un modello di classe o un membro di un modello di classe se una classe di base del modello di classe dipende dal modello-parametro, il classe di base ambito non esaminati nel nome non qualificato ricerca al momento della definizione del modello di classe o di un membro o durante un’istanza della classe di modello o di un membro.

    UPD: ho trovato duplicato infine: qui è.

    • Tra l’altro, è sempre il bug me che ho dovuto ri-typedef’ di tutto… non è piacevole, non è piacevole a tutti.
    • btw non hai bisogno di tutti gli argomenti di modello e di tutti, quando la qualificazione. A causa della iniettato nome di classe, basta scrivere typename B::Vec_t
    • Sto provando a fare come mi hai detto, ma io sono sempre errori, se io non specificare i parametri del modello per B. B non è una classe, spazio dei nomi, o enumerazione)
    • Io sto avendo il tuo stesso errore, ma solo su uno dei miei piattaforme, uno con un vecchio C++ standard. Mi chiedo se la necessità di qualificare completamente cambiato ad un certo punto?
  2. 35

    C’è qualcosa chiamato dipendente e tra loro nomi, nel caso di modelli.

    Se il nome dipende dal modello del parametro T la sua dipendente nome e gli altri, quelli che non dipendono da un parametro T sono indipendente nomi.

    Ecco la regola: il compilatore non
    guarda dipende classi di base (come
    A) quando guardando tra loro
    nomi (come Vec_t). Come risultato,
    il compilatore non sa che anche
    esistono figuriamoci sono tipi.

    Compilatore non può presumere che Vec_t è un tipo finché non conosce T perché C’è un potenziale di specializzazione di A<T> dove A<T>:: Vec_t è un membro dati

    La soluzione è di usare typename

     typename A<T>::Vec_t v;   good

    Mi consiglia di passare attraverso questo https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types.

    Vecchio (rotto) link: http://www.parashift.com/c++-faq-lite/modelli.html#faq-35.18

    • La tua è stata l’unica risposta che sembrava fornire una soluzione, oltre a una spiegazione. Grazie.
    • Il link è rotto
    • Ti offro un +1 se mi comunica che hai corretto il link.
    • Il link è stato aggiornato.
  3. 7

    Perché il compilatore non è certo che Vec_t nomi di un tipo. Per esempio, A<T> potrebbe essere specializzati per T=int per non hanno quel particolare typedef.

    • Per T una variabile di tipo A<T> è semplicemente inoltrare dichiarato, non ha una definizione. Solo A<t> dove t è un tipo (non di tipo variabile) può essere definito specializzandosi una definizione di un modello o di una esplicita di specializzazione). IOW, anche se si è rimosso il modello esplicito e parziale specializzazioni da C++ (ma non cambiare niente altro), ancora non sarebbe corretto.
  4. 3

    Per completezza, ecco come si potrebbe attenuare questo fastidio un po’, o:

    • ri-typedef quei tipi di classi derivate, o meglio – come
      metodi –
    • semplicemente importare i nomi nella classe derivata portata con un using declaration:

    template<typename T>
    class A
    {
    public:
        typedef std::vector<T> Vec_t;
    };
    
    
    template<typename T>
    class B : public A<T>
    {
    public:
        using typename A<T>::Vec_t;
        //.........
    
    private:
        Vec_t v;
    };

    Può essere utile se si dispone di più di un accenno al ereditato typedef nella classe derivata. Inoltre non c’è bisogno di aggiungere typename ogni volta con questo.

    • Si dispone di un errore di battitura. using typename A::Vec_t; dovrebbe essere using typename A<T>::Vec_t;
  5. 2

    È necessario qualificare in modo esplicito l’uso di Vec_t perché il compilatore non sa dove Vec_t viene.

    Non dare per scontato nulla sulla struttura di Un, dato che il modello di classe A possono essere specializzati. La specializzazione può includere un Vec_t che non è un typedef, o non può includere anche un membro Vec_t a tutti.

  6. 1

    Vec_t non è un dipendente di nome, e il compilatore ha bisogno di sapere di cosa si tratta senza istanziare tutti i modelli (classe base, in questo caso). È davvero diverso da:

    template <class T>
    class X
    {
        std::string s;
    }

    Qui il compilatore deve conoscere std::string, anche se X non è istanziato, dal momento che il nome non dipende dall’argomento del modello T (per quanto riguarda il compilatore può assumere).

    Di tutti i tipi in un modello di base di classe sembrano piuttosto inutili per l’uso nella classe derivata. I typedef sono utili per l’utente, tuttavia.

    • vuoi dire class X : T { qui?
  7. 1

    Questo concetto può essere associato come utilizziamo std::vector<T>. Per esempio, se abbiamo un std::vector<int> Foo. Ora, abbiamo deciso di usare altri tipi di membri, diciamo un iterator. In questo scenario si parla esplicitamente

    std::vector<int>::iterator foo_iterator;

    Allo stesso modo, nel tuo caso, in ordine al tipo di membro Vec_t di template <typename T> class A, è necessario dichiarare esplicitamente come

    A<T>::Vec_t v;
    OR
    A<int>::Vec_t int_type;

Lascia un commento