Dies ist ein kleines OT, aber ich dachte, ich würde es hier lassen, falls es jemand anderem hilft. Ich habe über die Spezialisierung von Vorlagen gegoogelt, die mich hierher geführt hat, und obwohl die Antwort von @ maxim1000 richtig ist und mir letztendlich geholfen hat, meine Probleme herauszufinden, habe ich nicht gedacht, dass es sehr klar ist.
Meine Situation ist etwas anders (aber ähnlich genug, um diese Antwort zu hinterlassen, denke ich) als die der OPs. Grundsätzlich verwende ich eine Drittanbieter-Bibliothek mit allen Arten von Klassen, die "Statustypen" definieren. Das Herzstück dieser Typen sind einfach enum
s, aber die Klassen erben alle von einem gemeinsamen (abstrakten) übergeordneten Element und bieten verschiedene Dienstprogrammfunktionen, wie z. B. das Überladen von Operatoren und eine static toString(enum type)
Funktion. Jeder Status enum
unterscheidet sich voneinander und ist nicht miteinander verbunden. Zum Beispiel hat einer enum
die Felder NORMAL, DEGRADED, INOPERABLE
, ein anderer hat AVAILBLE, PENDING, MISSING
usw. Meine Software ist verantwortlich für die Verwaltung verschiedener Arten von Status für verschiedene Komponenten. Es entstand, dass ich die toString
Funktionen für diese nutzen wollteenum
Klassen, aber da sie abstrakt sind, konnte ich sie nicht direkt instanziieren. Ich hätte jede Klasse, die ich verwenden wollte, erweitern können, aber letztendlich habe ich beschlossen, eine template
Klasse zu erstellen , in der typename
es sich um einen konkreten Status handelt, der . Da alle s völlig unabhängig waren, hatten sie jeweils ihre eigenenenum
Ich habe mich darum gekümmert. Wahrscheinlich kann eine Debatte über diese Entscheidung geführt werden, aber ich hatte das Gefühl, dass dies viel weniger Arbeit war, als jede abstrakte enum
Klasse um eine eigene zu erweitern und die abstrakten Funktionen zu implementieren. Und natürlich wollte ich in meinem Code nur .toString(enum type)
die Zeichenfolgendarstellung dieser Funktionen aufrufen und ausdrucken können, die (nach einigen Recherchen) mithilfe der Vorlagenspezialisierung aufgerufen werden mussten. Das hat mich hierher geführt. Unten ist eine MCVE von dem, was ich tun musste, damit dies richtig funktioniert. Und tatsächlich war meine Lösung etwas anders als die von @ maxim1000.enum
enum
toString
Dies ist eine (stark vereinfachte) Header-Datei für die enum
s. In Wirklichkeit wurde jede enum
Klasse in einer eigenen Datei definiert. Diese Datei stellt die Header-Dateien dar, die mir als Teil der von mir verwendeten Bibliothek zur Verfügung gestellt werden:
// 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
}
};
Hinzufügen dieser Zeile, um die nächste Datei in einen anderen Codeblock zu unterteilen:
// 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()
{
}
nächste Datei
// 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_);
}
nächste Datei
// 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;
}
und dies gibt aus:
BEARS1
TIGERS3
Keine Ahnung, ob dies die ideale Lösung ist, um mein Problem zu lösen, aber es hat bei mir funktioniert. Unabhängig davon, wie viele Aufzählungstypen ich letztendlich verwende, muss ich nur ein paar Zeilen für die toString
Methode in die CPP-Datei einfügen, und ich kann die bereits definierte toString
Methode der Bibliothek verwenden, ohne sie selbst zu implementieren und ohne sie zu erweitern enum
Klasse, die ich verwenden möchte.