2012-06-13 11 views
10

Esiste un modo per determinare il tipo di variabile passato a un modello e chiamare una funzione basata su se è unoo std::string ecc.?Eseguire diversi metodi basati sul tipo di variabile modello

Per esempio

template <class T> 
struct Jam 
{ 
    Jam(T *var) 
    { 
     if (typeid(var) == typeid(std::string*) 
       *var = "Hello!"; 
     else if (typeid(var) == typeid(int*) 
       *var = 25; 
    } 
}; 

Quando provo ad utilizzare quel codice, ottengo un errore invalid conversion from const char* to int. Sospetto che ciò avvenga perché il compilatore "espande" il modello in funzioni separate e quando ho specificato una nuova istanza della struttura throw Jam<std::string>(&setme); ha rilevato l'istruzione var* = 25 e si è rifiutata di compilare.

Esiste un modo corretto per farlo? Forse con le macro guardie? Grazie.

risposta

12

Utilizzare la funzione normale sovraccarico invece:

template <class T> 
struct Jam 
{ 
    Jam(std::string* var) 
    { 
     *var = "Hello!"; 
    } 

    Jam(int* var) 
    { 
     *var = 25; 
    } 
}; 

meno che non si desidera specializzarsi sul tipo T utilizzato per istanziare Jam. In tal caso, farei:

template<> 
struct Jam<std::string> 
{ 
    Jam(std::string* var) 
    { 
     *var = "Hello!"; 
    } 
}; 

template<> 
struct Jam<int> 
{ 
    Jam(int* var) 
    { 
     *var = 25; 
    } 
}; 


template<typename T> 
struct Jam 
{ 
    Jam(T* var) 
    { 
     // every other type 
    } 
}; 
+1

Esistono altre alternative, ad esempio la specializzazione solo del costruttore ('template <> Jam :: Jam (int * var) {}' esterno alla definizione della classe template) o più complesso SFINAE per abilitare/disabilitare il codice basato sugli argomenti del template ... Non penso che abbia senso in questo semplice problema, ma potrebbe avere senso quando queste semplici soluzioni diventano un peso (diciamo che il costruttore ha fatto 100 cose, solo una delle quali dipende dal tipo o che ci fossero altre 100 funzioni membro e che specializzasse l'intero tipo sarebbe costoso) –

6

Cercare "specializzazione modello parziale".

Prendere Jam() 's corpo fuori Jam {}:

template <class T> 
struct Jam 
{ 
    Jam(T *var); 
}; 

Ora scrivere due corpi:

Jam<int>::Jam(int *var) { 
    // stuff 
} 

Jam<std::string>::Jam(std::string *var) { 
    // stuff 
} 

(Attenzione:. Rusty C++ Ma è in generale come lo fai.)

Nuova domanda: se hai bisogno di digitazione anatra, perché stai usando il C++? Passerei a Ruby e salverò il C++ per i plug-in che richiedono velocità. Ma C++ continuerà a supportare progetti eleganti, con più lavoro!

+1

+1, anche se questo non è quello che viene comunemente indicato come specializzazione del modello * parziale *. La * parziale * in * specializzazione del modello parziale * di solito si riferisce al fatto che la specializzazione viene applicata solo a un sottoinsieme di tipi, rispetto a una * specializzazione completa * per la quale tutti gli argomenti del modello sono corretti. –

+2

Santo schifo. Conoscevo il C++? Spero che nulla sia esploso! – Phlip

+0

@Phlip Ho appena usato il tuo codice in un lancio dello space shuttle. Ha preso fuoco, ucciso tutti dentro e distrutto una città, tutto a causa del tuo codice. Molte grazie. – Andrew

Problemi correlati