我如何才能部分特化枚举值的 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();
}
可以根据枚举值对模板进行专门化
#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();
}