Просто чтобы подшутить над вариативными шаблонами, я предлагаю пару решений.
Оба они основаны на функции constexpr
, которая сообщает, находится ли значение в списке переменных шаблона (как value_in_list
в ответе aschepler, но это также работает в C ++ 14)
template <typename T, T ... ts>
constexpr bool isInList (T const & t0)
{
using unused = bool[];
bool ret { false };
(void)unused { false, ret |= t0 == ts... };
return ret;
}
Первый из них очень похож на решение Ашеплера (+1) и не использует специализацию шаблонов.
template <std::underlying_type_t<PositiveDigit> I>
struct IsNum1
{
static constexpr bool aPrimeDigit
= isInList<PositiveDigit, PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven>
(static_cast<PositiveDigit>(I));
};
Мне кажется, что проще, но если вы действительно (действительно!) Хотите пройти специализацию по шаблонам, вы можете написать что-то вроде следующего:
template <std::underlying_type_t<PositiveDigit>, typename = std::true_type>
struct IsNum2
{ static constexpr bool aPrimeDigit = false; };
template <std::underlying_type_t<PositiveDigit> I>
struct IsNum2<I, std::integral_constant<bool, isInList<
PositiveDigit, PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven>
(static_cast<PositiveDigit>(I))>>
{ static constexpr bool aPrimeDigit = true; };
Ниже приводится полный пример компиляции
#include <type_traits>
enum class PositiveDigit
{ Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine };
template <typename T, T ... ts>
constexpr bool isInList (T const & t0)
{
using unused = bool[];
bool ret { false };
(void)unused { false, ret |= t0 == ts... };
return ret;
}
template <std::underlying_type_t<PositiveDigit> I>
struct IsNum1
{
static constexpr bool aPrimeDigit
= isInList<PositiveDigit, PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven>
(static_cast<PositiveDigit>(I));
};
template <std::underlying_type_t<PositiveDigit>, typename = std::true_type>
struct IsNum2
{ static constexpr bool aPrimeDigit = false; };
template <std::underlying_type_t<PositiveDigit> I>
struct IsNum2<I, std::integral_constant<bool, isInList<
PositiveDigit, PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven>
(static_cast<PositiveDigit>(I))>>
{ static constexpr bool aPrimeDigit = true; };
int main ()
{
static_assert( false == IsNum1<-5>::aPrimeDigit, "!" );
static_assert( false == IsNum1<13>::aPrimeDigit, "!" );
static_assert( true == IsNum1< 7>::aPrimeDigit, "!" );
static_assert( false == IsNum2<-5>::aPrimeDigit, "!" );
static_assert( false == IsNum2<13>::aPrimeDigit, "!" );
static_assert( true == IsNum2< 7>::aPrimeDigit, "!" );
}