Home > Blockchain >  Specialize class templated on constrained non-type parameter
Specialize class templated on constrained non-type parameter

Time:07-29

Let's consider the following code for compile-time evaluation of the factorial function:

#include <concepts>

template <std::integral auto num>
struct factorial {
    constexpr static auto val{num * factorial<num - 1>::val};
};

// Note: This only specializes the class for (int)0
template <>
struct factorial<0> {
    constexpr static auto val{1};
};

// ...

factorial<4>::val;  // Ok: 24
factorial<4u>::val; // error: template instantiation depth exceeds maximum of 900
                    // This makes sense: There's no factorial<0u> specialization.

Is there a way to introduce specialization factorial<0> for all integral types (i.e. for all the types that satisfy std::integral)?

Of course, I'd like to avoid actually writing out specializations factorial<0u>, factorial<0l>, and so on.

CodePudding user response:

Instead of explicitly specializing for specifically 0 (i.e. an int with value 0), you can partially specialize for any value which compares equal to 0:

template <std::integral auto I> requires (I == 0)
struct factorial<I> {
    static constexpr auto val = 1;
};

which if you prefer can also be spelled this way:

template <class T, T I> requires (I == 0)
struct factorial<I> {
    static constexpr auto val = 1;
};

but I don't think there's a way to deduce T{0} as the value.

  • Related