web-dev-qa-db-fra.com

Initialiser un std :: array avec une valeur constante

J'ai besoin d'initialiser tous les éléments d'un std::array avec une valeur constante, comme cela peut être fait avec 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
}

Existe-t-il un moyen de le faire avec élégance?

En ce moment j'utilise ceci:

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

mais je voudrais éviter d'utiliser du code explicite pour l'initialisation.

24
Jabberwocky

Avec std::index_sequence, vous pourriez faire:

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>());
}

Avec usage

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

Ce qui, contrairement à std::fill solution, gère le type constructible non par défaut.

21
Jarod42

Hélas non; std::array supporte l'initialisation globale mais cela ne suffit pas ici.

Heureusement, vous pouvez utiliser std::fill, ou même std::array<T,N>::fill, qui, à partir de C++ 20 est élégant car ce dernier devient constexpr.

Référence: https://en.cppreference.com/w/cpp/container/array/fill

20
Bathsheba

Vous pouvez faire comme suit

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

Ou utiliser std::fill du fichier d'en-tête des algorithmes. Pour inclure le fichier d'en-tête des algorithmes, utilisez

#include <algorithm>
12
h4ckthepl4net

Depuis C++ 17, vous pouvez écrire une fonction constexpr pour configurer efficacement le tableau, car les accesseurs d'éléments sont maintenant constexpr. Cette méthode fonctionnera également pour divers autres schémas de configuration des valeurs initiales:

#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);
}
2
M.M

Le std::array type est un agrégat qui prend en charge l'initialisation de liste:

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

Il prend également en charge l'initialisation agrégée:

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

C'est gênant et sujet aux erreurs pour les longues baies, et vous feriez mieux d'utiliser une solution comme Jarod42 pour celles-ci.

0
Davislor