2013-10-28 5 views
10

I (vagamente) noto che un modello non viene istanziato se è nonutilizzato. Ad esempio, il codice seguente verrà compilato correttamente anche se T::type non ha senso quando T = int.L'impatto del virtuale sull'utilizzo del modello membro della classe

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 
}; 

A<int> a; //ok 

Compila perché f() non è usato, quindi non viene creata un'istanza — così la validità di T::type rimane incontrollato. Non importa se qualche altra membro funzione g() chiama f().

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 

    void g() { f(); } //Is f() still unused? 
}; 

A<int> a; //ok 

Questo anche compile fines. Ma qui mi rendo conto della vaghezza nella mia comprensione della definizione di "use". Chiedo:

  • f() è ancora inutilizzato? Come esattamente?

Posso chiaramente vederlo utilizzato all'interno di g(). Ma poi ho pensato che dal momento che g() non viene utilizzato, non viene utilizzato anche f(), dal punto di vista dell'istanziazione. Sembra abbastanza ragionevole. finora.

Tuttavia, se aggiungo virtual parola chiave per g(), non compilare:

template<typename T> 
struct A 
{ 
    void f() { using type = typename T::type; } 

    virtual void g() { f(); } //Now f() is used? How exactly? 
}; 

A<int> a; //error 

Essa si traduce in compilation error perché ora tenta di creare un'istanza f(). Non capisco questo comportamento.

Qualcuno potrebbe spiegarlo? Soprattutto l'impatto della parola chiave virtual sulla definizione di "uso" del modello membro della classe.

+1

Se ricordo correttamente, 'virtual' forza l'istanziazione della funzione membro perché è praticamente impossibile valutare staticamente se questa funzione verrà utilizzata o meno. In pratica, stai chiedendo di creare una v-table piena di puntatori alle funzioni ... quindi la funzione deve esistere in modo tale che possiamo prendere un puntatore. –

+0

Il modello di struct viene istanziato solo quando lo si utilizza. È o l'intera struttura o nulla. Non ha nulla a che fare con gof. – Sarien

+1

@Sarien: lo fa, le funzioni membro di una classe template vengono istanziate solo se usate ODR. –

risposta

8

Un rapido sguardo a 3,2 [basic.def.odr] rendimenti:

3/[...] Una funzione membro virtuale è ODR-utilizzato se non è pura. [...]

E ho anche trovato su 14.7.1 [temp.inst]:

10/Un'implementazione non deve implicitamente un'istanza di un modello di funzione, un modello di membro, un non- funzione membro virtuale, una classe membro o un membro dati statici di un modello di classe che non richiede l'istanziazione. Non è specificato se un'implementazione implichi o meno una funzione di membro virtuale di un modello di classe o meno, se la funzione membro virtuale non venga istanziata in altro modo. (sottolineatura mia)

Quindi ... direi che è probabile che un metodo virtual sarà sempre un'istanza.

In termini pragmatici, mi aspetto che un compilatore crei un'istanza della tabella virtuale di una classe template quando crea un'istanza della classe; e quindi istanzia immediatamente tutte le funzioni membro virtual di questa classe (quindi può fare riferimento a quelle dalla tabella virtuale).