I am implementing a Matrix class in C++ and I want to be able to initialize it with an intializer list like so:
Matrix<double, 2, 3> m({{1,2,1},
{0,1,1}});
In the class I have implemented the constructor like this:
template<typename Ty, unsigned int rows, unsigned int cols>
class Matrix
{
std::array<std::array<Ty, cols>, rows> data;
public:
Matrix(const std::initializer_list<std::initializer_list<Ty>>& list)
{
int i = 0;
for (auto& list_row : list)
{
int j = 0;
for (auto& list_value : list_row)
{
data[i][j++] = list_value;
}
i++;
}
}
}
The code work but I have a couple of questions. Is it possible to make it safe, so it only takes initializer lists of a certain size(the size of the matrix) and secondly can I make the code more concise - I had imagined something like this:
Matrix(const std::initializer_list<std::initializer_list<Ty>>& list)
: data(list)
{ }
And it doesn't work but any better way to do it would be appreciated.
There's a pretty easy way to make it safe:
template<typename Ty, unsigned int rows, unsigned int cols>
class Matrix
{
std::array<std::array<Ty, cols>, rows> data;
public:
Matrix(std::array<std::array<Ty, cols>, rows> const& in)
: data(in)
{ }
};
This lets you almost use the syntax you want - you just need one extra set of {}
s.
There's no way to statically enforce the size of a std::initializer_list
- you'd have to assert
or throw
to prevent me from passing in a bunch of extra values and causing you to perform out-of-range writes.