Как инициализировать стандартный контейнер С++ 11 с помощью обычных шаблонов конструктора?

Можно ли заменить длинный явный список инициализаторов каким-либо шаблоном, который его генерирует?

std::array<Foo, n_foos> foos = {{
        {0, bar},
        {1, bar},
        {2, bar},
        {3, bar},
        {4, bar},
        {5, bar},
        {6, bar},
        {7, bar},
}};

Теперь вот этот код работает только потому, что у нас constexpr int n_foos = 8. Как это можно сделать для произвольного и большого n_foos?


person not-a-user    schedule 14.08.2014    source источник
comment
Вы имеете в виду, что n_foos всегда равно constexpr, но вы просто не знаете, каким будет значение?   -  person Praetorian    schedule 14.08.2014
comment
Я не могу заставить его работать для std::array, так как у него есть только неявные конструкторы (или, другими словами, нет конструктора, принимающего std::initializer_list; конструктор в примере на самом деле является агрегатной инициализацией). Вот что я получил, используя трюк с индексами (работает для std::vector и т. д., но не для std::array): .stacked-crooked.com/a/0f9fe283af3b9b69   -  person tclamb    schedule 14.08.2014
comment
Связанный? stackoverflow.com/a/19016627   -  person dyp    schedule 14.08.2014
comment
Я сделал некоторое метапрограммирование, чтобы сделать что-то подобное здесь: stackoverflow.com /вопросы/15848781/   -  person aaragon    schedule 14.08.2014
comment
Хороший вопрос, объясненный просто и сформулированный таким образом, чтобы (в отличие от большинства веток на эту тему) можно было найти интуитивно понятные условия поиска. Я думаю, что ответ здесь очень применим и ко мне, так что спасибо за вопрос!   -  person underscore_d    schedule 13.01.2016


Ответы (1)


В следующем решении используются C++14 std::index_sequence и std::make_index_sequence (которые могут быть легко реализованы в C++11 программа):

template <std::size_t... indices>
constexpr std::array<Foo, sizeof...(indices)>
CreateArrayOfFoo(const Bar& bar, std::index_sequence<indices...>)
{
    return {{{indices, bar}...}};
}

template <std::size_t N>
constexpr std::array<Foo, N> CreateArrayOfFoo(const Bar& bar)
{
    return CreateArrayOfFoo(bar, std::make_index_sequence<N>());
}

// ...

constexpr std::size_t n_foos = 8;
constexpr auto foos = CreateArrayOfFoo<n_foos>(bar);

См. живой пример.

person Constructor    schedule 14.08.2014
comment
Потрясающе, спасибо! Я хочу заменить существующий std::vector и конструктор на основе цикла, и этот метод, похоже, позволит мне вместо этого создавать элементы в const std::array. Превосходно! Это гораздо более наглядный пример, чем все остальные, которые я нашел, что само по себе непросто, поскольку условия поиска очень неоднозначны. - person underscore_d; 13.01.2016