Проблема с вашими попытками состоит в том, что вы определяете одно и то же дважды, и хотя часть его использует enable_if
, что не делает все определение вложения отключенным, когда enable_if
isn не правда. то есть у вас есть два определения int_type::type
, даже если одно (или оба) из этих определений недействительны.
То, что вы ищете, это std::conditional
:
template< typename Type >
struct int_type {
using when_enum
= std::underlying_type<Type>;
using when_integral
= std::enable_if<std::is_integral<Type>::value, Type>;
using type
= typename std::conditional< std::is_enum<Type>::value,
when_enum, when_integral
>::type::type;
};
Или в C ++ 14 и более поздних версиях:
template< typename Type >
struct int_type {
using when_enum
= std::underlying_type<Type>;
using when_integral
= std::enable_if<std::is_integral<Type>::value, Type>;
using type
= typename std::conditional_t< std::is_enum<Type>::value,
when_enum, when_integral
>::type;
};
Но я думаю, что, вероятно, напишу его как шаблон псевдонима:
template< typename Type >
using int_type = std::conditional_t<
std::is_enum<Type>::value,
std::underlying_type<Type>,
std::enable_if<std::is_integral<Type>::value, Type>>;
И, возможно, еще более упростить его и сделать int_type<T>
псевдонимом для фактического типа, так что вам не нужно говорить typename int_type<T>::type
:
template< typename Type >
using int_type = typename std::conditional_t<
std::is_enum<Type>::value,
std::underlying_type<Type>,
std::enable_if<std::is_integral<Type>::value, Type>>::type;
(Примечание. В C ++ 17 вместо is_xxx<Type>::value
. Можно использовать std::is_enum_v<Type>
и std::is_integral_v
.)