До сих пор я знал о двух решениях.
В первом мне удалось сделать это с помощью выражений свертывания C ++ и перегрузки операторов.Этот код ужасен, и я не горжусь этим - но он есть.Каждый может комментировать и вносить свой вклад:
#include <utility>
#include <array>
struct Int {
size_t i;
};
constexpr std::array<Int, 2> operator+(Int i1, Int i2) {
return {i1, i2};
}
template<size_t SZ, size_t... Ix>
constexpr auto concat(std::array<Int, 2> arr1, std::array<Int, SZ> arr2, std::index_sequence<Ix...>)
{
return std::array<Int, SZ+2>{arr1[0], arr1[1], arr2[Ix]...};
}
template<size_t SZ>
constexpr auto operator+ (std::array<Int, 2> arr1, std::array<Int, SZ> arr2) {
return concat(arr1, arr2, std::make_index_sequence<SZ>{});
}
template<size_t SZ, size_t... Ix>
constexpr auto convert_impl(std::array<Int, SZ> arr, std::index_sequence<Ix...>) {
return std::array{arr[Ix].i...};
}
template<size_t SZ>
constexpr auto convert(std::array<Int, SZ> arr) {
return convert_impl(arr, std::make_index_sequence<SZ>{});
}
template<size_t... IX1, size_t... IX2>
constexpr auto make_arr(std::index_sequence<IX1...>, std::index_sequence<IX2...>) {
return convert(((Int{IX1} + Int{IX2})+ ...));
}
using i1 = std::index_sequence<1, 3, 5, 7>;
using i2 = std::index_sequence<2, 4, 6, 8>;
auto k = make_arr(i1{}, i2{});
Второе решение намного лучше:
#include <utility>
#include <array>
template<size_t... Ix, class T, size_t SZ>
auto concat(T t1, T t2, std::array<T, SZ> arr, std::index_sequence<Ix...>) {
return std::array{t1, t2, arr[Ix]...};
}
template<size_t i0, size_t... Ix0, size_t i1, size_t... Ix1>
auto make_array(std::index_sequence<i0, Ix0...>, std::index_sequence<i1, Ix1...>) {
if constexpr (sizeof...(Ix0) > 0) {
return concat(i0,
i1,
make_array(std::index_sequence<Ix0...>{}, std::index_sequence<Ix1...>{}),
std::make_index_sequence<sizeof...(Ix0) + sizeof...(Ix1)>{}
);
} else {
return std::array{i0, i1};
}
}
using i1 = std::index_sequence<1, 3, 5, 7>;
using i2 = std::index_sequence<2, 4, 6, 8>;
std::array<size_t, 8> k = make_array(i1{}, i2{});