szablon parametr szablonu innego niż typ

Dec 07 2020

Próbuję napisać stałą constexpr zwięźle przy użyciu funkcji 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);

ale nie kompiluje się ani na GCC, ani na clang.

Czy można określić parametry szablonu innego niż typ? Alternatywnie można to zapisać rekurencyjnie, ale dobrze byłoby wiedzieć, czy można to zapisać tak jak powyżej.

Zauważ, że to pytanie wygląda podobnie do parametru innego niż typ szablonu szablonu, ale parametr szablonu innego niż typ jest umieszczany na zagnieżdżonej liście parametrów szablonu zamiast na liście parametrów podstawowych.

Odpowiedzi

2 Kostas Dec 07 2020 at 22:22

Nie można bezpośrednio odwoływać się do argumentów do parametrów szablonu. Nie ma ich w zakresie. Ale możesz zrobić coś takiego:

#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
}

Biorąc to pod uwagę, istnieją prostsze sposoby implementacji 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

Możesz zrobić coś takiego:

#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);