struct TypeList {}; I want to ...">

The most elegant way to break C ++ TypeList

In "modern" C ++, I have a list of types:

template <typename... T> struct TypeList {}; 

I want to split the list of types according to the predicate, for example std::is_floating_point . To be more precise, my complete working example is:

 #include <iostream> #include <type_traits> template <typename... T> struct TypeList {}; // SplitTypeList<> implementation defined at the end of this post... template <typename T> void printType() { std::cout << "\n" << __PRETTY_FUNCTION__; } int main() { struct A { }; using typeList = TypeList<int, double, float, A, int>; using splited_typeList = SplitTypeList<std::is_floating_point, typeList>; using float_typeList = splited_typeList::predicate_is_true_typeList_type; using other_typeList = splited_typeList::predicate_is_false_typeList_type; printType<float_typeList>(); printType<other_typeList>(); } 

prints:

 g++ -std=c++17 typeList.cpp -o typeList; ./typeList void printType() [with T = TypeList<double, float>] void printType() [with T = TypeList<int, main()::A, int>] 

my question is : do you have an idea of ​​a possible shorter / more elegant solution that uses only C ++ (no problem with C ++ 17) and STL? (I do not want to use a helper library like Boost, Hana ...).

( Motivation : I don’t want to miss one or two lines / super elegant solution, since I will use this functionality in other places)


My current implementation:

 namespace Details { template <template <typename> class PREDICATE, typename... TYPELIST_PREDICATE_IS_TRUE, typename... TYPELIST_PREDICATE_IS_FALSE> constexpr auto splitTypeList(TypeList<TYPELIST_PREDICATE_IS_TRUE...>, TypeList<TYPELIST_PREDICATE_IS_FALSE...>, TypeList<>) { return std::make_pair(TypeList<TYPELIST_PREDICATE_IS_TRUE...>(), TypeList<TYPELIST_PREDICATE_IS_FALSE...>()); } template <template <typename> class PREDICATE, typename... TYPELIST_PREDICATE_IS_TRUE, typename... TYPELIST_PREDICATE_IS_FALSE, typename T, typename... TAIL> constexpr auto splitTypeList(TypeList<TYPELIST_PREDICATE_IS_TRUE...>, TypeList<TYPELIST_PREDICATE_IS_FALSE...>, TypeList<T, TAIL...>) { if constexpr (PREDICATE<T>::value) { return splitTypeList<PREDICATE>( TypeList<TYPELIST_PREDICATE_IS_TRUE..., T>(), TypeList<TYPELIST_PREDICATE_IS_FALSE...>(), TypeList<TAIL...>()); } else { return splitTypeList<PREDICATE>( TypeList<TYPELIST_PREDICATE_IS_TRUE...>(), TypeList<TYPELIST_PREDICATE_IS_FALSE..., T>(), TypeList<TAIL...>()); } } template <template <typename> class PREDICATE, typename... T> constexpr auto splitTypeList(TypeList<T...>) { return splitTypeList<PREDICATE>( TypeList<>(), TypeList<>(), TypeList<T...>()); } } template <template <typename> class PREDICATE, typename TYPELIST> struct SplitTypeList; template <template <typename> class PREDICATE, typename... TAIL> struct SplitTypeList<PREDICATE, TypeList<TAIL...>> { using pair_type = decltype( Details::splitTypeList<PREDICATE>(std::declval<TypeList<TAIL...>>())); using predicate_is_true_typeList_type = typename pair_type::first_type; using predicate_is_false_typeList_type = typename pair_type::second_type; }; 

Just for curiosity, the historical pointer to TypeList (Andrei Alexandrescu, 02/01/2002): http://www.drdobbs.com/generic-programmingtypelists-and-applica/184403813

+5
source share
2 answers

something like this might be a little simpler / shorter

 template< bool, template<typename> class, class... Vs > auto FilterImpl( TypeList<>, TypeList<Vs...> v ) { return v; } template< bool Include, template<typename> class P, class T, class... Ts, class... Vs > auto FilterImpl( TypeList<T,Ts...>, TypeList<Vs...> ) { return FilterImpl<Include,P>( TypeList<Ts...>{} , std::conditional_t< Include == P<T>::value, TypeList<T,Vs...>, TypeList<Vs...> >{} ); } template <template <typename> class PREDICATE, typename TYPELIST> struct SplitTypeList { using predicate_is_true_typeList_type = decltype(FilterImpl<true,PREDICATE>( TYPELIST{}, TypeList<>{} )); using predicate_is_false_typeList_type = decltype(FilterImpl<false,PREDICATE>( TYPELIST{}, TypeList<>{} )); }; 
+4
source

I am not saying that the next path is better or more elegant.

This is different, and this is my way.

Using only the specialization of variational template classes; no function.

Should work with C ++ 11 as well.

We hope this example helps.

 #include <tuple> #include <type_traits> template <template <typename> class Pred, typename> struct PredValFirst : public std::false_type { }; template <template <typename> class Pred, template <typename...> class C, typename T0, typename ... Ts> struct PredValFirst<Pred, C<T0, Ts...>> : public Pred<T0> { }; template <template <typename> class Pred, typename List, typename = std::tuple<>, typename = std::tuple<>, bool = PredValFirst<Pred, List>::value> struct SplitTypeList; template <template <typename> class Pred, template <typename...> class C, typename T0, typename ... Ts, typename ... Tt, typename Lf> struct SplitTypeList<Pred, C<T0, Ts...>, std::tuple<Tt...>, Lf, true> : SplitTypeList<Pred, C<Ts...>, std::tuple<Tt..., T0>, Lf> { }; template <template <typename> class Pred, template <typename...> class C, typename T0, typename ... Ts, typename Lt, typename ... Tf> struct SplitTypeList<Pred, C<T0, Ts...>, Lt, std::tuple<Tf...>, false> : SplitTypeList<Pred, C<Ts...>, Lt, std::tuple<Tf..., T0>> { }; template <template <typename> class Pred, template <typename...> class C, typename ... Tt, typename ... Tf> struct SplitTypeList<Pred, C<>, std::tuple<Tt...>, std::tuple<Tf...>, false> { using types_true = C<Tt...>; using types_false = C<Tf...>; }; template <typename...> struct TypeList { }; struct A { }; int main () { using typeList = TypeList<int, double, float, A, int>; using splited_typeList = SplitTypeList<std::is_floating_point, typeList>; using float_typeList = splited_typeList::types_true; using other_typeList = splited_typeList::types_false; static_assert( std::is_same<float_typeList, TypeList<double, float>>{}, "!"); static_assert( std::is_same<other_typeList, TypeList<int, A, int>>{}, "!"); } 
+1
source

Source: https://habr.com/ru/post/1272781/


All Articles