Ответ 1
Вот возможное решение:
#include <type_traits>
template<typename E>
using is_scoped_enum = std::integral_constant<
bool,
std::is_enum<E>::value && !std::is_convertible<E, int>::value>;
В решении используется различие в поведении между подсчетом и не областью перечисления, указанными в параграфе 7.2/9 стандарта С++ 11:
Значение перечислителя или объекта неперечисленного типа перечисления преобразуется в целое число путем цельной рекламы (4.5). [...] Обратите внимание, что это неявное преобразование enum to int не предоставляется для перечисления с областью. [...]
Вот демонстрация того, как вы его используете:
enum class E1 { };
enum E2 { };
struct X { };
int main()
{
// Will not fire
static_assert(is_scoped_enum<E1>::value, "Ouch!");
// Will fire
static_assert(is_scoped_enum<E2>::value, "Ouch!");
// Will fire
static_assert(is_scoped_enum<X>::value, "Ouch!");
}
А вот живой пример.
БЛАГОДАРНОСТЬ:
Спасибо Daniel Frey за то, что мой предыдущий подход будет работать только до тех пор, пока не будет определена пользовательская перегрузка operator +
.