std::underlying_type : SFINAE 是否防止未定义的行为?
std::underlying_type : Does SFINAE prevent undefined behavior?
std::underlying_type
在与非枚举类型一起使用时调用未定义的行为。
但是未定义的行为出现在哪里?
在此代码中:
template<typename E>
constexpr std::enable_if_t<std::is_enum<E>::value, std::underlying_type_t<E>> IntEnum(E e)
{
return static_cast<std::underlying_type_t<E>>(e);
}
我尝试使用 std::enable_if
来防止用户使用非枚举类型调用 IntEnum
。但是由于 enable_if
在决定是否可以调用函数之前被求值,它的模板参数也会被求值,包括 std::underlying_type_t<E>
。如果使用非枚举类型调用,那么这个 UB 是吗?我该如何更改它?
typename std::underlying_type<E>::type
甚至对非枚举类型进行评估(并且对 SFINAE 不友好)。
您可以使用一种间接方式来延迟评估并使 SFINAE 友好:
template<typename E>
constexpr
typename std::enable_if_t<std::is_enum<E>::value, std::underlying_type<E>>::type
IntEnum(E e)
{
return static_cast<std::underlying_type_t<E>>(e);
}
您可以使用 static_assert
来阻止编译
template<typename E>
constexpr auto IntEnum(E e)
{
static_assert(std::is_enum<E>::value, "E must be an enum");
return static_cast<std::underlying_type_t<E>>(e);
}
std::underlying_type
在与非枚举类型一起使用时调用未定义的行为。
但是未定义的行为出现在哪里?
在此代码中:
template<typename E>
constexpr std::enable_if_t<std::is_enum<E>::value, std::underlying_type_t<E>> IntEnum(E e)
{
return static_cast<std::underlying_type_t<E>>(e);
}
我尝试使用 std::enable_if
来防止用户使用非枚举类型调用 IntEnum
。但是由于 enable_if
在决定是否可以调用函数之前被求值,它的模板参数也会被求值,包括 std::underlying_type_t<E>
。如果使用非枚举类型调用,那么这个 UB 是吗?我该如何更改它?
typename std::underlying_type<E>::type
甚至对非枚举类型进行评估(并且对 SFINAE 不友好)。
您可以使用一种间接方式来延迟评估并使 SFINAE 友好:
template<typename E>
constexpr
typename std::enable_if_t<std::is_enum<E>::value, std::underlying_type<E>>::type
IntEnum(E e)
{
return static_cast<std::underlying_type_t<E>>(e);
}
您可以使用 static_assert
template<typename E>
constexpr auto IntEnum(E e)
{
static_assert(std::is_enum<E>::value, "E must be an enum");
return static_cast<std::underlying_type_t<E>>(e);
}