2009-06-14 13 views
20

Quando sto scrivendo una funzione in una classe template come posso scoprire qual è la mia T?come interrogare if (T == int) con la classe template

ad es.

template <typename T> 
ostream& operator << (ostream &out,Vector<T>& vec) 
{ 
if (typename T == int) 
} 

Come posso scrivere la dichiarazione sopra se così funziona?

+0

Solo così si sa, non c'è praticamente un consenso che hai accettato la risposta sbagliata. Potrebbe desiderare di non accettarlo e sceglierne un altro. :) – jalf

+0

Grazie per tutto il tuo contributo! Inizialmente ho accettato la risposta di tipo perché la specializzazione mi sembrava eccessiva per la semplice funzione che stavo scrivendo, ma più tardi ho finito per rendere la funzione un po 'più complicata, quindi ho optato comunque per la specializzazione. – Meir

risposta

39

Qualcosa di simile a questo:

template< class T > 
struct TypeIsInt 
{ 
    static const bool value = false; 
}; 

template<> 
struct TypeIsInt<int> 
{ 
    static const bool value = true; 
}; 

template <typename T> 
ostream& operator << (ostream &out,Vector<T>& vec) 
{ 
    if (TypeIsInt<T>::value) 
    // ... 
} 
+0

Possiamo aspettarci che questo sia ottimizzato in modo da non avere un extra se su ogni chiamata? –

10

definirlo in modo esplicito, ad es .:

template <> 
ostream& operator << (ostream &out,Vector<int>& vec) 
{ 
} 
+0

Rimuovi 'template ' e andrà bene. – avakar

+0

grazie, per indicare l'errore, non ho toccato C++ per un po ', non ricordavo come scrivere la specializzazione per i modelli. –

+7

Non è necessaria la specializzazione del modello. Preferisci una specializzazione sui modelli Function sovraccarico. Quest'ultimo può essere sorprendente a volte. (C'è un GOTW in materia) – jalf

8

questo modo.

ostream & operator << (ostream &out, Vector<int> const & vec) 
{ 
    // ... 
} 

Il compilatore sceglierà questa funzione sul modello di funzione se si passa Vector<int>.

Modifica: ho trovato this article, che tenta di spiegare perché preferire l'overloading alla specializzazione del modello.

+0

+1 perché è un ottimo articolo, ma se leggi "Morale # 2" dovresti averlo reso una specializzazione di modello di classe. Non posso credere che tutti gli altri ignorino questo articolo o non abbiano letto "Eccezionale stile C++" – TimW

+0

+1: preferisco sempre il sovraccarico sulla specializzazione. –

9

Il modo più semplice è quello di fornire un modello di specializzazione:

#include <iostream> 
#include <vector> 
using namespace std; 

template <typename T> struct A { 
}; 

template <typename T > 
ostream & operator <<(ostream & os, A<T> & a ) { 
    return os << "not an int" << endl; 
} 


template <> 
ostream & operator <<(ostream & os, A<int> & a ) { 
    return os << "an int" << endl; 
} 

int main() { 
    A <double> ad; 
    cout << ad; 
    A <int> ai; 
    cout << ai; 
} 
+1

Hai un punto e virgola dopo la definizione del secondo modello di funzione. Inoltre, perché preferisci la specializzazione dei modelli a un sovraccarico? – avakar

+0

Strano - quel codice esatto compilato con g ++ senza errori! –

+6

Se si sta scrivendo un modello di funzione primaria che probabilmente richiede specializzazione, è preferibile scriverlo come un modello a funzione singola che non dovrebbe mai essere specializzato o sovraccarico, quindi implementare il modello funzione interamente come un semplice handoff a un modello di classe contenente una funzione statica con la stessa firma. Tutti possono specializzarsi in modo completo e parziale, senza influire sui risultati della risoluzione del sovraccarico. – TimW

0

C++ modelli non funzionano in questo modo. L'idea generale di modelli è qualcosa di espressivo che è comune per molti tipi diversi. E nel tuo caso dovresti usare la specializzazione del modello.

template<class T> ostream& operator<< (ostream& out, const vector<T>& v) 
{ 
    // your general code for all type 
} 
// specialized template 
template<> ostream& operator<< <int>(ostream& out, const vector<int>& vec) 
{ 
    // your specific to iny type code goes here 
} 

Poi compilatore C++ chiamerà questa funzione quando si utilizza tipo int e l'attuazione generale per qualsiasi altro tipo

std::vector<int> f(5, 5); 
std::cout << f; 
6

TypeID non è mai una buona idea. Si basa su RTTI. Tra l'altro qui è la vostra risposta: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.7

+0

Quindi RTTI non è buono ora? E typeid è noto in fase di compilazione. – GManNickG

+0

qual è il problema con RTTI? – Meir

+0

typeid è abbastanza lento. La specializzazione dei modelli viene eseguita al momento della compilazione, mentre la costellazione ti costa runtime. Fai la tua strada. Rif: http: //www.velocityreviews.com/forums/t279741-how-do-you-know-datatype-when-using-templates.html – siddhant3s

10

più semplice, soluzione più generale: Basta scrivere la pianura vecchio overload della funzione:

ostream& operator << (ostream &out,Vector<int>& vec) 
{ 
// Your int-specific implementation goes here 
} 

Questo presuppone che i int e non int versioni don' Ho molto codice in comune, dato che devi scrivere due implementazioni separate.

SE si desidera utilizzare un'implementazione comune della funzione, con solo un if istruzione all'interno che si differenzia, usare l'esecuzione di Charles Bailey:

template< class T > 
struct TypeIsInt 
{ 
    static const bool value = false; 
}; 

template<> 
struct TypeIsInt<int> 
{ 
    static const bool value = true; 
}; 

template <typename T> 
ostream& operator << (ostream &out,Vector<T>& vec) 
{ 
    if (TypeIsInt<T>::value) { 
     // your int-specific code here 
    } 
} 

In generale, non utilizzare typeid se non lo fai bisogno di.

6

Dal C++ 11 abbiamo std::is_same:

if (std::is_same<T, int>::value) ... 

E 'implementato simile al tratto suggerito TypeIsInt suggerito in altre risposte, ma con due tipi da confrontare.

1

più Una soluzione è:

if(std::is_same<T, int>::value) 
    //It is int 
if (std::is_same<T, double>::value) 
    //It is double 
if (std::is_same<T, long double>::value) 
    //It is long double 
Problemi correlati