6

Can the long explicit initializer list in the following be replaced by some template that generates it?

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

Now here this code works only because we have constexpr int n_foos = 8. How can this be done for arbitrary and large n_foos?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
not-a-user
  • 4,088
  • 3
  • 21
  • 37
  • Do you mean `n_foos` is always `constexpr`, but you just don't know what the value will be? – Praetorian Aug 14 '14 at 16:43
  • I can't quite get it to work for `std::array` since that only has implicit constructors (or put another way, there is no constructor accepting `std::initializer_list`; the constructor in the example is actually aggregate initialization). Here's as far as I got using the indices trick (works for `std::vector` etc, just not `std::array`): http://coliru.stacked-crooked.com/a/0f9fe283af3b9b69 – tclamb Aug 14 '14 at 16:55
  • Related? http://stackoverflow.com/a/19016627 – dyp Aug 14 '14 at 17:58
  • I did some metaprogramming to do something similar here: http://stackoverflow.com/questions/15848781/constructor-for-nested-initializer-lists – aaragon Aug 14 '14 at 18:23
  • Good question, explained simply and phrased in a way that (unlike most threads about this) intuitive search terms can find. I think the answer here is very applicable to me too, so thanks for asking the question! – underscore_d Jan 13 '16 at 12:48

1 Answers1

8

The following solution uses C++14 std::index_sequence and std::make_index_sequence (which can be easily implemented in C++11 program):

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

See live example.

Community
  • 1
  • 1
Constructor
  • 7,273
  • 2
  • 24
  • 66
  • Awesome, thanks! I want to replace an existing `std::vector` and loop-based constructor, and this method would seem to allow me to construct the elements into a `const std::array` instead. Excellent! This is a much clearer example than all the others I found - which in itself isn't easy, since the search terms are very ambiguous. – underscore_d Jan 13 '16 at 12:47