43

I need to initialize all elements of a std::array with a constant value, like it can be done with std::vector.

#include <vector>
#include <array>

int main()
{
  std::vector<int> v(10, 7);    // OK
  std::array<int, 10> a(7);     // does not compile, pretty frustrating
}

Is there a way to do this elegantly?

Right now I'm using this:

std::array<int, 10> a;
for (auto & v : a)
  v = 7;

but I'd like to avoid using explicit code for the initialisation.

Jarod42
  • 190,553
  • 13
  • 166
  • 271
Jabberwocky
  • 45,262
  • 17
  • 54
  • 100
  • 2
    Related to [Why does std::array not have an constructor that takes a value for the array to be filled with?](https://stackoverflow.com/questions/17923683/why-does-stdarray-not-have-an-constructor-that-takes-a-value-for-the-array-to) – Jarod42 Sep 04 '19 at 22:27

5 Answers5

32

With std::index_sequence, you might do:

namespace detail
{
    template <typename T, std::size_t ... Is>
    constexpr std::array<T, sizeof...(Is)>
    create_array(T value, std::index_sequence<Is...>)
    {
        // cast Is to void to remove the warning: unused value
        return {{(static_cast<void>(Is), value)...}};
    }
}

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

With usage

auto a = create_array<10 /*, int*/>(7); // auto is std::array<int, 10>

Which, contrary to std::fill solution, handle non default constructible types.

Jarod42
  • 190,553
  • 13
  • 166
  • 271
26

Alas not; std::array supports aggregate initialisation but that's not enough here.

Fortunately you can use std::fill, or even std::array<T,N>::fill, which, from C++20 is elegant as the latter becomes constexpr.

Reference: https://en.cppreference.com/w/cpp/container/array/fill

Bathsheba
  • 227,678
  • 33
  • 352
  • 470
17

You can do as following

std::array<int, 10> a; 
a.fill(2/*or any other value*/);

Or use std::fill from algorithms header file. To include algorithms header file use

#include <algorithm>
h4ckthepl4net
  • 301
  • 1
  • 11
  • 1
    Thanks for taking the time to write out the actual code. This is something I don't do often enough: Stack Overflow works best when there are multiple answers to choose from. – Bathsheba Sep 02 '19 at 12:08
  • @Bathsheba no problem mate) – h4ckthepl4net Sep 02 '19 at 12:09
  • @Bathsheba I am writing this from a phone so I haven't seen that you already answered the question – h4ckthepl4net Sep 02 '19 at 12:11
  • I'm glad - you should answer answer a question if you believe you have something to say that, perhaps, hasn't already been said. I think this answer is more useful in some ways than mine. – Bathsheba Sep 02 '19 at 12:12
6

Since C++17 you can write a constexpr function to efficiently set up the array, since the element accessors are constexpr now. This method will also work for various other schemes of setting up initial values:

#include <array>

template<typename T, size_t N>
constexpr auto make_array(T value) -> std::array<T, N>
{
    std::array<T, N> a{};
    for (auto& x : a)
        x = value;
    return a;
}

int main()
{
    auto arr = make_array<int, 10>(7);
}
M.M
  • 134,614
  • 21
  • 188
  • 335
2

The std::array type is an aggregate that supports list-initialization:

std::array<int, 10> a{2, 2, 2, 2, 2, 2, 2, 2, 2, 2};

It also supports aggregate-initialization:

std::array<int, 10> a = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2};

This is inconvenient and error-prone for long arrays, and you would be better off using a solution like Jarod42’s for those.

Jarod42
  • 190,553
  • 13
  • 166
  • 271
Davislor
  • 13,447
  • 2
  • 30
  • 40
  • 2
    This is inconvenient and error-prone for _any_ array length. – Jabberwocky Sep 03 '19 at 08:51
  • 3
    @Jabberwocky The accepted answer is great and I upvoted it. It’s also kind of overkill for an array of three elements. The others don’t work for a `constexpr std::array`. So this technique is sometimes appropriate. – Davislor Sep 03 '19 at 16:33