Как создать std:: array с std:: transform без конструктора по умолчанию

У меня есть std::array<Foo, 10>, и я хотел бы создать std::array<Bar, 10>, используя функцию от Foo до Bar. Обычно я использовал бы std::transform так:

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

Однако Bar не имеет конструктора по умолчанию, поэтому я не могу создать массив bars. Я всегда мог использовать vector, но было бы неплохо использовать array, чтобы гарантировать, что у меня всегда будет ровно 10 элементов. Возможно ли это?

Ответы

Ответ 1

Не с std::transform, но ничего, что магия шаблона не может исправить.

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, а друзья - это С++ 14, но легко реализуемые в С++ 11. На SO есть, вероятно, полдюжины реализаций.