2009-06-14 8 views
20

Cuando estoy escribiendo una función en una clase de plantilla, ¿cómo puedo averiguar cuál es mi T?cómo consultar si (T == int) con la clase de plantilla

p. Ej.

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

¿Cómo puedo escribir la declaración if anterior para que funcione?

+0

Para que lo sepas, no hay prácticamente un consenso que ha aceptado la respuesta equivocada. Podría querer no aceptarlo y elegir otro. :) – jalf

+0

¡Gracias por todas sus aportaciones! Inicialmente, acepté la respuesta tipográfica porque la especialización parecía excesiva para la función simple que estaba escribiendo, pero más tarde terminé por hacer la función un poco más complicada, así que opté por la especialización de todos modos. – Meir

Respuesta

39

Algo como esto:

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

¿Podemos esperar que esto se optimice para que no tengamos un extra si en cada llamada? –

10

definirlo de forma explícita, por ejemplo .:

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

Eliminar 'plantilla ' y todo estará bien. – avakar

+0

gracias, por apuntar al error, no toqué C++ por un tiempo, no recuerdo cómo escribir especialización para plantillas. –

+7

No hay necesidad de una especialización de plantilla. Prefiere una sobrecarga sobre las especializaciones de plantilla de función. Esto último puede ser sorprendente a veces. (Hay un GOTW sobre el tema) – jalf

8

esta manera.

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

El compilador elegir esta función sobre la plantilla de función si pasa Vector<int>.

Editar: Encontré this article, que intenta explicar por qué preferir la sobrecarga a la especialización de plantillas.

+0

+1 porque es un gran artículo, pero si lee "Moral # 2" debería haberlo convertido en una especialización de plantilla de clase. No puedo creer que todos los demás simplemente ignoren este artículo o que no hayan leído "Exceptional C++ Style" – TimW

+0

+1: siempre prefiero la sobrecarga a la especialización. –

9

La forma más sencilla es proporcionar una especialización de plantilla:

#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

Tiene un punto y coma después de la segunda definición de plantilla de función. Además, ¿por qué prefieres la especialización de plantillas a una sobrecarga? – avakar

+0

Extraño: ¡ese código exacto compilado con g ++ sin errores! –

+6

Si está escribiendo una plantilla de función primaria que probablemente necesite especialización, prefiera escribirla como una plantilla de función única que nunca debe estar especializada o sobrecargada, y luego implementar la plantilla de función completamente como una simple transferencia a una plantilla de clase que contiene una función estática con la misma firma. Todos pueden especializarse tanto total como parcialmente, y sin afectar los resultados de la resolución de sobrecarga. – TimW

0

C++ plantillas no funcionan de esta manera. La idea general de las plantillas es expresar algo que es común para muchos tipos diferentes. Y en su caso, debe usar la especialización de plantilla.

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 
} 

Entonces compilador de C++ se llamar a esta función cuando se utiliza el tipo int y la aplicación general para cualquier otro tipo

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

TypeID nunca es una buena idea. Se basa en RTTI. Por cierto aquí es su respuesta: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.7

+0

¿Entonces RTTI está mal ahora? Y typeid es conocido en tiempo de compilación. – GManNickG

+0

¿cuál es el problema con RTTI? – Meir

+0

typeid es bastante lento. La especialización de plantillas se realiza en tiempo de compilación, mientras que typeid le cuesta tiempo de ejecución. Hacer su camino. Ref: http: //www.velocityreviews.com/forums/t279741-how-do-you-know-datatype-when-using-templates.html – siddhant3s

10

más simple, más solución general: Sólo tiene que escribir una vieja sobrecarga normal de la función:

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

Esto supone que los int y no int versiones Don' Tiene mucho código en común, ya que tiene que escribir dos implementaciones separadas.

SI desea utilizar una aplicación común de la función, con sólo una declaración if dentro de esa diferencia, utilice la aplicación de 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 
    } 
} 

En general, no utilice typeid si no lo hace Necesitar.

6

Como C++ 11 tenemos std::is_same:

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

Se implementó similar al rasgo sugerido TypeIsInt sugiere en las otras respuestas, pero con dos tipos que deben compararse.

1

Una solución es más:

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 
Cuestiones relacionadas