Concatenating a sequence of std::arrays
You may do the following:
template <typename F, typename T, typename T2>auto func(F f, T&& t, T2&& t2){ return f(std::forward<T>(t), std::forward<T2>(t2));}template <typename F, typename T, typename T2, typename ... Ts>auto func(F f, T&& t, T2&& t2, Ts&&...args){ return func(f, f(std::forward<T>(t), std::forward<T2>(t2)), std::forward<Ts>(args)...);}
With usage
struct concatenater{ template<typename T, std::size_t N, std::size_t M> auto operator()(const std::array<T, N>& ar1, const std::array<T, M>& ar2) const { std::array<T, N+M> result; std::copy (ar1.cbegin(), ar1.cend(), result.begin()); std::copy (ar2.cbegin(), ar2.cend(), result.begin() + N); return result; }};
and
auto result = func(concatenater{}, ar1, ar2, ar3, ar4);
Here is a simple C++17 solution via fold expressions:
#include <array>#include <algorithm>template <typename Type, std::size_t... sizes>auto concatenate(const std::array<Type, sizes>&... arrays){ std::array<Type, (sizes + ...)> result; std::size_t index{}; ((std::copy_n(arrays.begin(), sizes, result.begin() + index), index += sizes), ...); return result;}
Example of using:
const std::array<int, 3> array1 = {{1, 2, 3}};const std::array<int, 2> array2 = {{4, 5}};const std::array<int, 4> array3 = {{6, 7, 8, 9}};const auto result = concatenate(array1, array2, array3);
Given a sequence of
std::array<T, length1>
,std::array<T, length2>
, ...,std::array<T, lengthK>
, how can I write a function which concatenates the sequence into anstd::array<T, sum(lengths)>
?
Here's a C++17 solution. It can very probably be shortened and improved, working on it.
template <std::size_t Last = 0, typename TF, typename TArray, typename... TRest>constexpr auto with_acc_sizes(TF&& f, const TArray& array, const TRest&... rest){ f(array, std::integral_constant<std::size_t, Last>{}); if constexpr(sizeof...(TRest) != 0) { with_acc_sizes<Last + std::tuple_size_v<TArray>>(f, rest...); }}template<typename T, std::size_t... Sizes>constexpr auto concat(const std::array<T, Sizes>&... arrays){ std::array<T, (Sizes + ...)> result{}; with_acc_sizes([&](const auto& arr, auto offset) { std::copy(arr.begin(), arr.end(), result.begin() + offset); }, arrays...); return result;}
Usage:
std::array<int, 3> ar1 = {1, 2, 3};std::array<int, 2> ar2 = {4, 5};std::array<int, 3> ar3 = {6, 7, 8};auto result = concat(ar1, ar2, ar3);
Works with both g++7 and clang++5.