Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 772
Drew Avatar asked Aug 24 '15 06:08

Drew


People also ask

Does std :: array initialize?

std::array contains a built-in array, which can be initialized via an initializer list, which is what the inner set is. The outer set is for aggregate initialization.

How do you initialize STD array std STD?

Initialization of std::array Like arrays, we initialize an std::array by simply assigning it values at the time of declaration. For example, we will initialize an integer type std::array named 'n' of length 5 as shown below; std::array<int, 5> n = {1, 2, 3, 4, 5};

What does std :: transform do?

std::transform applies the given function to a range and stores the result in another range, keeping the original elements order and beginning at d_first .

How does transform work in C++?

The transform() function in C++ sequentially applies an operation to the elements of an array(s) and then stores the result in another output array. The transform function is used in two forms: Unary operation: The operation is applied to each element in the input range, and the result is stored in the output array.


1 Answers

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.

like image 80
T.C. Avatar answered Oct 26 '22 13:10

T.C.