| #include <iostream>
#include <string>
#include <tuple>
#include <utility>
//////////////////////////////////////////////
// Определяем, находится ли тип в списке типов
template <typename T, typename...>
struct is_in_the_list : std::false_type {};
template <typename T, typename U, typename...X>
struct is_in_the_list<T, U, X...> : is_in_the_list<T, X...> {};
template <typename T, typename...X>
struct is_in_the_list<T, T, X...> : std::true_type {};
//////////////////////////////////////////////////////////////////////////////
// Строим список индексов входного тупла, которые попадают в конечный тупл
template <typename Tuple, typename FilterTuple, typename I = std::index_sequence<0>, typename = void>
struct filtered_index_sequence;
template <typename T, typename...S, typename...F, size_t I, size_t...J>
struct filtered_index_sequence<std::tuple<T, S...>, std::tuple<F...>, std::index_sequence<I, J...>,
std::enable_if_t<is_in_the_list<T, F...>::value>> :
filtered_index_sequence<std::tuple<S...>, std::tuple<F...>, std::index_sequence<I + 1, J..., I>> { };
template <typename T, typename...S, typename...F, size_t I, size_t...J>
struct filtered_index_sequence<std::tuple<T, S...>, std::tuple<F...>, std::index_sequence<I, J...>,
std::enable_if_t<!is_in_the_list<T, F...>::value>> :
filtered_index_sequence<std::tuple<S...>, std::tuple<F...>, std::index_sequence<I + 1, J...>> { };
template <typename...F, size_t I, size_t...J>
struct filtered_index_sequence<std::tuple<>, std::tuple<F...>, std::index_sequence<I, J...>>
{
using type = std::index_sequence<J...>;
};
template <typename Tuple, typename...Filter>
using make_filtered_index_sequence = typename filtered_index_sequence<Tuple, std::tuple<Filter...>>::type;
///////////////////////////////
// Выводим тип конечного тупла
template <typename Tuple, typename...Filter>
struct filtered_tuple;
template <typename...T, size_t...I>
struct filtered_tuple<std::tuple<T...>, std::index_sequence<I...>> {
using type = std::tuple<std::tuple_element_t<I, std::tuple<T...>>...>;
};
template <typename...T, typename...Filter>
struct filtered_tuple<std::tuple<T...>, Filter...> :
filtered_tuple<std::tuple<T...>, make_filtered_index_sequence<std::tuple<T...>, Filter...>> {};
template <typename Tuple, typename...Filter>
using filtered_tuple_t = typename filtered_tuple<Tuple, Filter...>::type;
///////////////////////////////////////
// Фильтрация тупла по списку индексов
template <typename...T, size_t...I>
auto make_filtered_tuple(const std::tuple<T...>& tuple, std::index_sequence<I...>)
-> filtered_tuple_t<std::tuple<T...>, std::index_sequence<I...>>
{
return { std::get<I>(tuple)... };
}
////////////////////////////////////
// Фильтрация тупла по списку типов
template <typename...Filter, typename...T>
auto make_filtered_tuple(const std::tuple<T...>& tuple)
-> filtered_tuple_t<std::tuple<T...>, Filter...>
{
return make_filtered_tuple(tuple, make_filtered_index_sequence<std::tuple<T...>, Filter...>{});
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Try to use
template <typename...T, size_t...I>
void print(const std::tuple<T...>& tuple, std::index_sequence<I...>)
{
((std::cout << std::get<I>(tuple) << ", "), ...) << std::endl;
}
template <typename...T>
void print(const std::tuple<T...>& tuple)
{
print(tuple, std::index_sequence_for<T...>{});
}
int main()
{
const auto tuple = std::make_tuple("Morning", 42, std::string("Hello"), 3.14, true, std::string("World"), 'A');
print(make_filtered_tuple<int, std::string>(tuple)); // -> 42, Hello, World,
print(make_filtered_tuple<double, const char*, char>(tuple)); // -> Morning, 3.14, A,
}
|