I am initialising a very large array with thousands of set values. I would like these values set at compile time rather than run time as they are fixed and will not change.
Is there a way of generating these values automatically, perhaps using the preprocessor? Currently I am generating these values using another small program then simply copying and pasting the values in respectively.
Here is what I am generating:
class MyClass
{
public:
MyClass(int x, int y, int z) : X(x), Y(y), Z(z) {}
int X, Y, Z;
};
std::vector<MyClass> my_vector{
#include "my_vector_default_values.h"
};
my_vector_default_values.h
MyClass(0, 0, 1),
MyClass(0, 0, 2),
MyClass(0, 0, 3),
MyClass(0, 0, 4),
// etc... for thousands of lines
// ...
Edit:
The actual values I am generating are generated as follows (this is the C# program):
var sb = new StringBuilder();
var sizeX = 32;
var sizeY = 32;
var sizeZ = 32;
for (var x = 0; x < sizeX; x++)
{
for (var y = 0; y < sizeY; y++)
{
for (var z = 0; z < sizeZ; z++)
{
sb.AppendLine($"MyClass({x}, {y}, {z}),");
}
}
}
var s = sb.ToString();
After the pre-processing is over, all the undefined macros are initialized with default value 0.
This is called token pasting or token concatenation. The ' ## ' preprocessing operator performs token pasting.
The preprocessor performs preliminary operations on C and C++ files before they are passed to the compiler. You can use the preprocessor to conditionally compile code, insert files, specify compile-time error messages, and apply machine-specific rules to sections of code.
Removing comments : It removes all the comments. A comment is written only for the humans to understand the code. So, it is obvious that they are of no use to a machine. So, preprocessor removes all of them as they are not required in the execution and won't be executed as well.
Here is some sample C++17 code, if you can make the class default-constructible:
#include <array>
const size_t gX = 32, gY = 32, gZ = 32;
class MyClass
{
public:
int X, Y, Z;
};
constexpr std::array<MyClass, gX*gY*gZ> gen()
{
std::array<MyClass, gX*gY*gZ> r{};
size_t n = 0;
for (int x = 0; x < gX; ++x)
for (int y = 0; y < gY; ++y)
for (int z = 0; z < gZ; ++z)
r[n++] = { x, y, z };
return r;
}
extern constexpr auto global = gen();
int main()
{
return global[35].Z;
}
As you can see from the assembly output, the table was computed at compile-time.
Since C++17 std::array
allows operator[]
to be used in a constexpr manner. Prior to C++17, or if you want to retain the class's non-default-constructibility, you'd have to use variadic templates to generate a braced initializer for the array; this answer provides a code outline that you could modify to use your generation algorithm.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With