Reputation: 877
I'm coding a function that evaluates binomial coefficients: binom(N, K)
I want to check that both N and K are unsigned-type integers with N >= K at compile time, but having a problem with this.
Here's my code:
template <typename N>
concept Unsigned = std::is_unsigned_v<N>;
template <Unsigned U>
constexpr double binom(U N, U K) {
static_assert(N >= K);
double d = 1.0;
while (K) {
d *= static_cast<double>(N) / static_cast<double>(K);
K--;
N--;
}
return d;
}
template <Unsigned U>
constexpr double binom_pmf(U N, U K, double theta) {
return binom(N, K) * std::pow(theta, K) * std::pow(1 - theta, N - K);
}
Here is the error message from Clang 10:
/mnt/c/programming/ML/2_3_1_binomial_bernoulli.cpp:12:19: error: static_assert expression is not an integral constant expression
static_assert(N >= K);
^~~~~~
/mnt/c/programming/ML/2_3_1_binomial_bernoulli.cpp:24:12: note: in instantiation of function template specialization 'binom<unsigned long>' requested here
return binom(N, K) * std::pow(theta, K) * std::pow(1 - theta, N - K);
^
/mnt/c/programming/ML/2_3_1_binomial_bernoulli.cpp:36:16: note: in instantiation of function template specialization 'binom_pmf<unsigned long>' requested here
y[K] = binom_pmf(N, K, theta);
The problem is static_assert(N >= K)
.
I've declared parameter N as constexpr size_t
, and K is the loop parameter in for (size_t K = 0; K <= N; K++)
, so anyone can conclude that N and K are surely unsigned integers with N >= K, but the compiler doesn't look so happy.
Oh, the compiler is also complaining when I try to insert static_assert(theta >= 0.0 && theta <= 1.0);
in binom_pdf
.
What should I do? Thanks in advance.
Upvotes: 0
Views: 1221
Reputation: 40023
If you really are happy with all these being available only for constant expressions, declare the functions consteval
and throw
(no actual exception needed) when you don’t like the arguments. That allows floating-point types even without compiler support for them as template parameters.
Upvotes: 0
Reputation: 218148
Function parameters are not constexpr
.
template <Unsigned U, U N, U K>
constexpr double binom()
would allow your static_assert
.
Upvotes: 1