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 enums, 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 enumes diferente entre sí y no está relacionado. Por ejemplo, uno enumtiene 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 toStringfunciones para estosenumclases, pero como son abstractas no pude instanciarlas directamente. Podría haber extendido cada clase que quería usar, pero finalmente decidí crear una templateclase, donde typenamesería cualquier estado concreto que enumme importara. Probablemente se pueda tener algún debate sobre esa decisión, pero sentí que eso era mucho menos trabajo que extender cada enumclase 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 enums no tenían ninguna relación, cada uno tenía su propiotoStringfunciones 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 enums. En realidad, cada enumclase 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 toStringmétodo en el archivo .cpp, y puedo usar el toStringmétodo de bibliotecas ya definido sin implementarlo yo mismo y sin extender cada enumclase que quiero usar.