user12411795
user12411795

Reputation:

concatenation of multiple std::array objects using variadic templates

I need a function fulfilling the following functionality:

template<typename T, std::size_t SIZE_L, std::size_t ...SIZE_R>
std::array<T, SIZE_L> concat(const std::array<T, SIZE_R...>&);

This is supposed to concatenate all passed arrays on the RHS into a single array. The sum of SIZE_R should be identical to SIZE_L -- and if possible one should not need to specify SIZE_L by hand.

The element type of this array will be always double.

Upvotes: 0

Views: 387

Answers (2)

aschepler
aschepler

Reputation: 72346

If needed, here's a version that can deal with a type which can't be default-constructed (try it online):

#include <array>
#include <type_traits>
#include <utility>
#include <tuple>

namespace array_concat_helper {

template <std::size_t Idx, typename SizeSeq, typename Enable=void>
struct indices
{
    static constexpr std::size_t tuple_index = 0;
    static constexpr std::size_t elem_index = Idx;
};

template <std::size_t Idx, std::size_t FirstN, std::size_t ...Ns>
struct indices<Idx, std::index_sequence<FirstN, Ns...>,
    std::enable_if_t<(Idx >= FirstN)>>
{
    static constexpr std::size_t tuple_index =
    1 + indices<Idx-FirstN, std::index_sequence<Ns...>>::tuple_index;
    static constexpr std::size_t elem_index =
    indices<Idx-FirstN, std::index_sequence<Ns...>>::elem_index;
};

template <typename T, std::size_t ...Ns, std::size_t ...Is>
std::array<T, (... + Ns)> concat(
    std::index_sequence<Is...>,
    const std::array<T, Ns>&... arrs)
{
    auto arr_tuple = std::tie(arrs...);
    return {{
        std::get<indices<Is, std::index_sequence<Ns...>>::tuple_index>
        (arr_tuple)
        [indices<Is, std::index_sequence<Ns...>>::elem_index]...
    }};
}

} // end namespace array_concat_helper

template<typename T, std::size_t ...Ns>
std::array<T, (... + Ns)> concat(const std::array<T, Ns>&... arrs)
{
    return array_concat_helper::concat(
        std::make_index_sequence<(... + Ns)>{}, arrs...);
}

Upvotes: 3

Jarod42
Jarod42

Reputation: 217283

With default constructible T, you might do (C++17):

template<typename T, std::size_t ...Ns>
std::array<T, (... + Ns)> concat(const std::array<T, Ns>&... arrs)
{
    std::array<T, (... + Ns)> res;
    std::size_t offset = 0;
    
    ((std::copy(arrs.begin(), arrs.end(), res.begin() + offset),
      offset += arrs.size()),
     ...);
    return res;
}

Demo

Upvotes: 4

Related Questions