web-dev-qa-db-fra.com

Pourquoi std :: array n'a-t-il pas de constructeur qui prend une valeur pour que le tableau soit rempli?

L'absence de

std::array<T,size>::array(const T& value);

un oubli? Il me semble très utile et les conteneurs dynamiques (comme std::vector) ont un constructeur similaire.

Je suis pleinement conscient de

std::array<T,size>::fill(const T& value);

mais ce n'est pas un constructeur, et la mémoire sera mise à zéro en premier. Et si je veux tout -1 c'est comme ce mec ?

66
rubenvb

std::array est, par conception, un agrégat, donc n'a pas de constructeurs déclarés par l'utilisateur.

Comme vous le dites, vous pouvez utiliser fill après la construction par défaut. Puisqu'il s'agit d'un agrégat, la construction par défaut ne remettra pas à zéro la mémoire, mais la laissera non initialisée (si le type contenu est trivialement initialisable).

49
Mike Seymour

Notez que vous pouvez simuler efficacement ce type de constructeur en tirant parti du fait que le tableau n'est pas initialisé à zéro, et a un constructeur de copie et do.

template <size_t N, class T>
array<T,N> make_array(const T &v) {
    array<T,N> ret;
    ret.fill(v);
    return ret;
}

auto a = make_array<20>('z');
21
tohava

Tout d'abord, ce n'est pas std::array<T>, c'est std::array<T,N>N est l'expression intégrale de la constante de temps de compilation.

Seconde, std::array est fait agrégé par conception. Il n'a donc rien qui le rend non agrégé, c'est pourquoi il n'a pas de constructeur ... ni de destructeur, de fonctions virtuelles, etc.

11
Nawaz

Vous pouvez utiliser std::index sequence Pour cela:

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

Démo

std::make_index_sequence Est C++ 14, mais peut être implémenté en C++ 11.

static_cast<void>(Is) est pour gérer le mal operator, que T pourrait fournir.

9
Jarod42