I want to create a 2D-array populated by some known function with no runtime overhead.
To have an example, suppose a function f(x, y) = 10 * y + x
, let x
be in {1, 2, 3}
and y
in {4, 5, 6}
. I want to create a 2D array with content
41 42 43
51 52 53
61 62 63
Now, the easiest way to go is just hard-code the values directly in my sources. And it is indeed appropriate for my task, so the question is just out of curiosity.
I would like to create a metafunc and a struct possessed with some kind of black magic, which allows me to define an array out of given sets of values for x
and y
. Like this:
template<int X> struct Func {
template<int Y> struct over {
static const int value = 10 * Y + X; // f(x, y)
};
};
template<int... args1> struct Rows {
template<int... args2> struct Cols {
static const int data[sizeof...(args1)][sizeof...(args2)];
};
};
template<int... args1>
template<int... args2>
const int Rows<args1...>::Cols<args2...>::data[sizeof...(args1)][sizeof...(args2)] = {
{ Func<args1>::over<args2>::value... } // This does not do what I want :(
// Need some black magic here
};
// Here is my precious table
const auto& table = Rows<1, 2, 3>::Cols<4, 5, 6>::data;
If I print values from the table, I have this:
41 52 63
0 0 0
0 0 0
I understand what's happening, the term Func<args1>::over<args2>::value
has two parameter packs in it, args1
and args2
, so applying ...
on it expand them simultaneously, and I only have 3 members instead of 9.
If you've reached so far, you've already understood what I want. So the question is, how do I do it? How do I apply ellipsis separately to both parameter packs so I can have cartesian combination in the initializer? Or maybe there are some other ways to do it?
I am aware of this answer and that answer. They use std::array
instead of plain array, so they first construct 1D-arrays, and then initialize 2D-array with a number of 1D-array. But if I understood correctly, this initialization has to be done in runtime. I want to avoid that. However, I have no objections against std::array
. I suppose that with a proper compiler they are just as fast as plain arrays.
By the way, here is my possible solution using generalized constexpr
from C++14 and a question about it. Any ideas on how to solve the task with constexpr
from C++11 are also welcomed.