web-dev-qa-db-fra.com

Comment créer std :: array avec la liste d'initialisation sans fournir de taille directement

Comment puis-je faire a3 compiler?

int main()
{
    int a1[] = { 1, 2, 3 };
    std::array<int, 3> a2 = { 1, 2, 3 };
    std::array<int> a3 = { 1, 2, 3 };
}

Il est très gênant et fragile de coder en dur la taille du tableau lors de l'utilisation d'une liste d'initialisation, particulièrement longue. Y a-t-il une solution de contournement? J'espère que sinon, je suis déçu parce que je déteste les tableaux C et std::array est censé être leur remplaçant.

39
Neil Kirk

Il n'y a actuellement aucun moyen de le faire sans lancer votre propre make_array, il existe une proposition pour cela N3824: make_array qui a la portée suivante:

LWG 851 ​​destiné à fournir une syntaxe de remplacement pour

array<T, N> a = { E1, E2, ... };

, donc ce qui suit

auto a = make_array(42u, 3.14);

est bien formé (avec des static_casts supplémentaires appliqués à l'intérieur) car

array<double, 2> = { 42u, 3.14 };

est bien formé.

Cet article vise à fournir un ensemble d'interfaces de création std :: array qui sont complètes à la fois du point de vue de Tuple et du point de vue du tableau, donc le rétrécissement est tout simplement interdit. Voir plus de détails entraînés par cette direction dans Design Decisions.

Il comprend également un exemple d'implémentation , qui est assez long, donc la copie ici n'est pas pratique, mais Konrad Rudolph a une version simplifiée ici qui est cohérente avec l'exemple d'implémentation ci-dessus:

template <typename... T>
constexpr auto make_array(T&&... values) ->
    std::array<
       typename std::decay<
           typename std::common_type<T...>::type>::type,
       sizeof...(T)> {
    return std::array<
        typename std::decay<
            typename std::common_type<T...>::type>::type,
        sizeof...(T)>{std::forward<T>(values)...};
}
23
Shafik Yaghmour

Vous êtes un peu trop dramatique lorsque vous dites "une fonction aussi horriblement complexe (pour moi) est nécessaire". Vous pouvez créer vous-même une version simplifiée, la proposition comprend également une fonction "to_array" pour convertir les tableaux C et déduire le type du premier paramètre. Si vous omettez cela, cela devient tout à fait gérable.

template<typename T, typename... N>
auto my_make_array(N&&... args) -> std::array<T,sizeof...(args)>
{
    return {std::forward<N>(args)...};
}

que vous pouvez ensuite appeler comme

auto arr = my_make_array<int>(1,2,3,4,5);

edit: Je dois mentionner qu'il y a en fait une version de cela dans la proposition que j'ai ignorée, donc cela devrait être plus correct que ma version:

template <typename V, typename... T>
constexpr auto array_of(T&&... t)
    -> std::array < V, sizeof...(T) >
{
    return {{ std::forward<T>(t)... }};
}
12
PeterT