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.