Reputation: 1309
I am a little new to C++ and learning the language. Right now I'm using C++17 and G++.
I'm trying to initialize an array of structs at compile time. I want to explicitly specify the array indexes in which my initial data goes which makes the process much less error prone. For the indexes I'm going to use integer-aliasses, but for the sake of simplicitly I left the alliases out in the example.
I found that this approach could work:
#include <array>
struct Spec
{
int val;
double otherVal;
};
constexpr static std::array<Spec, 2> make_init_data()
{
std::array<Spec, 2> array{};
array[0] = {1, 3.56};
array[1] = {1, 3.56};
return array;
};
constexpr static std::array<Spec, 2> myArray = make_init_data();
This does compile, and myArray
is populated.
However, I want myArray
to be a class member. So I modified my example to be:
#include <array>
struct Spec
{
int val;
double otherVal;
};
class Test
{
constexpr static std::array<Spec, 2> make_init_data()
{
std::array<Spec, 2> array{};
array[0] = {1, 3.56};
array[1] = {1, 3.56};
return array;
};
constexpr static std::array<Spec, 2> myArray = make_init_data();
};
Which gives me the following error:
Test.h:19:66: error: 'static constexpr std::array<Spec, 2> Test::make_init_data()' called in a constant expression before its definition is complete
19 | constexpr static std::array<Spec, 2> myArray = make_init_data();
|
I understand that the class definition is not yet complete, and that therefore the constexpr
make_init_data
cannot be evaluated yet. I can simply put it outside the class definition, but I need many classes doing this. To avoid a lot of cluttering, scrolling and searching, now and in the future my aim is to to have code which is only relevant for functioanlity inside one class to also be inside this class.
Is there a way to use the constexpr
so that my array gets populated at compile time while the array is also class member?
(Another way to populate the array at compile time in a similar way without constexpr
would also be fine).
Upvotes: 0
Views: 55
Reputation: 13076
I would do it like this a private lambda to calculate the values, and then initialze from that.
#include <array>
struct Spec
{
int val;
double otherVal;
};
class Test
{
private:
static constexpr auto init_array = []
{
std::array<Spec, 2> array{};
array[0] = { 1, 3.56 };
array[1] = { 1, 3.56 };
return array;
};
public:
static constexpr auto myArray{ init_array() };
};
int main()
{
static_assert(Test::myArray[0].val == 1);
return 0;
}
Upvotes: 1
Reputation: 195
you can also initialize it outside the class definition.
// Test.hpp
std::array<Spec, 2> Test::myArray = Test::make_init_data();
Upvotes: 0