шаблон не типовой параметр шаблона

Dec 07 2020

Я пытаюсь кратко написать константу constexpr, используя функции C ++ 20.

#include <utility>

template <template <typename T, T ... Ints> std::integer_sequence<T, Ints...> I>
static constexpr long pow10_helper = ((Ints, 10) * ...);

template <std::size_t exp>
static constexpr long pow10 = pow10_helper< std::make_index_sequence<exp> >;

static_assert(pow10<3> == 1000);

но он не компилируется ни на GCC, ни на clang.

Можно ли указать параметры шаблона, не относящиеся к типу? В качестве альтернативы можно записать его рекурсивно, но было бы неплохо знать, можно ли написать его, как указано выше.

Обратите внимание, что этот вопрос похож на параметр шаблона шаблона без типа, но параметр шаблона без типа помещается во вложенный список параметров шаблона, а не в список основных параметров.

Ответы

2 Kostas Dec 07 2020 at 22:22

Вы не можете напрямую ссылаться на аргументы параметров шаблона шаблона. Они не входят в сферу охвата. Но вы могли бы сделать что-то вроде этого:

#include <utility>

template <class>
class pow10_helper {};

template <template <typename T, T ...> class IntSeq, class T, T ... Ints>
struct pow10_helper<IntSeq<T, Ints...>> {
  static constexpr long value = ((Ints, 10) * ...);
};

template <size_t pow>
static constexpr long pow10 = pow10_helper<std::make_index_sequence<pow>>::value;
#include <iostream>
int main() {
  size_t pow = pow10<3>;
  std::cout << pow << std::endl; // prints 1000
}

При этом есть более простые способы реализации pow10:

template <size_t pow>
struct pow10 { static constexpr size_t value = 10 * pow10<pow-1>::value; };
template <> struct pow10<0> { static constexpr size_t value = 1; };
int main() {
  size_t pow = pow10<3>::value;
  std::cout << pow << std::endl; //prints 1000
}
4 Mestkon Dec 07 2020 at 22:23

Вы можете сделать что-то вроде этого:

#include <utility>

template<class T>
static constexpr long pow10_helper;

template<class T, T... Is>
static constexpr long pow10_helper<std::integer_sequence<T, Is...>> = ((Is, 10) * ...);

template <std::size_t exp>
static constexpr long pow10 = pow10_helper<std::make_index_sequence<exp> >;

static_assert(pow10<3> == 1000);