Initialize an std::array algorithmically at compile time
For completeness' sake, here's a version that does not require the definition of a function but instead uses a lambda. C++17 introduced the ability of using lambdas in constant expressions, so you can declare your array constexpr
and use a lambda to initialize it:
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;
}();
(Note the ()
in the last line, which calls the lambda right away.)
If you don't like the auto
in the axis
declaration because it makes it harder to read the actual type, but you don't want to repeat the type inside the lambda, you can instead do:
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;
}();
Here is the full compileable code:
#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>();
};
There's also the std::index_sequence
trick (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>{});