在模板函数中,如果输入的类型是枚举 class,我该如何使用 std::underlying_type?
In a template function, How do I use std::underlying_type just if type of the input is enum class?
我有一段代码 returns 给定数字的某些位的值(我也将枚举 classes 算作一个数字,使用 static_cast) .
template<typename Type>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination)
{
if (offset + n> sizeof(Type) * 8)
return false;
Type bitmask = 0;
for (int i = 0; i < n; ++i)
bitmask |= (1 << i);
*destination = static_cast<Type>(input >> offset & bitmask);
return true;
}
此函数尝试 return 从 offset
开始的 input
的 n
位的值。它适用于整数类型,但当我尝试将它与枚举 classes 一起使用时,编译失败。我尝试使用 std::underlying_type 然后它适用于枚举 classes 但不适用于整数类型 :|。我怎样才能将它用于他们两个?我的意思是如果类型是枚举 class,我想将输入转换为它的 underlying_type
,做一些按位运算,然后将结果(使用 static_cast
)存储到目的地。但是对于没有 underlying_type.
的整数类型,不应进行这些转换
您可以使用 SFINAE 拆分枚举 class 实现:
template <typename Type,
typename = std::enable_if_t<std::is_enum_v<Type>>>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination) {
// enum-class implementation
}
和积分实现:
template <typename Type,
typename = std::enable_if_t<std::is_integral_v<Type>>>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination) {
// integral implementation
}
以上为C++17版本
对于 C++11,你会得到如下内容:
template <typename Type,
typename std::enable_if<std::is_enum<Type>::value>::type* = nullptr>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination) {
// enum-class implementation
}
template <typename Type,
typename std::enable_if<std::is_integral<Type>::value>::type* = nullptr>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination) {
// integral implementation
}
如果您经常需要它,可以在 std::underlying_type
上写一个适配器。像这样
namespace detail {
template<typename T, bool = std::is_enum<T>::value>
struct underlying_type { using type = T; };
template<typename T>
struct underlying_type<T, true> : ::std::underlying_type<T> {};
}
当您使用 detail::underlying_type<T>
时,替换也会出现在默认参数中。当提供的类型不是枚举时,主模板匹配参数(隐式),并且公开的 type
是 T
.
当提供的类型是枚举时(并且只有在那时),才会使用特化。它所做的一切都是为了标准特征。
我有一段代码 returns 给定数字的某些位的值(我也将枚举 classes 算作一个数字,使用 static_cast) .
template<typename Type>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination)
{
if (offset + n> sizeof(Type) * 8)
return false;
Type bitmask = 0;
for (int i = 0; i < n; ++i)
bitmask |= (1 << i);
*destination = static_cast<Type>(input >> offset & bitmask);
return true;
}
此函数尝试 return 从 offset
开始的 input
的 n
位的值。它适用于整数类型,但当我尝试将它与枚举 classes 一起使用时,编译失败。我尝试使用 std::underlying_type 然后它适用于枚举 classes 但不适用于整数类型 :|。我怎样才能将它用于他们两个?我的意思是如果类型是枚举 class,我想将输入转换为它的 underlying_type
,做一些按位运算,然后将结果(使用 static_cast
)存储到目的地。但是对于没有 underlying_type.
您可以使用 SFINAE 拆分枚举 class 实现:
template <typename Type,
typename = std::enable_if_t<std::is_enum_v<Type>>>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination) {
// enum-class implementation
}
和积分实现:
template <typename Type,
typename = std::enable_if_t<std::is_integral_v<Type>>>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination) {
// integral implementation
}
以上为C++17版本
对于 C++11,你会得到如下内容:
template <typename Type,
typename std::enable_if<std::is_enum<Type>::value>::type* = nullptr>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination) {
// enum-class implementation
}
template <typename Type,
typename std::enable_if<std::is_integral<Type>::value>::type* = nullptr>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination) {
// integral implementation
}
如果您经常需要它,可以在 std::underlying_type
上写一个适配器。像这样
namespace detail {
template<typename T, bool = std::is_enum<T>::value>
struct underlying_type { using type = T; };
template<typename T>
struct underlying_type<T, true> : ::std::underlying_type<T> {};
}
当您使用 detail::underlying_type<T>
时,替换也会出现在默认参数中。当提供的类型不是枚举时,主模板匹配参数(隐式),并且公开的 type
是 T
.
当提供的类型是枚举时(并且只有在那时),才会使用特化。它所做的一切都是为了标准特征。