Reputation: 994
I am trying to implement matrix-like class, using an std::array to actually store the data. All of the data is known at compile-time.
I want to be able to use initializer-lists to initialize the Matrix. Something along the lines of
Matrix m = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
I also want to be able to set the dimensions of my matrix during instantiation.
My current code is similar to the following:
template<int m, int n>
class Matrix {
public:
using initializer_list2d = std::initializer_list< std::initializer_list<float> >;
using array2d = std::array< std::array<float, m>, n >;
consteval Matrix(initializer_list2d initList) {
// static_assert to check initList length [...]
int i = 0;
for (auto &row : initList) {
// static_assert to check row length [...]
std::copy(row.begin(), row.end(), data_[i].begin());
i++;
}
}
// Definitions of operators and methods [...]
private:
array2d data_;
};
In order to use this though, I have to set the dimensions through the template:
Matrix<3, 3> m = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
It seems to me, that since the constructor is consteval (and all of its parameters have to be known at compile-time anyway) it should somehow bet possible to deduce the dimensions through the initializer-list alone.
Using a dynamic data type (e.g. vector) is not possible for my application, since this program has to be able to run without access to the heap.
Is there some way to achieve this?
Thanks for any help in advance!
Upvotes: 0
Views: 237
Reputation: 994
I found another interesting solution, using variadic templates:
template<int m, class T, class... U>
struct Matrix {
Matrix(const T (&t)[m], const U (& ...u)[m]) {
std::copy(t, t+m, arr[0]);
int i = 0;
(std::copy(u, u+m, arr[++i]), ...);
}
T (arr[m])[sizeof...(U) + 1];
};
It even allows for getting rid of the second brace required in cigien's answer and doesn't need a template deduction guide (Although it still needs C++17 in order for int m
to be automatically deduced):
Matrix mat = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Also, the compiler seems to be able to optimze this quite a bit, as seen here
Upvotes: 0
Reputation: 60208
Before C++17 there is no deduction of template arguments for a class template, so this is not possible.
From C++17, you can write this deduction guide:
template<int m, int n>
Matrix(float const (&)[n][m]) -> Matrix<m, n>;
and add an extra pair of braces when constructing the Matrix
:
Matrix m =
{
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}
};
Here's a demo.
Upvotes: 2