2

Please consider these types:

struct Part
{
    float data;
};

struct Wrap
{
    Wrap( const Part& p )
        :data( p.data )
    {}
    float data;
};

Now I would like to use an std::array<Part, N> to initialize an std::array<Wrap, N>.

int main()
{
    std::array<Part, 3> parts{ Part{ 1.0f }, Part{ 2.0f }, Part{ 3.0f } };
    std::array<Wrap, 3> wrappers( parts );
    return 0;
}

( This throws the error "conversion from 'std::array<Part, 3>' to non-scalar type 'std::array<Wrap, 3>' requested" )

How can I use an std::array of type T to initialize an std::array of a type which is constructable from T?

2 Answers 2

2

You could use a helper function to automate conversion:

// Convert each element based on a sequence of indices:
template<typename ToType, typename FromType, std::size_t... Indices>
std::array<ToType, sizeof...(Indices)>
convert_impl(const std::array<FromType, sizeof...(Indices)>& input, std::index_sequence<Indices...>)
{
    return {ToType(std::get<Indices>(input))...};
}

// Wraps convert_impl to hide the use of index_sequence from users:
template<typename ToType, typename FromType, std::size_t N>
std::array<ToType, N> convert(const std::array<FromType, N>& input)
{
    return convert_impl<ToType>(input, std::make_index_sequence<N>{});
}

int main()
{
    std::array<Part, 3> parts {Part{1.0f}, Part{2.0f}, Part{3.0f}};
    std::array<Wrap, 3> wraps = convert<Wrap>(parts);

    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

1

Possible simple options are:

O. Use vector instead (arrays are still evil 0_o).

    std::vector<Part> ps{Part{1.0}, Part{2.0}, Part{3.0}};
    std::vector<Wrap> ws(ps.cbegin(), ps.cend());

I. Make it explicit.

    std::array<Part, 3> parts{ Part{ 1.0f }, Part{ 2.0f }, Part{ 3.0f } };
    std::array<Wrap, 3> wrappers = {parts[0], parts[1], parts[2]};

II. Split construction and initialization.

struct Unwrap {
    Unwrap() {}
    Unwrap(Part const &p): data(p.data) {}
    float data;
};

int main() {
    std::array<Part, 3> parts{ Part{ 1.0f }, Part{ 2.0f }, Part{ 3.0f } };
    std::array<Unwrap, 3> unwrappers;
    std::copy(parts.cbegin(), parts.cend(), unwrappers.begin());
}

BTW, does your code with parentheses in Part initialization even compile? I could only make it to by changing them to braces.

1 Comment

Oh yes my fault, I should have either added a constructor for Part or used braces.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.