Esto es un poco de OT, pero pensé en dejar esto aquí en caso de que ayude a alguien más. Estaba buscando en Google sobre la especialización de plantillas, lo que me llevó aquí, y aunque la respuesta de @ maxim1000 es correcta y, en última instancia, me ayudó a resolver mis problemas, no pensé que estuviera muy claro.
Mi situación es un poco diferente (pero lo suficientemente similar como para dejar esta respuesta, creo) que la de los OP. Básicamente, estoy usando una biblioteca de terceros con diferentes tipos de clases que definen "tipos de estado". El corazón de estos tipos son simplemente enum
s, pero todas las clases heredan de un padre común (abstracto) y proporcionan diferentes funciones de utilidad, como la sobrecarga del operador y una static toString(enum type)
función. Cada estado enum
es diferente entre sí y no está relacionado. Por ejemplo, uno enum
tiene los campos NORMAL, DEGRADED, INOPERABLE
, otro tiene AVAILBLE, PENDING, MISSING
, etc. Mi software se encarga de gestionar diferentes tipos de estados para diferentes componentes. Sucedió que quería utilizar las toString
funciones para estosenum
clases, pero como son abstractas no pude instanciarlas directamente. Podría haber extendido cada clase que quería usar, pero finalmente decidí crear una template
clase, donde typename
sería cualquier estado concreto que enum
me importara. Probablemente se pueda tener algún debate sobre esa decisión, pero sentí que eso era mucho menos trabajo que extender cada enum
clase abstracta con una personalizada e implementar las funciones abstractas. Y, por supuesto, en mi código, solo quería poder llamar .toString(enum type)
y hacer que imprima la representación de cadena de eso enum
. Dado que todos los enum
s no tenían ninguna relación, cada uno tenía su propiotoString
funciones que (después de algunas investigaciones que aprendí) tenían que llamarse usando la especialización de plantillas. Eso me trajo aquí. A continuación se muestra un MCVE de lo que tuve que hacer para que esto funcione correctamente. Y en realidad mi solución fue un poco diferente a la de @ maxim1000.
Este es un archivo de encabezado (muy simplificado) para el enum
s. En realidad, cada enum
clase se definió en su propio archivo. Este archivo representa los archivos de encabezado que se me proporcionan como parte de la biblioteca que estoy usando:
#include <string>
class Enum1
{
public:
enum EnumerationItem
{
BEARS1,
BEARS2,
BEARS3
};
static std::string toString(EnumerationItem e)
{
}
};
class Enum2
{
public:
enum EnumerationItem
{
TIGERS1,
TIGERS2,
TIGERS3
};
static std::string toString(EnumerationItem e)
{
}
};
agregando esta línea solo para separar el siguiente archivo en un bloque de código diferente:
#include <string>
template <typename T>
class TemplateExample
{
public:
TemplateExample(T t);
virtual ~TemplateExample();
std::string toString();
private:
T type_;
};
template <typename T>
TemplateExample<T>::TemplateExample(T t)
: type_(t)
{
}
template <typename T>
TemplateExample<T>::~TemplateExample()
{
}
siguiente archivo
#include <string>
#include "enums.h"
#include "TemplateExample.h"
template <>
std::string TemplateExample<Enum1::EnumerationItem>::toString()
{
return Enum1::toString(type_);
}
template <>
std::string TemplateExample<Enum2::EnumerationItem>::toString()
{
return Enum2::toString(type_);
}
siguiente archivo
#include <iostream>
#include "TemplateExample.h"
#include "enums.h"
int main()
{
TemplateExample<Enum1::EnumerationItem> t1(Enum1::EnumerationItem::BEARS1);
TemplateExample<Enum2::EnumerationItem> t2(Enum2::EnumerationItem::TIGERS3);
std::cout << t1.toString() << std::endl;
std::cout << t2.toString() << std::endl;
return 0;
}
y esto produce:
BEARS1
TIGERS3
No tengo idea de si esta es la solución ideal para resolver mi problema, pero funcionó para mí. Ahora, no importa cuántos tipos de enumeración termine usando, todo lo que tengo que hacer es agregar algunas líneas para el toString
método en el archivo .cpp, y puedo usar el toString
método de bibliotecas ya definido sin implementarlo yo mismo y sin extender cada enum
clase que quiero usar.