C++ filling multidimensional std::arrays

Viewed 206

To declare a matrix with all of its elements having a certain value, using std::array the only way I know to do so looks like the following:

std::array<std::array<int, dim_1>, dim_2> matrix;
for (auto it = matrix.begin(); it != matrix.end(); ++it) 
    std::fill(it->begin(), it->end(), number);

Is there a better, more concise way?

3 Answers
auto matrix = std::array<std::array<int, 4>, 4>();
const auto value = 64;

A one-liner:

std::for_each(matrix.begin(), matrix.end(), [value](auto& column) { std::for_each(column.begin(), column.end(), [value](auto& element) {element = value; }); });

Another one:

std::for_each(matrix.begin(), matrix.end(), [value](auto& column) { std::fill(column.begin(), column.end(), value); });

Something actually readable:

for (auto& column : matrix) {
    for (auto& element : column) {
        element = value;
    }
}

I have no idea if those are actually columns though

This compiles on latest MSVC too and looks funny enough:

std::fill(matrix.begin(), matrix.end(), std::array{ value, value, value, value });

If you're looking for conciseness, you can fill it with a filled array:

decltype(matrix[0]) temp;
temp.fill(5);
matrix.fill(temp);

You can technically remove the temporary assuming a non-zero dimension:

matrix[0].fill(5);
matrix.fill(matrix[0]);

In order for this to perform as well as filling in place, you'll have to rely on the compiler seeing through it. Alternatively, you can plop this in a constexpr function since C++20 and guarantee a compile-time result if you wish.

With helper function:

namespace detail
{

    template <typename T, std::size_t...Is>
    constexpr std::array<T, sizeof...(Is)>
    make_array(const T& value, std::index_sequence<Is...>)
    {
        return {{(static_cast<void>(Is), value)...}};
    }
}

template <std::size_t N, typename T>
constexpr std::array<T, N> make_array(const T& value)
{
    return detail::make_array(value, std::make_index_sequence<N>());
}

And then

/*const*/ auto matrix = make_array<dim_2>(make_array<dim_1>(value));

Advantage over fill is that it support non-default constructible types.

And advantage of helper function (even if implemented with std::fill) over assignation afterward is that you can initialize const variable :)

Related