Home > Mobile >  Create std::array<T, N> from constructor argument list
Create std::array<T, N> from constructor argument list

Time:08-29

The desired behaviour is that of emplace called N times.

Very similar to this question Initializing a std::array with a constant value. Except instead of calling the copy constructor given some T, you are given some argument list for which you call the corresponding constructor of T.

Pseudo code:

template <typename ...Args>
std::array<T, N> create_array(Args&&... args)
{
    return { T(args...), T(args...), .... };
}

For example, this is necessary when T has members that are (smart) pointers and you want these pointers to reference unique objects.

CodePudding user response:

Modifying this answer, I came up with:

namespace detail
{
    template <typename T, std::size_t ... Is, typename ...V>
    constexpr std::array<T, sizeof...(Is)>
        create_array(std::index_sequence<Is...>, V&&... values)
    {
        // cast Is to void to remove the warning: unused value
        return { {(static_cast<void>(Is), T(values...))...} };
    }
}

template <typename T, std::size_t N, typename ...V>
constexpr std::array<T, N> create_array(V&&... values)
{
    return detail::create_array<T>(std::make_index_sequence<N>(), std::forward<V>(values)...);
}

CodePudding user response:

Jarod commented that this should be implemented with a generator, and with c 20 templated lambdas we can do away with the helper function

template <std::size_t N, typename Generator> 
auto create_array_from_generator(Generator gen)
{
    return [&]<std::size_t... I>(std::index_sequence<I...>) -> std::array<std::decay_t<decltype(gen())>, N>
        {
            return { {(static_cast<void>(I), gen())...} };
        }(std::make_integer_sequence<std::size_t, N>{});
}

https://godbolt.org/z/PMPhvW81q

  • Related