Ответ 1
Лучший способ реализовать это - использовать магию компилятора, и я считаю, что большинство реализаций делают это.
Например, здесь реализация libС++ для gcc >= 4.3 и любого компилятора, что __has_feature(is_enum)
1
template <class _Tp> struct _LIBCPP_VISIBLE is_enum
: public integral_constant<bool, __is_enum(_Tp)> {};
Для всех других компиляторов libС++ делает:
template <class _Tp> struct _LIBCPP_VISIBLE is_enum
: public integral_constant<bool, !is_void<_Tp>::value &&
!is_integral<_Tp>::value &&
!is_floating_point<_Tp>::value &&
!is_array<_Tp>::value &&
!is_pointer<_Tp>::value &&
!is_reference<_Tp>::value &&
!is_member_pointer<_Tp>::value &&
!is_union<_Tp>::value &&
!is_class<_Tp>::value &&
!is_function<_Tp>::value > {};
Некоторые из этих черт другого типа по-прежнему требуют магии компилятора. 2. is_union
. Однако это условие можно переписать так, что ему не нужна магия компилятора. Это можно сделать, заменив отдельные проверки для объединений и классов с помощью одной проверки для обоих, как указывает Йоханнес Шауб.
<суб > 1. Насколько я знаю, только clang реализует __has_feature
, к сожалению.
<Суб > 2. Интересно, что libС++ имеет версию is_union<T>
и is_class<T>
, которые не используют встроенные функции компилятора, но в результате они дают ошибочные результаты для типов union. Но их ошибочные результаты являются взаимодополняющими, поэтому реализация резервного копирования libС++ is_enum<T>
обеспечивает точные результаты.