Слишком поздно играть?
Я предлагаю следующее решение
template <typename T, typename ...>
struct cat
{ using type = T; };
template <template <typename ...> class C,
typename ... Ts1, typename ... Ts2, typename ... Ts3>
struct cat<C<Ts1...>, C<Ts2...>, Ts3...>
: public cat<C<Ts1..., Ts2...>, Ts3...>
{ };
Обратите внимание, что это решение работает не только с вариационным списком std::tuple
, но и суниверсальный контейнер типов.Если вам достаточно только std::tuple
решения, вы можете упростить его следующим образом:
template <typename T, typename ...>
struct cat
{ using type = T; };
template <typename ... Ts1, typename ... Ts2, typename ... Ts3>
struct cat<std::tuple<Ts1...>, std::tuple<Ts2...>, Ts3...>
: public cat<std::tuple<Ts1..., Ts2...>, Ts3...>
{ };
Вы можете протестировать работу с
using t1 = typename cat<std::tuple<int, float>,
std::tuple<char, bool>,
std::tuple<long, char, double>>::type;
using t2 = std::tuple<int, float, char, bool, long, char, double>;
static_assert(std::is_same<t1, t2>::value, "!");
- РЕДАКТИРОВАТЬ --
Как указано felix
(спасибо!) С моим прецедентным решением, мы имеем, что
std::is_same<int, typename cat<int>::type>::value == true
, то есть ... cat<T>::type
определяется также, когда T
не std::tuple
.
Это проблема?
Я не знаю, потому что я не знаю, как используется cat<T>::type
.
Во всяком случае ... избегайте того, чтобы cat<Ts...>::type
определялось только тогда, когда все Ts...
являются контейнерами типа (с одним и тем же контейнером), это просто: основная версия для cat
становится только объявленной, но не определенной
template <typename, typename ...> // or also template <typename...>
struct cat;
и вводится дополнительная специализация с одним типом (но только если это контейнер типов).
template <template <typename ...> class C, typename ... Ts1>
struct cat<C<Ts1...>>
{ using type = C<Ts1...>; };