Очень грубая реализация:
#include <type_traits>
#include <tuple>
#include <typeinfo>
#include <iostream>
template <typename ... T1, typename ... T2, std::size_t ... I1, std::size_t ... I2>
auto concat_tuple(const std::tuple<T1...>& t1, const std::tuple<T2...>& t2, std::index_sequence<I1...>, std::index_sequence<I2...>) {
return std::tuple<T1..., T2...>(
std::get<I1>(t1)...,
std::get<I2>(t2)...
);
}
template <typename ... T1, typename ... T2>
auto concat_tuple(const std::tuple<T1...>& t1, const std::tuple<T2...>& t2) {
return concat_tuple(t1, t2,
std::make_index_sequence<sizeof...(T1)>{},
std::make_index_sequence<sizeof...(T2)>{}
);
}
template <typename ... T, std::size_t ... I>
auto tuple_rest(const std::tuple<T...>& tup, std::index_sequence<I...>) {
return std::make_tuple(std::get<I+1>(tup)...);
}
template <typename ... T>
auto tuple_rest(const std::tuple<T...>& tup) {
return tuple_rest(tup, std::make_index_sequence<sizeof...(T) - 1>{});
}
template <template <typename T> class Pred, typename ... TAcc>
auto group_by_pred(std::tuple<TAcc...> acc, std::tuple<> tup) {
if constexpr (sizeof...(TAcc) == 0u) {
return std::make_tuple();
}
else return std::make_tuple(acc);
}
template <template <typename T> class Pred, typename ... TAcc, typename T0, typename ... T>
auto group_by_pred(std::tuple<TAcc...> acc, std::tuple<T0, T...> tup) {
if constexpr (Pred<T0>::value) {
return group_by_pred<Pred>(
concat_tuple(acc, std::make_tuple(std::get<0>(tup))),
tuple_rest(tup)
);
}
else {
if constexpr (sizeof...(TAcc) == 0u) {
return concat_tuple(
std::make_tuple(),
concat_tuple(
std::make_tuple(std::get<0>(tup)),
group_by_pred<Pred>(std::make_tuple(), tuple_rest(tup))
)
);
}
else return concat_tuple(
std::make_tuple(acc),
concat_tuple(
std::make_tuple(std::get<0>(tup)),
group_by_pred<Pred>(std::make_tuple(), tuple_rest(tup))
)
);
}
}
template <typename T>
struct not_int : std::true_type {};
template <>
struct not_int<int> : std::false_type {};
int main() {
auto tup = std::make_tuple(1, 2.0, 3.0, 2, 3.0);
auto result = group_by_pred<not_int>(std::make_tuple(), tup);
std::cout << typeid(result).name() << "\n";
}
Идея проста, но шаблонов шаблонов много.
Ссылка проводника компилятора