Это немного ОТ, но я подумал, что оставлю это здесь, на случай, если это поможет кому-то другому. Я искал в Google специализацию шаблонов, которая привела меня сюда, и хотя ответ @ maxim1000 верен и в конечном итоге помог мне разобраться в моих проблемах, я не думал, что это достаточно ясно.
Моя ситуация немного отличается (но достаточно похожа, чтобы оставить этот ответ, я думаю), чем у OP. По сути, я использую стороннюю библиотеку со всеми видами классов, которые определяют «типы статуса». В основе этих типов лежат простые enum
, но все классы наследуются от общего (абстрактного) родителя и предоставляют различные служебные функции, такие как перегрузка оператора и функция 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
класс был определен в собственном файле. Этот файл представляет файлы заголовков, которые предоставляются мне как часть библиотеки, которую я использую:
// 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
}
};
добавив эту строку, чтобы разделить следующий файл на другой блок кода:
// 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()
{
}
следующий файл
// 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_);
}
следующий файл
// 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;
}
и это выводит:
BEARS1
TIGERS3
Понятия не имею, является ли это идеальным решением моей проблемы, но у меня оно сработало. Теперь, независимо от того, сколько типов перечисления я в конечном итоге использую, все, что мне нужно сделать, это добавить несколько строк для метода toString
в файл .cpp, и я могу использовать уже определенный библиотекой метод toString
, не реализуя его самостоятельно и без расширение каждого enum
класса, который я хочу использовать.
person
yano
schedule
12.01.2019