2013-01-04 13 views
5

dire che mi dichiaro una classe template A in a.hPerché posizione esplicita modello di istanza importa

#include <iostream> 

template<bool b> 
class A { 
public: 
    void print(std::ostream& out); 
}; 

e definire il metodo di stampa a a.cpp (con instatiation esplicita true e false)

#include "a.h" 

template<bool b> 
void A<b>::print(std::ostream& out) { 
    out << "A" << b; 
} 

template class A<true>; 
template class A<false>; 

Un esempio di programma principale principale in main.cpp potrebbe essere

#include "a.h" 

int main() { 
    A<true> a; 
    a.print(std::cout); 
} 

Il piccolo progetto sopra compila bene.

Domanda: Se metto le istanze esplicite di sopra della definizione del metodo print (in a.cpp), il codice non viene compilato più, con il solito errore di undefined reference to A<true>::print(...).

#include "a.h" 

template class A<true>; 
template class A<false>; 

template<bool b> 
void A<b>::print(std::ostream& out) { 
    out << "A" << b; 
} 

Perché è questo il caso?

Edit: Makefile per compilare

main : main.o a.o 
    g++ main.o a.o -o main 

main.o : main.cpp 
    g++ -c main.cpp 

a.o : a.cpp 
    g++ -c a.cpp 
+1

funziona anche su VS2012. – billz

+0

Ho fatto e ho cambiato l'ordine come Dejan menzionato – billz

+1

@jogojapan - +1. Ho cancellato il mio commento che diceva che si compila con clang32 e gcc48. Si stava compilando bene con qualsiasi compilatore e con qualsiasi ordine se i contenuti di tre file sono stati tagliati e incollati in un unico file - come ho fatto inizialmente per il mio test. Dopo che Dejan ha pubblicato Makefile, sono riuscito a riprodurre l'errore con clang e gcc di qualsiasi versione. –

risposta

8

Non penso che ci sia una buona spiegazione naturale per il motivo per cui è così. Chiaramente, il compilatore potrebbe vedere la definizione della funzione membro anche se è fornita dopo l'istanza esplicita – perché si trova nello stesso file.

Tuttavia, i compilatori non sono tenuti a questo; è infatti esplicitamente vietato dalla norma:

(§14.7.2/9) Una definizione esplicita di istanza che i nomi di un modello di classe di specializzazione un'istanza in modo esplicito la specializzazione modello di classe ed è una definizione esplicita di istanza dei soli membri che sono stati definiti nel punto di istanziazione.

immagino le ragioni di questo sono i seguenti:

  • ci potrebbero essere diverse specializzazioni esplicite distinti per alcune delle funzioni membro in seguito a l'unità di traduzione; ha senso, anche nell'interesse del programmatore, avere una regola esplicita su quale di questi verrà istanziato;

  • Quando un modello è implicitamente istanziato, solo le specializzazioni definite prima del punto di creazione dell'istanza vengono prese in considerazione; quindi la regola è la stessa per le istanze implicite ed esplicite.

1
template class A<true>; 
template class A<false>; 

Il stesso motivo per cui è in genere prevede che il codice del modello è definita nell'intestazione stesso. Per eseguire un'istanza esplicita, è necessario (il compilatore) essere in grado di visualizzare l'intera definizione della classe modello, che non è possibile dal tuo main.cpp.

Tuttavia, a.cpp ha accesso a tutta la definizione della classe (qui il metodo di stampa), quindi l'istanziazione esplicita funziona lì.

+0

Non sono sicuro di aver capito la tua risposta. La mia confusione è con il riordino delle istruzioni all'interno di 'a.cpp'. –

+0

@ DejanJovanović: ah la mia incomprensione, quindi sembra una cosa del compilatore, funziona su VS2010 –

Problemi correlati