我如何才能部分特化枚举值的 class 模板?

How can I partially specialize a class template for enums values?

可以根据枚举值对模板进行专门化

#include <type_traits>

template<typename T, typename = void>
struct Specialize
{
};

template<typename T>
struct Specialize<T, typename std::enable_if<std::is_enum<T>::value>::type>
{
    void convert() { }
};

enum E
{
};

int main()
{
    Specialize<E> spec;
    spec.convert();
}

// My doubt: is below code valid? if not how to achieve this?

enum E
{
    E1,
    E2
};

int main()
{
    Specialize<E, E1> spec;
    spec.convert();
}

这是对以下问题的回答的后续问题。

How can I partially specialize a class template for ALL enums?

我已经从上面链接的问题的答案中复制粘贴了代码。

我的更改出现以下错误。

error: type/value mismatch at argument 2 in template parameter list for _template<class T, class>

// My doubt: is below code valid?

Specialize<E, E1> spec;

简答:否

长答案。

您已将 Specialized 定义为模板 struct 接收两个 类型 模板参数

template<typename T, typename = void>
struct Specialize
{
};

E 是一种类型,但 E1 是一个

if not how to achieve this?

如果您希望 struct/class 接收类型和该类型的值作为模板参数,从而启用 struct/class iff(当且仅当)类型是枚举,你必须添加 typename = void 作为第三个模板参数

template<typename T, T Val, typename = void>
struct Specialize
{
};

template<typename T, T Val>
struct Specialize<T, Val, typename std::enable_if<std::is_enum<T>::value>::type>
{
    void convert() { }
};

从 C++17 开始,您还可以使用 auto 作为模板值的类型并删除第一个模板参数

template<auto Val, typename = void>
struct Specialize
{
};

template<auto Val>
struct Specialize<Val, std::enable_if_t<std::is_enum_v<decltype(Val)>>>
{
    void convert() { }
};

-- 编辑--

OP 询问

how would we define the function "convert" outside the struct/class?

不幸的是,在这种情况下,我没有找到避免 std::enable_if 重复的方法

template <typename T, T Val>
struct Specialize<T, Val,
   typename std::enable_if<std::is_enum<T>::value>::type>
 { void convert(); };

template <typename T, T Val>
void Specialize<T, Val,
   typename std::enable_if<std::is_enum<T>::value>::type>::convert ()
 { };

您的编译器告诉您 Specialize<E, E1> spec; 无效。

您可以使用 std::integral_constant 将值包装在类型中。

template<typename T, T V>
struct Specialize<std::integral_constant<T, V>, typename std::enable_if<std::is_enum<T>::value>::type>
{
    void convert() { }
};

int main()
{
    Specialize<std::integral_constant<E, E1>> spec;
    spec.convert();
}