Consider the below:
#include <type_traits>
template <typename E>
using is_scoped_enum = std::integral_constant<
bool,
std::is_enum_v<E> && !std::is_convertible_v<E, std::underlying_type_t<E>>
>;
template <typename E>
constexpr auto is_scoped_enum_v = is_scoped_enum<E>::value;void foo() {}
class Foo {};
enum Bar {};
enum class Baz {};
//static_assert(!is_scoped_enum_v<Foo>);
static_assert(!is_scoped_enum_v<Bar>);
static_assert(is_scoped_enum_v<Baz>);
The commented-out line breaks the build, because Foo
is not an enum and therefore does not have an underlying type. Of course, &&
(even though it's in a constant expression) doesn't short-circuit the need for std::underlying_type_t<E>
to be valid.
Do I need to create some monstrosity of tagged types and chained enable_if, or is there some trivial fix I'm missing?