在编译时通过算法初始化std :: array

Vor*_*rac 36 c++ initialization compile-time stdarray c++17

考虑:

static constexpr unsigned num_points{ 7810 };
std::array< double, num_points > axis;

for (int i = 0; i < num_points; ++i)
{
    axis[i] = 180 + 0.1 * i;
}
Run Code Online (Sandbox Code Playgroud)

axis是全类常量。我想避免像其他任何全局变量一样初始化它。可以在编译时完成吗?


这是完整的最后一堂课:

// https://www.nist.gov/pml/atomic-spectroscopy-compendium-basic-ideas-notation-data-and-formulas/atomic-spectroscopy
// https://www.nist.gov/pml/atomic-spectra-database
struct Spectrum
{
    static constexpr unsigned _num_points{ 7810 };
    using Axis = std::array< double, _num_points >;

    static constexpr Axis _x{ [] ()            // wavelength, nm
        {
            Axis a {};
            for( unsigned i = 0; i < _num_points; ++i )
            {
                a[ i ] = 180 + 0.1 * i;
            }
            return a;
        } () };
    Axis _y {};                                // radiance, W·sr?1·m?2
};
Run Code Online (Sandbox Code Playgroud)

代码和变量的混合很难看,但是至少公式在读者的眼前。任何其他解决方案都涉及大量键入操作,以获取类中定义的常量和类型。

或者,如果我更改了壁炉,则可以在运行时简单地返回lambda。

Nik*_* C. 35

为了完整起见,这是一个不需要定义函数而是使用lambda的版本。C ++ 17引入了在常量表达式中使用lambda的功能,因此您可以声明数组constexpr并使用lambda对其进行初始化:

static constexpr auto axis = [] {
    std::array<double, num_points> a{};
    for (int i = 0; i < num_points; ++i) {
        a[i] = 180 + 0.1 * i;
    }
    return a;
}();
Run Code Online (Sandbox Code Playgroud)

(请注意()最后一行中的,它立即调用了lambda。)

如果你不喜欢autoaxis声明,因为它使得它难以阅读的实际类型,但你不想重复拉姆达内部的类型,可以改为做:

static constexpr std::array<double, num_points> axis = [] {
    auto a = decltype(axis){};
    for (int i = 0; i < num_points; ++i) {
        a[i] = 180 + 0.1 * i;
    }
    return a;
}();
Run Code Online (Sandbox Code Playgroud)

  • @Rakete1111你是对的。lambda 的调用运算符自动标记为“constexpr”。 (2认同)

Ser*_*eyA 32

这是完整的可编译代码:

#include <array>

template<int num_points>
static constexpr std::array<double, num_points> init_axis() {
    std::array<double, num_points> a{};
    for(int i = 0; i < num_points; ++i) 
    {
        a[i] = 180 + 0.1 * i;
    }
    return a;
};

struct Z {
    static constexpr int num_points = 10;
    static constexpr auto axis = init_axis<num_points>();
};
Run Code Online (Sandbox Code Playgroud)

  • @doug我觉得这是偏好问题。有些人喜欢知道类型,有些人则喜欢较少的“类型”(双关语!)。 (4认同)
  • 建议用“ std :: array &lt;double,num_points&gt;”代替“ auto”,这样读者就不必检查初始化函数来知道类型了。 (3认同)

met*_*fox 14

还有个std::index_sequence窍门(Wandbox example):

template <unsigned... i>
static constexpr auto init_axis(std::integer_sequence<unsigned, i...>) {
   return std::array{(180 + 0.1 * i)...};
};

static constexpr auto axis = init_axis(std::make_integer_sequence<unsigned, num_points>{});
Run Code Online (Sandbox Code Playgroud)