Suppose I have a std::vector
of a size known at compile time, and I want to turn that into an std::array
. How would I do that? Is there a standard function to do this?
The best solution I have so far is this:
template<class T, std::size_t N, class Indexable, std::size_t... Indices>
std::array<T, N> to_array_1(const Indexable& indexable, std::index_sequence<Indices...>) {
return {{ indexable[Indices]... }};
}
template<class T, std::size_t N, class Indexable>
std::array<T, N> to_array(const Indexable& indexable) {
return to_array_1<T, N>(indexable, std::make_index_sequence<N>());
}
std::array<Foo, 123> initFoos {
std::vector<Foo> lst;
for (unsigned i = 0; i < 123; ++i)
lst.push_back(getNextFoo(lst));
return to_array<Foo, 123>(lst); // passing lst.begin() works, too
}
The application is similar to Populate std::array with non-default-constructible type (no variadic templates): I too have a type which is not default-constructible, so I need to compute the actual values by the time the array gets initialized. However contrary to that question, for me the values are not merely a function of the index, but also of the preceding values. I can build my values much more easily using a loop than a series of function calls. So I construct the elements in a loop and place them in a vector, then I want to use the final state of that vector to initialize the array.
The above seems to compile and work fine, but perhaps there are ways to improve it.
- Perhaps I could make clever use of some standard library functionality that I wasn't aware of.
- Perhaps I can avoid the helper function somehow.
- Perhaps I can somehow formulate this in such a way that it works with move semantics for the elements instead of the copy semantics employed above.
- Perhaps I can avoid the random access using
operator[]
, and instead use forward iterator semantics only so it would work forstd::set
orstd::forward_list
as input, too. - Perhaps I should stop using
std::vector
and instead express my goal usingstd::array<std::optional<T>, N>
instead, using C++17 or some equivalent implementation.
Related questions:
- Copy std::vector into std::array which doesn't assume a type without default constructor, so copying after default initialization is feasible there but not for me.
- Populate std::array with non-default-constructible type (no variadic templates) which computes each element from its index independently, so it tries to avoid an intermediate container. Answers use variadic templates even though the title requests avoiding them.