SFINAE not happening with std::underlying_type
std::underlying_type
is not SFINAE friendly. Attempting to access std::underlying_type<T>::type
for a non-enumeration type results in undefined behavior (often a hard error), not substitution failure.
You need to ascertain that the type at issue is an enumeration type first, before attempting to access its underlying type. Writing this in line would be something along the lines of typename std::enable_if<std::is_enum<H>::value, std::underlying_type<H>>::type::type
. Replacing the typename std::underlying_type<H>::type
in your return type with this hideous mess and you get an even more hideous mess that works :)
If you find yourself needing to do this often - or just don't want to write typename std::enable_if<std::is_same<typename std::enable_if<std::is_enum<H>::value, std::underlying_type<H>>::type::type, uint8_t>::value>::type
- you can write a SFINAE-friendly underlying_type
:
template<class T, bool = std::is_enum<T>::value>
struct safe_underlying_type : std::underlying_type<T> {};
template<class T>
struct safe_underlying_type<T, false /* is_enum */> {};