C'est un peu OT, mais j'ai pensé laisser ça ici au cas où cela aiderait quelqu'un d'autre. Je cherchais sur la spécialisation des modèles sur Google, ce qui m'a conduit ici, et bien que la réponse de @ maxim1000 soit correcte et m'a finalement aidé à résoudre mes problèmes, je ne pensais pas que c'était très clair.
Ma situation est un peu différente (mais assez similaire pour laisser cette réponse je pense) que celle de l'OP. Fondamentalement, j'utilise une bibliothèque tierce avec toutes sortes de classes qui définissent des "types d'état". Le cœur de ces types est simplement enum
s, mais les classes héritent toutes d'un parent commun (abstrait) et fournissent différentes fonctions d'utilité, telles que la surcharge d'opérateurs et une static toString(enum type)
fonction. Chaque statut enum
est différent les uns des autres et sans rapport. Par exemple, l'un enum
a les champs NORMAL, DEGRADED, INOPERABLE
, un autre a AVAILBLE, PENDING, MISSING
, etc. Mon logiciel est en charge de gérer différents types de statuts pour différents composants. Il est arrivé que je voulais utiliser les toString
fonctions pour cesenum
classes, mais comme elles sont abstraites, je ne peux pas les instancier directement. J'aurais pu étendre chaque classe que je voulais utiliser, mais j'ai finalement décidé de créer une template
classe, où le typename
serait le statut concret qui me tenait à enum
cœur. Probablement un débat peut avoir lieu à propos de cette décision, mais j'ai senti que c'était beaucoup moins de travail que d'étendre chaque enum
classe abstraite avec une classe personnalisée et d'implémenter les fonctions abstraites. Et bien sûr, dans mon code, je voulais juste pouvoir appeler .toString(enum type)
et lui faire imprimer la représentation sous forme de chaîne de cela enum
. Puisque tous les enum
s étaient totalement sans rapport, ils avaient chacun leur propretoString
fonctions qui (après quelques recherches que j'ai apprises) ont dû être appelées en utilisant la spécialisation des modèles. Cela m'a conduit ici. Vous trouverez ci-dessous un MCVE de ce que je devais faire pour que cela fonctionne correctement. Et en fait, ma solution était un peu différente de celle de @ maxim1000.
Il s'agit d'un fichier d'en-tête (grandement simplifié) pour le enum
s. En réalité, chaque enum
classe était définie dans son propre fichier. Ce fichier représente les fichiers d'en-tête qui me sont fournis dans le cadre de la bibliothèque que j'utilise:
// file enums.h
#include <string>
class Enum1
{
public:
enum EnumerationItem
{
BEARS1,
BEARS2,
BEARS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
class Enum2
{
public:
enum EnumerationItem
{
TIGERS1,
TIGERS2,
TIGERS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
en ajoutant cette ligne juste pour séparer le fichier suivant dans un bloc de code différent:
// file TemplateExample.h
#include <string>
template <typename T>
class TemplateExample
{
public:
TemplateExample(T t);
virtual ~TemplateExample();
// this is the function I was most concerned about. Unlike @maxim1000's
// answer where (s)he declared it outside the class with full template
// parameters, I was able to keep mine declared in the class just like
// this
std::string toString();
private:
T type_;
};
template <typename T>
TemplateExample<T>::TemplateExample(T t)
: type_(t)
{
}
template <typename T>
TemplateExample<T>::~TemplateExample()
{
}
fichier suivant
// file TemplateExample.cpp
#include <string>
#include "enums.h"
#include "TemplateExample.h"
// for each enum type, I specify a different toString method, and the
// correct one gets called when I call it on that type.
template <>
std::string TemplateExample<Enum1::EnumerationItem>::toString()
{
return Enum1::toString(type_);
}
template <>
std::string TemplateExample<Enum2::EnumerationItem>::toString()
{
return Enum2::toString(type_);
}
fichier suivant
// and finally, main.cpp
#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;
}
et cela produit:
BEARS1
TIGERS3
Je ne sais pas si c'est la solution idéale pour résoudre mon problème, mais cela a fonctionné pour moi. Maintenant, quel que soit le nombre de types d'énumérations que je toString
finis par utiliser, tout ce que j'ai à faire est d'ajouter quelques lignes pour la méthode dans le fichier .cpp, et je peux utiliser la toString
méthode déjà définie des bibliothèques sans l'implémenter moi-même et sans étendre chacune enum
classe que je veux utiliser.