可以创建匹配枚举类型的类模板的部分模板特化吗?

Can I create a partial template specialization of of a class template matching enumeration types?

本文关键字:创建 类型 枚举      更新时间:2023-10-16

我有一个函数模板,由一组类模板显式特化提供语法,如

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");
}

由于不可能部分专门化函数模板,因此您必须更改实现以使用"委托到类"技巧:

#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);
}

您可以使用SFINAE基于模板参数是否是enum来启用/禁用重载。std::is_enumstd::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 << "generaln";
    // 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 << "enumn";
    // return something
}
enum class E : short {
};
int main()
{
    GetAs<int>(L"hm");
    GetAs<E>(L"hm");
}

这很难看,但是委托给一个类来模仿函数模板的部分专门化也是如此,IMO:)