考慮してください:
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;
}
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
};
コードと変数の混合は見苦しいですが、少なくとも公式は読者の目の前にあります。他の解決策では、クラス内で定義された定数と型を取得するために、多くの型付けが必要でした。
または、囲炉裏を変更した場合、実行時にラムダを返すだけです。
完全を期すために、関数の定義を必要とせず、代わりにラムダを使用するバージョンを次に示します。 C++ 17は定数式でラムダを使用する機能を導入したため、配列constexpr
を宣言し、ラムダを使用してそれを初期化できます。
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;
}();
(()
最後の行で、ラムダをすぐに呼び出します。)
auto
宣言のaxis
が気に入らない場合、実際の型を読み取るのが難しくなりますが、ラムダ内でその型を繰り返したくない場合は、代わりに行う:
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;
}();
次に、完全なコンパイル可能なコードを示します。
#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>();
};
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>{});