static_assert проверка аргументов во время компиляции с концепцией C ++ 20 - PullRequest
0 голосов
/ 31 марта 2020

Я кодирую функцию, которая оценивает биномиальные коэффициенты: binom(N, K)

Я хочу проверить, что и N, и K являются целыми числами без знака с N> = K во время компиляции, но возникли проблемы с этим.

Вот мой код:

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

Вот сообщение об ошибке от 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);

Проблема static_assert(N >= K).

Я объявил параметр N как constexpr size_t, а K - это параметр l oop в for (size_t K = 0; K <= N; K++), поэтому любой может прийти к выводу, что N и K, безусловно, являются целыми числами без знака с N> = K, но компилятор не не выглядит таким счастливым.

О, компилятор также жалуется, когда я пытаюсь вставить static_assert(theta >= 0.0 && theta <= 1.0); в binom_pdf.

Что мне делать? Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Параметры функции не constexpr.

template <Unsigned U, U N, U K> constexpr double binom() позволят вашему static_assert.

0 голосов
/ 01 апреля 2020

Если вы действительно довольны тем, что все это доступно только для константных выражений, объявите функции consteval и throw (без фактического исключения), если вам не нравятся аргументы. Это позволяет использовать типы с плавающей точкой даже без поддержки компилятором их в качестве параметров шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...