Могу ли я создать частичную шаблонную специализацию шаблона класса, соответствующего типам перечисления?

У меня есть шаблон функции, основанный на наборе явных специализаций шаблона класса, дающих такой синтаксис, как

abc.GetAs<DesiredType>("Name");

(где GetAs<t> это что-то вроде:

template<typename T>
T GetAs(wchar_t const* propName) const
{
typedef Converter<T> Converter;
auto thing = Get(propName);
return Converter::Convert(thing);
}

)

Я хотел бы иметь специализацию для DesiredType когда этот тип является перечислением, так что возвращаемый тип соответствует базовому типу перечисления (или enum class).

Это возможно, или клиенты просто должны сами указать базовый тип?


Я пытаюсь разрешить такой код:

enum class Example
{
One,
Two
}

int main()
{
foo_ipc_class ic(L"/// Construct me");
// Today, calls the primary template rather than an explicit
// specialization for an integral type.
Example ex = ic.GetAs<Example>(L"Property Name");
}

1

Решение

Поскольку невозможно частично специализировать шаблоны функций, вам придется изменить свою реализацию, чтобы использовать трюк «делегировать классу»:

#include <type_traits>

// Class to delegate to
template <typename T, bool isEnum = std::is_enum<T>::value>
struct GetAs_Class {
typedef your_return_type ReturnType;
static ReturnType GetAs(your_parameters) { your_code; }
};

// Partial specialisation
template <typename T>
struct GetAs_Class<T, true> {
typedef specialisation_return_type ReturnType;
static ReturnType GetAs(your_parameters) { specialisation_code; }
};// Your function now delegates to the class
template <typename T>
typename GetAs_Class<T>::ReturnType GetAs(your_parameters) {
return GetAs_Class<T>::GetAs(your_arguments);
}
2

Другие решения

Вы можете использовать SFINAE для включения / отключения перегрузок в зависимости от того, является ли параметр шаблона перечислением или нет. std::is_enum а также std::underlying_type пригодиться я написал GetAs как бесплатная функция для простоты:

#include <type_traits>
#include <iostream>

template<typename T>
struct identity {
typedef T type;
};

template<typename T>
typename std::enable_if<!std::is_enum<T>::value, identity<T>>::type::type
GetAs(wchar_t const*)
{
std::cout << "general\n";
// return something
}

template<typename T>
typename std::enable_if<std::is_enum<T>::value, std::underlying_type<T>>::type::type
GetAs(wchar_t const*)
{
std::cout << "enum\n";
// return something
}

enum class E : short {
};

int main()
{
GetAs<int>(L"hm");
GetAs<E>(L"hm");
}

Это довольно уродливо, но и делегирование классу для имитации частичной специализации шаблонов функций, IMO 🙂

1

По вопросам рекламы [email protected]