Drew
Drew

Reputation: 13398

How to create a std::array with std::transform without default constructor

I have a std::array<Foo, 10> and I would like to create a std::array<Bar, 10> using a function from Foo to Bar. Ordinarily I would use std::transform like so:

array<Bar, 10> bars;
transform(foos.begin(), foos.end(), bars.begin(), [](Foo foo){
    return Bar(foo.m_1, foo.m_2);
});

However, Bar doesn't have a default constructor, so I can't create the bars array. I could always use vector but it would be nice to be able to use array to guarantee that that I always have exactly 10 elements. Is that possible?

Upvotes: 18

Views: 4692

Answers (1)

T.C.
T.C.

Reputation: 137315

Not with std::transform, but nothing a little template magic can't fix.

template<std::size_t N, std::size_t... Is>
std::array<Bar, N> foos_to_bars(const std::array<Foo, N>& foos,
                                std::index_sequence<Is...>) {
    return {{ Bar(foos[Is].m_1, foos[Is].m_2)... }};
}

template<std::size_t N, std::size_t... Is>
std::array<Bar, N> foos_to_bars(const std::array<Foo, N>& foos) {
    return foos_to_bars(foos, std::make_index_sequence<N>());
}

std::index_sequence and friends are C++14, but easily implementable in C++11. There are probably half a dozen implementations on SO alone.

Upvotes: 17

Related Questions