Це трохи ЗЗ, але я думав залишити це тут на випадок, якщо це допоможе комусь іншому. Я гуглив про спеціалізацію шаблонів, яка привела мене сюди, і хоча відповідь @ 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
s були абсолютно не пов'язані між собою, у кожного з них були свої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
клас, який я хочу використовувати.