C ++, как вы «перегружаете» шаблон для работы как для значения, так и для типа? - PullRequest
1 голос
/ 26 марта 2019

Рассмотрим этот простой мета-запрос, чтобы проверить интеграл:

#include <type_traits>

template <typename T>
struct IsIntegralConstant
{
    static constexpr bool value = std::is_integral_v<T>;
};

// partial specialization if type destructuring matches an integral_constant
template <typename T, auto N>
struct IsIntegralConstant<std::integral_constant<T, N>>
{
    static constexpr bool value = true;
};
template <typename T> constexpr auto isIntegralConstant_v = IsIntegralConstant<T>::value;

// Now I can do queries such as:
static_assert( isIntegralConstant_v<int> );
static_assert( isIntegralConstant_v<std::integral_constant<int, 2>> );

// it'd be nice if it could work for direct values too 
// static_assert( isIntegralConstant_v<2> ); ?

// let's see...
template <auto N>
struct IsIntegralConstant<std::integral_constant<decltype(N), N>>
{
    static constexpr bool value = true;
};
// gcc:
 //error: partial specialization of 'struct IsIntegralConstant<std::integral_constant<decltype (N), N> >' after instantiation of 'struct IsIntegralConstant<std::integral_constant<int, 2> >' [-fpermissive]
 //struct IsIntegralConstant<std::integral_constant<decltype(N), N>>
// what ?

// clang says nothing, until we force instanciation:
static_assert( isIntegralConstant_v<2> );

//#1 with x86-64 clang 8.0.0
//<source>:35:38: error: template argument for template type parameter must be a type

поиграть с ним: https://godbolt.org/z/dosK7G

Кажется, когда ваш основной шаблон принял решение между типом или значением, тогдаВы просто застряли с этим для всех специализаций.

Нет ли способа иметь более общую вещь, такую ​​как:

template <autotypename TorV> ... ?

1 Ответ

1 голос
/ 26 марта 2019

Нет ли способа иметь более общую вещь, такую ​​как

Пока ни в одной версии C ++.И это тоже вряд ли изменится.Несмотря на загруженное имя IsIntegralConstant, мы, очевидно, не собираемся тестировать такие вещи, как IsIntegralConstant_v<2>.Утилита шаблонов в общем коде, где ничего не хватает:

template<auto wut>
struct bar {
     // static_assert(IsIntegralConstant_v<wut>);
     // ill-formed, but we only really care and need
     static_assert(IsIntegralConstant_v<decltype(wut)>);
};
...