2012-06-13 22 views
10

¿Hay alguna forma de determinar el tipo de variable pasada a una plantilla y llamar a una función según si es int o std::string, etc.?Realizar diferentes métodos basados ​​en la variable de plantilla tipo

Por ejemplo

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

Cuando trato de usar el código, me sale un error invalid conversion from const char* to int. Sospecho que esto se debe a que el compilador "expande" la plantilla en funciones separadas y cuando especifiqué una nueva instancia de la estructura throw Jam<std::string>(&setme); detectó la declaración var* = 25 y se negó a compilar.

¿Hay una forma adecuada de hacerlo? Tal vez con macro guardias? Gracias.

Respuesta

12

Uso función regular la sobrecarga en su lugar:

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

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

a menos que quiera especializarse en el tipo T utilizado para crear instancias de Jam. En ese caso, usted haría:

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

Existen otras alternativas, como por ejemplo, especializar solo el constructor ('template <> Jam :: Jam (int * var) {}' fuera de la definición de clase de plantilla) o SFINAE más complejo para activar/desactivar código basado en los argumentos de la plantilla ... No creo que tenga sentido en este simple problema, pero podría tener sentido cuando estas soluciones simples se conviertan en una carga (digamos que el constructor hizo 100 cosas, de las cuales solo una depende del tipo , o que había otras 100 funciones miembro y la especialización del tipo completo sería costoso) –

6

Busque "especialización de plantilla parcial".

Take Jam() del cuerpo 's de Jam {}:

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

Ahora escribe dos cuerpos:

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

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

(Advertencia:. Oxidada C++, pero eso es por lo general la forma de hacerlo.)

Nueva pregunta: Si necesita pato-tipado, ¿por qué está usando C++ en absoluto? Cambiaría a Ruby y guardaría el C++ para los complementos que necesitan velocidad. ¡Pero C++ seguirá soportando diseños elegantes, con más trabajo!

+1

+1, aunque esto no es lo que comúnmente se conoce como especialización de plantilla * partial *. La especialización de plantilla * parcial * en * normalmente se refiere al hecho de que la especialización se aplica solo a un subconjunto de tipos, en comparación con una * especialización completa * para la cual se fijan todos los argumentos de la plantilla. –

+2

Holy crap. Sabía C++? Espero que nada explote! – Phlip

+0

@Phlip Acabo de utilizar su código en el lanzamiento de un transbordador espacial. Se incendió, mató a todos los que estaban dentro y destruyó una ciudad, todo por tu código. Muchas gracias. – Andrew

Cuestiones relacionadas