SHARE
TWEET

Untitled

a guest Nov 14th, 2017 48 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Pack<Pack<int, char, double>, Pack<int, double, char>, Pack<char, int, double>, Pack<char, double, int>, Pack<double, int, char>, Pack<double, char, int>>
  2.    
  3. #include <iostream>
  4. #include <type_traits>
  5.  
  6. template <typename, typename, typename...> struct RemoveFirstTypeFound;
  7.  
  8. template <typename T> struct Identity { using type = T; };
  9.  
  10. template <typename RemoveMe, template<typename...> class P, typename First, typename... Rest, typename... Types>
  11. struct RemoveFirstTypeFound<RemoveMe, P<First, Rest...>, Types...> : std::conditional<std::is_same<RemoveMe, First>::value,
  12.         Identity<P<Types..., Rest...>>,
  13.         RemoveFirstTypeFound<RemoveMe, P<Rest...>, Types..., First>
  14.     >::type {};
  15.  
  16. template <typename, typename> struct Prepend;
  17.  
  18. template <typename T, template <typename...> class P, typename... Types>
  19. struct Prepend<T, P<Types...>> {
  20.     using type = P<T, Types...>;
  21. };
  22.  
  23. template <typename, typename> struct PrependToEachPack;
  24.  
  25. template <typename T, template <typename...> class P, typename... Packs>
  26. struct PrependToEachPack<T, P<Packs...>> {
  27.     using type = P<typename Prepend<T, Packs>::type...>;
  28. };
  29.  
  30. template <typename, typename> struct Merge;
  31.  
  32. template <template <typename...> class P, typename... Types1, typename... Types2>
  33. struct Merge<P<Types1...>, P<Types2...>> {
  34.     using type = P<Types1..., Types2...>;
  35. };
  36.  
  37. template <typename, typename, typename> struct AllPermutedPacksHelper;
  38.  
  39. template <template<typename...> class P, typename Pack, typename... AccumulatedPacks>
  40. struct AllPermutedPacksHelper<Pack, P<>, P<AccumulatedPacks...>> {
  41.     using type = P<AccumulatedPacks...>;
  42. };
  43.  
  44. template <template<typename...> class P, typename... Types, typename Last>
  45. struct AllPermutedPacksHelper<P<Types...>, P<Last>, P<>> {
  46.     using type = P<P<Last>>;
  47. };
  48.  
  49. template <template<typename...> class P, typename First, typename Pack1, typename Pack2, typename Pack3, typename Pack4>
  50. using AllPermutedPacksHelperAlias = AllPermutedPacksHelper<Pack1, Pack2, typename Merge<Pack3,
  51.         typename PrependToEachPack<First, typename AllPermutedPacksHelper<Pack4, Pack4, P<>>::type>::type>::type>;
  52.  
  53. template <template<typename...> class P, typename... Types, typename... AccumulatedPacks, typename First, typename... Rest>
  54. struct AllPermutedPacksHelper<P<Types...>, P<First, Rest...>, P<AccumulatedPacks...>> :
  55.     AllPermutedPacksHelperAlias<P, First, P<Types...>, P<Rest...>, P<AccumulatedPacks...>, typename RemoveFirstTypeFound<First, P<Types...>>::type> {};
  56.  
  57. template <typename> struct AllPermutedPacks;
  58.  
  59. template <template<typename...> class P, typename... Types>
  60. struct AllPermutedPacks<P<Types...>> : AllPermutedPacksHelper<P<Types...>, P<Types...>, P<>> {};
  61.  
  62. // -----------------------------------------------------------------------------------------------------------------------------------------------
  63. // Testing
  64.  
  65. template <typename...> struct Pack {};
  66.  
  67. int main() {
  68.     std::cout << std::boolalpha << std::is_same< AllPermutedPacks<Pack<>>::type,
  69.         Pack<>
  70.     >::value << std::endl;  // true
  71.  
  72.     std::cout << std::is_same< AllPermutedPacks<Pack<int>>::type,
  73.         Pack<Pack<int>>
  74.     >::value << std::endl;  // true
  75.  
  76.     std::cout << std::is_same< AllPermutedPacks<Pack<int, char>>::type,
  77.         Pack<Pack<int, char>, Pack<char, int>>
  78.     >::value << std::endl;  // true
  79.  
  80.     std::cout << std::is_same< AllPermutedPacks<Pack<int, char, double>>::type,
  81.         Pack<Pack<int, char, double>, Pack<int, double, char>, Pack<char, int, double>, Pack<char, double, int>, Pack<double, int, char>, Pack<double, char, int>>
  82.     >::value << std::endl;  // true
  83. }
  84.    
  85. #include <type_traits>
  86. #include <utility>
  87.  
  88. namespace utilities {
  89.     template <typename Pack1, typename Pack2> struct merge;
  90.  
  91.     template <template <typename...> class P, typename... Ts, typename... Us>
  92.     struct merge<P<Ts...>, P<Us...>> {
  93.         using type = P<Ts..., Us...>;  
  94.     };
  95. }
  96.  
  97. template <std::size_t R, typename Pack, typename TypesIgnored, typename Output, typename = void> struct nPr_h;
  98.  
  99. template <template <typename...> class P, typename First, typename... Rest, typename... TypesIgnored, typename... Output>
  100. struct nPr_h<0, P<First, Rest...>, P<TypesIgnored...>, P<Output...>> {
  101.     using type = P<P<Output...>>;  // Just one single pack (which must be wrapped in P so that the resulting merge will gave all such single packs, rather than a merge of all the types).  
  102. };
  103.  
  104. template <std::size_t R, template <typename...> class P, typename TypesIgnored, typename Output>
  105. struct nPr_h<R, P<>, TypesIgnored, Output> {
  106.     using type = P<>;  // No pack can come out of this (permuting R types from nothing).
  107. };
  108.  
  109. template <std::size_t R, template <typename...> class P, typename First, typename... Rest, typename... TypesIgnored, typename... Output>
  110. struct nPr_h<R, P<First, Rest...>, P<TypesIgnored...>, P<Output...>, std::enable_if_t<(R > sizeof...(Rest) + sizeof...(TypesIgnored))>> {
  111.     using type = P<>;  // No pack can come out of this (since there are less types in P<TypesIgnored..., Rest...> than R).
  112. };
  113.  
  114. template <std::size_t R, template <typename...> class P, typename First, typename... Rest, typename... TypesIgnored, typename... Output>
  115. struct nPr_h<R, P<First, Rest...>, P<TypesIgnored...>, P<Output...>, std::enable_if_t<(R <= sizeof...(Rest) + sizeof...(TypesIgnored) && R != 0)>> : utilities::merge<
  116.     typename nPr_h<R-1, P<TypesIgnored..., Rest...>, P<>, P<Output..., First>>::type,  // Case 1: 'First' is in the permuted pack (note that Output..., First are the types in just one pack).  Now continue to get R-1 more types from TypesIgnored..., Rest... (which are the remaining available types since 'First' is no longer available for the remaining R-1 types, and the ignored types are now P<> since we are starting a new nPr_h call).
  117.     typename nPr_h<R, P<Rest...>, P<TypesIgnored..., First>, P<Output...>>::type  // Case 2:  'First in not in the permuted pack, so try to get R types from Rest... to append to Output...  First is appended o TypesIgnored... since it is now among those types not used.
  118. > { };
  119.  
  120. template <std::size_t R, typename Pack> struct nPr;
  121.  
  122. template <std::size_t R, template <typename...> class P, typename... Ts>
  123. struct nPr<R, P<Ts...>> : nPr_h<R, P<Ts...>, P<>, P<>> { };
  124.  
  125. // Testing
  126. template <typename...> struct P;
  127.  
  128. int main() {
  129.     static_assert(std::is_same<
  130.         nPr<2, P<int, char, float>>::type,  
  131.         P<P<int, char>, P<int, float>, P<char, int>, P<char, float>, P<float, int>, P<float, char>>
  132.     >::value);
  133.  
  134.     static_assert(std::is_same<
  135.         nPr<3, P<int, char, float, bool>>::type,
  136.         P<P<int, char, float>, P<int, char, bool>, P<int, float, char>, P<int, float, bool>, P<int, bool, char>, P<int, bool, float>, P<char, int, float>, P<char, int, bool>, P<char, float, int>, P<char, float, bool>, P<char, bool, int>, P<char, bool, float>, P<float, int, char>, P<float, int, bool>, P<float, char, int>, P<float, char, bool>, P<float, bool, int>, P<float, bool, char>, P<bool, int, char>, P<bool, int, float>, P<bool, char, int>, P<bool, char, float>, P<bool, float, int>, P<bool, float, char>>
  137.     >::value);
  138. }
RAW Paste Data
Top