c++ - 使用 constexpr 定义并声明 const std::array if

标签 c++ arrays stl containers constexpr

我正在尝试实现高斯-勒让德求积,并且我想要一个模板化函数 将点数作为模板参数。 现在我有这个:

template<int number_of_quadrature_points>
double gaussian_quadrature_integral_core(double (*f)(double), double from, double to){
    double scaling_factor = (to-from)/2;   
    double average_factor = (from+to)/2;
    std::array<double, number_of_quadrature_points> factors;
    std::array<double, number_of_quadrature_points> points;
    if constexpr(number_of_quadrature_points == 2){
        factors = {1, 1};
        points = {-1.0/sqrt(3), 1.0/sqrt(3)};
    }
    if constexpr(number_of_quadrature_points == 3){
        factors = {5.0/9.0, 8.0/9.0, 5.0/9.0};
        points = {-sqrt(3.0/5.0), 0, sqrt(3.0/5.0)};
    }
    
    double sum = 0;

    for(int i = 0; i < number_of_quadrature_points; i++){
        sum += factors.at(i)*((*f)(scaling_factor*points.at(i)+average_factor));
    }

    sum *= scaling_factor;
    return sum;
}

如您所见,当模板参数发生变化时,不仅数组大小发生变化,而且内容也发生变化,但对于给定的大小,内容是众所周知的。出于这个原因,我认为如果 std::arrays 是 const static 会更好,因为该函数被调用很多次。

现在我只能使用 if constexpr 来声明数组,但是如何使用它来定义和声明数组,以便它在 if constexpr 范围之外可见,并且数组只定义一次?

最佳答案

添加两个辅助函数就足够了(如果您使用的是 C++20):

template<unsigned N>
constexpr auto init_factors() {
    std::array<double, N> rv;
    if constexpr(N == 2){
        rv = {1., 1.};
    } else {
        rv = {5.0/9.0, 8.0/9.0, 5.0/9.0};
    }
    return rv;
}

template<unsigned N>
constexpr auto init_points() {
    std::array<double, N> rv;
    if constexpr(N == 2){
        rv = {-1.0/std::sqrt(3.), 1.0/std::sqrt(3.)};
    } else {
        rv = {-std::sqrt(3.0/5.0), 0, std::sqrt(3.0/5.0)};
    }
    return rv;
}

template<unsigned number_of_quadrature_points>
double gaussian_quadrature_integral_core(double (*f)(double), double from,
                                                              double to)
{
    static constexpr auto factors = init_factors<number_of_quadrature_points>();
    static constexpr auto points = init_points<number_of_quadrature_points>();
[...]

为了防止使用错误的点数,您可以添加 static_assert

template<unsigned number_of_quadrature_points>
double
gaussian_quadrature_integral_core(double (*f)(double), double from,
                                                       double to)
{
    static_assert(number_of_quadrature_points==2||number_of_quadrature_points==3);

...或者如果您想稍后进行特化,则可以阻止使用 SFINAE 进行匹配:

#include <type_traits>

template<unsigned number_of_quadrature_points>
std::enable_if_t<number_of_quadrature_points==2||number_of_quadrature_points==3,
                 double>
gaussian_quadrature_integral_core(double (*f)(double), double from,
                                                       double to)
{

关于c++ - 使用 constexpr 定义并声明 const std::array if,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65341949/

相关文章:

c++ - Qt:在运行时从 C++ 代码创建 QML 组件时未启动 onChildrenChanged

c++ - 在C/C++中检测内存IO以进行硬件仿真

c++ - 不同的结果取决于 C++ 中 for 循环的循环索引的位置

c++ - 在函数 c++ 中访问全局变量

c++ - 有哪些不同的可能方法可以降低给定程序中 vector 数组实现堆栈的时间复杂度……?

javascript - 在 .push()-method 之后,一个数组仍然引用第二个数组(JS/vue.js)

java - 将数组中的元素连接到字符串

c++ - 线性探测哈希函数不起作用?

c++ - 对自定义对象的 vector 进行排序

c++ - 迭代时从 std::list 中删除