检查枚举 class 是否包含特定标识符
Check if enum class contains a specific identfier
我在 SO 上搜索了一下,很惊讶我没有找到任何类似的问题。很高兴收到任何提示,以防这已经得到解答。
我有一个代码库,其中定义了很多枚举 类。其中一些指定了一个 totalNum 常量,例如
enum class Foo : int
{
a,
b,
c,
totalNum
}
其他人没有这个喜欢
enum class Bar : bool
{
oneOption,
otherOption
}
然后我有一个功能基本上是这样的
template <class EnumClassType>
EnumClassType typeToEnum (typename std::underlying_type<EnumClassType>::type value)
{
// If you hit this assertion, the value is outside of the valid enum range
assert (isPositiveAndBelow (value, decltype (value) (EnumClassType::totalNum)));
return EnumClassType (value);
}
虽然这对于指定了 totalNum
的枚举有效并且有意义,但我想跳过这个断言以防枚举中没有这样的标识符。有什么办法吗?代码库目前使用 C++ 14,但由于即将进行的编译器更改,也欢迎使用 C++ 17 解决方案。
同时自己找到了答案,使用评论中提到的 @jfh 之类的方法。
首先,这是一种检查枚举 class 是否包含具有特定名称的标识符的方法
template <class EnumToTest>
class EnumConstantDefined_totalNum
{
private:
using Yes = int8_t;
using No = int16_t;
template <class E>
static Yes test (decltype (E::totalNum)*);
template <class E>
static No test (...);
public:
static constexpr bool value = sizeof (test<EnumToTest> (0)) == sizeof (Yes);
};
然后我们可以使用 SFINAE 为两种枚举指定两个重载。
template <class EnumType>
std::enable_if_t<EnumConstantDefined_totalNum<EnumType>::value, void> assertValueIsInRange (typename std::underlying_type<EnumType>::type value)
{
assert (isPositiveAndBelow (value, decltype (value) (EnumType::totalNum)));
}
template <class EnumType>
std::enable_if_t<! EnumConstantDefined_totalNum<EnumType>::value, void> assertValueIsInRange (typename std::underlying_type<EnumType>::type)
{
// do nothing
}
然后在实际的转换函数中使用这个断言函数
/**
Casts a value matching an enum class underlying type to an enum class constant and asserts that the
value is inside the valid enum range
*/
template <class EnumClassType>
EnumClassType typeToEnum (typename std::underlying_type<EnumClassType>::type value)
{
assertValueIsInRange<EnumClassType> (value);
return EnumClassType (value);
}
我在 SO 上搜索了一下,很惊讶我没有找到任何类似的问题。很高兴收到任何提示,以防这已经得到解答。
我有一个代码库,其中定义了很多枚举 类。其中一些指定了一个 totalNum 常量,例如
enum class Foo : int
{
a,
b,
c,
totalNum
}
其他人没有这个喜欢
enum class Bar : bool
{
oneOption,
otherOption
}
然后我有一个功能基本上是这样的
template <class EnumClassType>
EnumClassType typeToEnum (typename std::underlying_type<EnumClassType>::type value)
{
// If you hit this assertion, the value is outside of the valid enum range
assert (isPositiveAndBelow (value, decltype (value) (EnumClassType::totalNum)));
return EnumClassType (value);
}
虽然这对于指定了 totalNum
的枚举有效并且有意义,但我想跳过这个断言以防枚举中没有这样的标识符。有什么办法吗?代码库目前使用 C++ 14,但由于即将进行的编译器更改,也欢迎使用 C++ 17 解决方案。
同时自己找到了答案,使用评论中提到的 @jfh 之类的方法。
首先,这是一种检查枚举 class 是否包含具有特定名称的标识符的方法
template <class EnumToTest>
class EnumConstantDefined_totalNum
{
private:
using Yes = int8_t;
using No = int16_t;
template <class E>
static Yes test (decltype (E::totalNum)*);
template <class E>
static No test (...);
public:
static constexpr bool value = sizeof (test<EnumToTest> (0)) == sizeof (Yes);
};
然后我们可以使用 SFINAE 为两种枚举指定两个重载。
template <class EnumType>
std::enable_if_t<EnumConstantDefined_totalNum<EnumType>::value, void> assertValueIsInRange (typename std::underlying_type<EnumType>::type value)
{
assert (isPositiveAndBelow (value, decltype (value) (EnumType::totalNum)));
}
template <class EnumType>
std::enable_if_t<! EnumConstantDefined_totalNum<EnumType>::value, void> assertValueIsInRange (typename std::underlying_type<EnumType>::type)
{
// do nothing
}
然后在实际的转换函数中使用这个断言函数
/**
Casts a value matching an enum class underlying type to an enum class constant and asserts that the
value is inside the valid enum range
*/
template <class EnumClassType>
EnumClassType typeToEnum (typename std::underlying_type<EnumClassType>::type value)
{
assertValueIsInRange<EnumClassType> (value);
return EnumClassType (value);
}