2016-01-24 34 views
5

Desidero inoltrare i modelli di variabile dichiarati in un file di intestazione e quindi disporre delle istanze effettive in un'unità di compilazione separata.Impossibile dichiarare una variabile modello senza definirla

Sono stato indotto a credere che i modelli di variabili C++ 14 funzionassero molto come le variabili di classe statica. Purtroppo questo sembra non essere il caso, e mi impedisce di inoltrare i miei template variabili.

template <typename T> struct Variable { 
    static int variable; 
}; 

template <typename T> 
extern int variable; 

int main() { 
    (void) Variable<char>::variable; 
    // (void) variable<char>;     // <-- line 10 
} 

template <> int Variable<char>::variable = 42; 
template <> int variable<char> = 23; 

L'esempio di codice sopra compila ed esegue come-è in GCC. Ma la riga 10 non commentante fornisce un errore in fase di compilazione:

specialization of 'variable<char>' after instantiation 
    template <> int variable<char> = 23; 
        ^
+1

Clang rifiuta entrambi. Questo è NDR malformato. L'istanziazione * esplicita * e la specializzazione * esplicita * sono animali completamente diversi. –

+0

Va bene - così come * do * realizzo ciò che voglio - ovvero dichiarare la variabile in un'intestazione ma definirla in un file .cpp? –

risposta

1

Penso che tu sia sulla strada giusta.

Il trucco è questo: in qualsiasi unità di traduzione, non creare un'istanza del modello prima della specializzazione.

Ad esempio:

// test.h 
#ifndef TEST_H 
#define TEST_H 

template <typename T> 
extern int variable; 

template <> extern int variable<char>; 
template <> extern int variable<int>; 

#endif // TEST_H 

Poi:

// test2.cpp 
#include "test.h" 

template <> int variable<char> = 23; 
template <> int variable<int> = 24; 

E infine:

// test.cpp 
#include "test.h" 
#include <iostream> 

int 
main() 
{ 
    std::cout << variable<char> << '\n'; 
    std::cout << variable<int> << '\n'; 
} 

per me questo uscite:

23 
24 

Aggiornamento

T.C. sottolinea nei commenti sotto che le specializzazioni devono essere dichiarate prima del primo utilizzo, quindi ho aggiornato "test.h" qui sopra per farlo.

Update 2

Sembra che ci sia qualche divergenza attuazione. clang sembra gestire questo bene:

template <typename T> 
extern int variable; 

template <> extern int variable<char>; 
template <> extern int variable<int>; 

#include <iostream> 

int 
main() 
{ 
    std::cout << variable<char> << '\n'; 
    std::cout << variable<int> << '\n'; 
} 

template <> int variable<char> = 23; 
template <> int variable<int> = 24; 

http://melpon.org/wandbox/permlink/DGYKvvoPbmRIHaFi

Tuttavia gcc restituisce un errore:

prog.cc:4:13: error: explicit template specialization cannot have a storage class 
template <> extern int variable<char>; 
      ^~~~~~ 

prog.cc:5:13: error: explicit template specialization cannot have a storage class 
template <> extern int variable<int>; 
      ^~~~~~ 

Ho cercato lo standard e la lista Nucleo Problemi, e non riesco a trovare qualsiasi cosa indichi che un compilatore o l'altro sia corretto. Se qualcuno vede tali prove, sono felice di includerlo in questa risposta.

+0

Questo è ancora [NDR non formato] (http://eel.is/c++draft/temp.expl.spec#6). Ciò che è necessario è una dichiarazione della specializzazione esplicita nell'intestazione, anche se non sono sicuro che l'OP significhi in realtà specializzarsi esplicitamente sul modello. –

+0

@ T.C .: Grazie, risolto. –

+0

Questo ancora non funziona - ecco il codice. https://github.com/rec/variable-template Non funzionerà affatto su clang; su g ++ 5.3.0, compila ma stampa 0 e 0; anche una build "unity" non viene compilata. –

Problemi correlati