Domanda

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

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 ricevo un errore che Vec_t non viene riconosciuto e devo scriverlo esplicitamente?

typename A<T>::Vec_t v;
È stato utile?

Soluzione

Credo che questa domanda sia duplicata, ma non riesco a trovarla ora. Lo standard C ++ afferma che è necessario qualificare completamente il nome in base al 14.6.2 / 3:

  

Nella definizione di un modello di classe o di un membro di un modello di classe, se una classe di base del modello di classe dipende da un parametro modello, l'ambito della classe di base non viene esaminato durante la ricerca del nome non qualificato nel punto di definizione del modello di classe o del membro o durante un'istanza del modello di classe o del membro.

UPD: ho finalmente trovato un duplicato: eccolo .

Altri suggerimenti

Esiste qualcosa chiamato nomi dipendenti e non dipendenti in caso di modelli.

Se il nome dipende dal parametro T del modello, il suo dipendente nome e altri quelli che non dipendono dal parametro T sono indipendenti .

  

Ecco la regola: il compilatore no   cerca in classi di base dipendenti (come   A) quando si guarda in modo indipendente   nomi (come Vec_t). Di conseguenza,   il compilatore non sa nemmeno che   esistono e tanto meno sono tipi.

Il compilatore non può presumere che Vec_t sia un tipo fino a quando non conosce T perché esiste una potenziale specializzazione di A<T> dove A<T>:: Vec_t è a è un membro di dati

Quindi la soluzione è usare typename

 typename A<T>::Vec_t v;  ← good

Ti consiglio di consultare questo https://isocpp.org/ wiki / faq / templates # nondependent-nome-lookup-tipi .

Vecchio link (non funzionante): http: // www. parashift.com/c++-faq-lite/templates.html#faq-35.18

Perché il compilatore non è sicuro che Vec_t nomina un tipo. Ad esempio, A<T> potrebbe essere specializzato per T=int in non avere quel particolare typedef.

Per completezza, ecco come è possibile mitigare un po 'questo fastidio:

  • riscrive quei tipi in classi derivate, o meglio - come con metodi -
  • importa semplicemente quei nomi nell'ambito della classe derivata 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 hai più di una menzione dell'ereditato typedef nella classe derivata. Inoltre non è necessario aggiungere typename ogni volta con questo.

Devi qualificare esplicitamente l'uso di Vec_t perché il compilatore non sa da dove proviene <=>.

Non può assumere nulla sulla struttura di A, poiché il modello di classe A può essere specializzato. La specializzazione può includere un <=> che non è un typedef o potrebbe non includere affatto un membro <=>.

Vec_t non è un nome dipendente e il compilatore deve sapere di cosa si tratta senza creare un'istanza di modelli (in questo caso la classe base). Non è davvero diverso da:

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

Anche qui il compilatore deve sapere di std :: string anche se X non è istanziato, poiché il nome non dipende dall'argomento template T (per quanto il compilatore possa supporre).

Tutto sommato, i typedef in una classe base del modello sembrano piuttosto inutili per l'uso nella classe derivata. I typedef sono comunque utili per l'utente.

Questo concetto può essere associato al modo in cui usiamo std::vector<T>. Ad esempio, se abbiamo un std::vector<int> Foo. Ora, decidiamo di utilizzare uno qualsiasi dei suoi tipi di membri, diciamo un iterator. In questo scenario menzioniamo esplicitamente

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

Analogamente nel tuo caso, per utilizzare un tipo di membro pubblico Vec_t di template <typename T> class A, devi dichiararlo esplicitamente come

A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top