template - ¿Cómo hacer un tipo de tipo si no es así en la plantilla de c++?
template typename t c++ (6)
¿Qué tal una simple sobrecarga?
// in the private section
static int& do_increase(int& i){ return ++i; }
static char& do_increase(char& c){
if(c >= ''a'' && c <= ''z'')
c += ''A'' - ''a'';
return c;
}
template<class U>
static U& do_increase(U& arg){
// some default implementation?
return arg;
}
(Tenga en cuenta que el estándar no garantiza un orden alfabético para los valores numéricos de un char
).
Luego simplemente llame a en increase
como return do_increase(element);
.
// template specialization
#include <iostream>
using namespace std;
// class template:
template <class T>
class mycontainer {
T element;
public:
mycontainer (T arg) {element=arg;}
T increase () {
//if(T.type==int)//how to do this or something similar?
//do this if an int
return ++element;
//if(T.type==char)
//if ((element>=''a'')&&(element<=''z''))
//element+=''A''-''a'';
//return element;
}
};
Sé cómo escribir una especialización de plantilla y hacer una definición de clase completa por separado solo para el tipo char.
Pero, ¿y si quisiera manejar todo en un solo bloque de código?
¿Cómo puedo verificar si T es un int o un char?
Esto es similar a la respuesta de Andy Prowls, pero todo se hace en tiempo de compilación utilizando una clase de ayudante mínima con especialización.
En este caso, tiene un ayudante que realmente hace la especialización pero también podría hacer que la clase ayudante solo tome un bool y luego use algo como std::is_same<T, int>::value
para pasar ese valor como un parámetro de plantilla.
template <typename T>
struct myContainerHelper;
{
// General Case
static inline T increase(T element)
{
return ++element;
}
};
template <>
struct myContainerHelper<char>
{
// Specific case
static inline char increase(char element)
{
if ((element>=''a'')&&(element<=''z'')) element+=''A''-''a'';
return element;
}
};
template <class T>
class mycontainer
{
T element;
public:
mycontainer (T arg) {element=arg;}
T increase ()
{
return myContainerHelper<T>::increase(element);
}
};
Esto le permite especializar solo la función única en lugar de toda la clase. Estoy usando una clase de plantilla con estadísticas porque estoy acostumbrado a las limitaciones de VS2012 con especialización parcial para las plantillas de funciones.
La solución habitual aquí es reenviar a una función sobrecargada con un argumento adicional. Algo como:
template <typename T>
class MyContainer
{
T increase( int const* ) { /* special treatment for int */ }
T increase( ... ) { /* default treatment */ }
public:
T increase()
{
return increase( (T const*)0 );
}
};
Con un poco de imaginación, puede llegar a todo tipo de distinciones. Si realiza las funciones de destino con las plantillas de argumentos adicionales, incluso puede aprovechar SFINAE: diseñar el argumento ficticio para que falle la sustitución del tipo de plantilla, y la función no se considerará en el conjunto de sobrecarga. Y dado que todas las funciones están en línea, es probable que no haya una sobrecarga adicional, siempre que optimice.
Lo que quieres es probablemente algo como un tiempo de compilación si . Desafortunadamente, C ++ 11 no tiene soporte nativo para tal construcción de lenguaje.
Sin embargo, si solo quiere comprobar si dos tipos son idénticos, el rasgo de tipo std::is_same<>
debería ayudarlo:
#include <type_traits> // <== INCLUDE THIS STANDARD HEADER
// class template:
template <class T>
class mycontainer
{
T element;
public:
mycontainer (T arg) {element=arg;}
T increase ()
{
if (std::is_same<T, int>::value) // <== THIS IS HOW YOU WOULD USE IT
return ++element;
if (std::is_same<T, char>::value) // <== THIS IS HOW YOU WOULD USE IT
{
if ((element>=''a'') && (element<=''z''))
element+=''A''-''a'';
}
return element;
}
};
Sin embargo, tenga en cuenta que la condición se evalúa en tiempo de ejecución , aunque el valor de is_same<T, int>::value
se conoce en tiempo de compilación. Esto significa que tanto la rama true
como la false
de la sentencia if
deben compilarse .
Por ejemplo, lo siguiente no sería legal:
if (std::is_same<T, int>::value)
{
cout << element;
}
else if (std::is_same<T, my_class>::value)
{
element->print(); // Would not compile when T is int!
}
Además, como Xeo señaló correctamente en los comentarios, es probable que el compilador emita advertencias porque su condición siempre se evaluará como true
o false
, por lo que una de las dos ramas contendrá código inalcanzable.
Podrías usar typeid
:
if (typeid(T) == typeid(int))
O podrías usar el rasgo de tipo std::is_same
:
if (std::is_same<T, int>::value)
Puede utilizar la especialización de plantillas explícitas.
#include <iostream>
using namespace std;
// class template:
template <class T>
class mycontainer {
T element;
public:
mycontainer (T arg) {element=arg;}
T increase();
};
template<>
int mycontainer<int>::increase(){
return ++element;
}
template<>
char mycontainer<char>::increase(){
if ((element>=''a'')&&(element<=''z''))
element+=''A''-''a'';
return element;
}
int main(){
mycontainer<int> A(10);
mycontainer<char> B(''x'');
cout << A.increase() <<endl;
cout << B.increase() <<endl;
return 0;
}