Skip to content

Instantly share code, notes, and snippets.

@ecatmur
Last active June 30, 2017 15:44
Show Gist options
  • Save ecatmur/577a73d230ae05d6ba356f5c8e600c60 to your computer and use it in GitHub Desktop.
Save ecatmur/577a73d230ae05d6ba356f5c8e600c60 to your computer and use it in GitHub Desktop.
Non-recursive variadic array concat using indexing arrays and folds.
#include <array>
#include <type_traits>
#include <utility>
template<class> struct Nth;
template<std::size_t... Is> struct Nth<std::index_sequence<Is...>>
{
template<std::size_t> struct Ignore { template<class T> constexpr Ignore(T&&) {} };
template<class T, class... Us> constexpr T&& operator()(Ignore<Is>..., T&& t, Us&&...) { return std::forward<T>(t); }
};
template<std::size_t I, class... Ts> constexpr decltype(auto) nth(Ts&&... ts) { return Nth<std::make_index_sequence<I>>{}(ts...); }
template<std::size_t... Is, std::size_t... Js, class... Ts, std::size_t... Ns>
constexpr auto concatImpl(std::index_sequence<Is...>, std::index_sequence<Js...>, std::array<Ts, Ns> const&... as) ->
std::array<std::common_type_t<Ts...>, sizeof...(Js)>
{
constexpr std::size_t P[]{[](std::size_t I) { return (0u + ... + (Is < I ? Ns : 0u)); }(Is)...};
constexpr std::size_t Q[]{[&](std::size_t J) { return (0u + ... + (Is != 0u && P[Is] <= J ? 1u : 0u)); }(Js)...};
return {nth<Q[Js]>(as...)[Js - P[Q[Js]]]...};
}
template<class... Ts, std::size_t... Ns>
constexpr auto concat(std::array<Ts, Ns> const&... as) -> std::array<std::common_type_t<Ts...>, (0 + ... + Ns)>
{
return concatImpl(std::index_sequence_for<Ts...>{}, std::make_index_sequence<(0 + ... + Ns)>{}, as...);
}
auto aa = concat(
std::array<char, 5>{'H', 'e', 'l', 'l', 'o'},
std::array<char, 0>{},
std::array<char, 5>{1, 2, 3, 4});
int main()
{
constexpr auto a = concat(std::array<int, 1>{0l}, std::array<int, 0>{}, std::array<int, 4>{1, 2, 3, 4});
return a[4];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment