Это немного ОТ, но я подумал, что оставлю это здесь, на случай, если это поможет кому-то другому. Я искал в гугле специализацию шаблонов, которая привела меня сюда, и хотя ответ @ maxim1000 правильный и в конечном итоге помог мне разобраться в моих проблемах, я не думал, что это достаточно ясно.
Моя ситуация немного отличается (но достаточно похожа, чтобы оставить этот ответ, я думаю), чем у OP. По сути, я использую стороннюю библиотеку со всеми видами классов, которые определяют «типы статуса». Сердцем этих типов являются просто enum
s, но все классы наследуются от общего (абстрактного) родителя и предоставляют различные служебные функции, такие как перегрузка оператора и static toString(enum type)
функция. Каждый статус enum
отличается друг от друга и не связан. Например, у одного enum
есть поля NORMAL, DEGRADED, INOPERABLE
, у другого - AVAILBLE, PENDING, MISSING
и т. Д. Моя программа отвечает за управление разными типами статусов для разных компонентов. Оказалось, что я хотел использовать toString
функции для этихenum
классы, но поскольку они абстрактны, я не мог создать их экземпляры напрямую. Я мог бы расширить каждый класс, который хотел бы использовать, но в конечном итоге я решил создать template
класс, в котором typename
будет любой конкретный статус, который enum
меня заботит. Вероятно, это решение можно обсудить, но я чувствовал, что это было намного меньше работы, чем расширение каждого абстрактного enum
класса моим собственным и реализация абстрактных функций. И, конечно же, в моем коде я просто хотел иметь возможность вызывать .toString(enum type)
и печатать строковое представление этого enum
. Поскольку все они enum
были совершенно не связаны между собой, у каждого из них были своиtoString
функции, которые (после некоторых исследований, которые я узнал) должны были вызываться с использованием специализации шаблонов. Это привело меня сюда. Ниже приводится MCVE того, что мне пришлось сделать, чтобы это работало правильно. И на самом деле мое решение немного отличалось от @ maxim1000.
Это (значительно упрощенный) заголовочный файл для enum
s. На самом деле каждый enum
класс был определен в собственном файле. Этот файл представляет файлы заголовков, которые предоставляются мне как часть библиотеки, которую я использую:
#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)
{
}
};
добавив эту строку, чтобы разделить следующий файл на другой блок кода:
#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()
{
}
следующий файл
#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_);
}
следующий файл
#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;
}
и это выводит:
BEARS1
TIGERS3
Понятия не имею, является ли это идеальным решением моей проблемы, но у меня оно сработало. Теперь, независимо от того, сколько типов перечисления я в конечном итоге использую, все, что мне нужно сделать, это добавить несколько строк для toString
метода в файл .cpp, и я могу использовать метод, уже определенный в библиотеках, toString
не реализуя его самостоятельно и не расширяя каждый enum
класс, который я хочу использовать.