Application of set theory to C ++ 11 variation patterns

Say I have two variation patterns; typename... T, typename... U , how would I find them;

  • concatenation
  • Maximum total subsequence
  • Inverse maximum total subsequence

So, from what I understand, concatenation is simple; (t..., u...) , but what about finding the maximum common subsequence of two? - is it possible?

+4
source share
1 answer

Here is a solution that computes set operations for pairs of tuple types . I assume that tuples can be used to store packages of variable arguments, so if you have Ts... and Us... , you do:

 typename tuple_intersect<std::tuple<Ts...>, std::tuple<Us...>>::type 

And that gives you a tuple where Vs... is the intersection of Ts... and Us... If you need to extract Vs... again as an argument package, simply specify the tuple as the input to the function that takes tuple<Ts...> :

 template<typename... Vs> void func(std::tuple<Vs...>) { // Here, you have Vs... (= Us... & Ts...) as an argument pack } 

Framework

Here are some simple meta functions common to all major meta functions below:

 template<typename T, typename... Ts> struct is_member_of_type_seq { static const bool value = false; }; template<typename T, typename U, typename... Ts> struct is_member_of_type_seq<T, U, Ts...> { static const bool value = std::conditional< std::is_same<T, U>::value, std::true_type, is_member_of_type_seq<T, Ts...> >::type::value; }; template<typename, typename> struct append_to_type_seq { }; template<typename T, typename... Ts> struct append_to_type_seq<T, std::tuple<Ts...>> { using type = std::tuple<Ts..., T>; }; template<typename, typename> struct prepend_to_type_seq { }; template<typename T, typename... Ts> struct prepend_to_type_seq<T, std::tuple<Ts...>> { using type = std::tuple<T, Ts...>; }; 

1 - Concatenation

It is pretty simple:

 template<typename, typename> struct concat_type_seq { }; template<typename... Ts, typename... Us> struct concat_type_seq<std::tuple<Ts...>, std::tuple<Us...>> { using type = std::tuple<Ts..., Us...>; }; 

And some tests:

 static_assert( std::is_same< concat_type_seq< std::tuple<char, int, bool>, std::tuple<double, double, int> >::type, std::tuple<char, int, bool, double, double, int> >::value, "Error" ); 

2 - The longest common subsequence

This is a little trickier:

 namespace detail { // Meta-function that returns, given two sequences S1 and S2, the longest // subsequence of S1 in S2 that starts with the first element of S1 and // begins at the first element of S2 (in other words, it returns the // subsequence S2[0]..S2[N] such that S1[i] = S2[i] for each 0 <= i <= N. template<typename, typename> struct match_seq_in_seq_from_start { using type = std::tuple<>; }; template<typename T, typename U, typename... Ts, typename... Us> struct match_seq_in_seq_from_start<std::tuple<T, Ts...>, std::tuple<U, Us...>> { using type = typename std::conditional< std::is_same<T, U>::value, typename prepend_to_type_seq< T, typename match_seq_in_seq_from_start< std::tuple<Ts...>, std::tuple<Us...> >::type >::type, std::tuple<> >::type; }; // Some testing... static_assert( std::is_same< match_seq_in_seq_from_start< std::tuple<int, double, char>, std::tuple<int, double, long> // ^^^^^^^^^^^ >::type, std::tuple<int, double> >::value, "Error!" ); // Meta-function that returns the same as the meta-function above, // but starting from the first element of S2 which is identical to // the first element of S1. template<typename, typename> struct match_first_seq_in_seq { using type = std::tuple<>; }; template<typename T, typename U, typename... Ts, typename... Us> struct match_first_seq_in_seq<std::tuple<T, Ts...>, std::tuple<U, Us...>> { using type = typename std::conditional< std::is_same<T, U>::value, typename match_seq_in_seq_from_start< std::tuple<T, Ts...>, std::tuple<U, Us...> >::type, typename match_first_seq_in_seq< std::tuple<T, Ts...>, std::tuple<Us...> >::type >::type; }; // Some testing... static_assert( std::is_same< match_first_seq_in_seq< std::tuple<int, double, char>, std::tuple<bool, char, int, double, long, int, double, char> // ^^^^^^^^^^^ >::type, std::tuple<int, double> >::value, "Error!" ); // Meta-function that returns, given two sequences S1 and S2, the longest // subsequence of S1 in S2 that starts with the first element of S1. template<typename T, typename U> struct match_seq_in_seq { using type = std::tuple<>; }; template<typename U, typename... Ts, typename... Us> struct match_seq_in_seq<std::tuple<Ts...>, std::tuple<U, Us...>> { using type1 = typename match_first_seq_in_seq< std::tuple<Ts...>, std::tuple<U, Us...> >::type; using type2 = typename match_seq_in_seq< std::tuple<Ts...>, std::tuple<Us...> >::type; using type = typename std::conditional< (std::tuple_size<type1>::value > std::tuple_size<type2>::value), type1, type2 >::type; }; // Some testing... static_assert( std::is_same< match_seq_in_seq< std::tuple<int, double, char>, std::tuple<char, int, double, long, int, double, char> // ^^^^^^^^^^^^^^^^^ >::type, std::tuple<int, double, char> >::value, "Error!" ); } // Meta-function that returns, given two sequences S1 and S2, the longest // subsequence of S1 in S2 (longest common subsequence). template<typename T, typename U> struct max_common_subseq { using type = std::tuple<>; }; template<typename T, typename... Ts, typename... Us> struct max_common_subseq<std::tuple<T, Ts...>, std::tuple<Us...>> { using type1 = typename detail::match_seq_in_seq< std::tuple<T, Ts...>, std::tuple<Us...> >::type; using type2 = typename max_common_subseq< std::tuple<Ts...>, std::tuple<Us...> >::type; using type = typename std::conditional< (std::tuple_size<type1>::value > std::tuple_size<type2>::value), type1, type2 >::type; }; 

And some tests:

 // Some testing... static_assert( std::is_same< max_common_subseq< std::tuple<int, double, char>, std::tuple<char, int, char, double, char, long, int, bool, double> >::type, std::tuple<double, char> >::value, "Error!" ); // Some more testing... static_assert( std::is_same< max_common_subseq< std::tuple<int, double, char, long, long, bool>, // ^^^^^^^^^^^^^^^^ std::tuple<char, long, long, double, double, char> // ^^^^^^^^^^^^^^^^ >::type, std::tuple<char, long, long> >::value, "Error!" ); 

3 - Inversion

Here is a trait for inverting a type sequence (returns a tuple with an inverted type):

 template<typename... Ts> struct revert_type_seq { using type = std::tuple<>; }; template<typename T, typename... Ts> struct revert_type_seq<T, Ts...> { using type = typename append_to_type_seq< T, typename revert_type_seq<Ts...>::type >::type; }; 

And some tests:

 // Some testing... static_assert( std::is_same< revert_type_seq<char, int, bool>::type, std::tuple<bool, int, char> >::value, "Error" ); 

4 - Intersection

This request was not requested, but is provided as a bonus:

 template<typename, typename> struct intersect_type_seq { using type = std::tuple<>; }; template<typename T, typename... Ts, typename... Us> struct intersect_type_seq<std::tuple<T, Ts...>, std::tuple<Us...>> { using type = typename std::conditional< !is_member_of_type_seq<T, Us...>::value, typename intersect_type_seq< std::tuple<Ts...>, std::tuple<Us...>> ::type, typename prepend_to_type_seq< T, typename intersect_type_seq< std::tuple<Ts...>, std::tuple<Us...> >::type >::type >::type; }; 

And some tests:

 // Some testing... static_assert( std::is_same< intersect_type_seq< std::tuple<char, int, bool, double>, std::tuple<bool, long, double, float> >::type, std::tuple<bool, double> >::value, "Error!" ); 
+10
source

All Articles