fork download
  1. // IsPermutation<Pack1, Pack2>::value has value true if the types in Pack1 are a permutation of the types in Pack2.
  2.  
  3. #include <iostream>
  4. #include <type_traits>
  5.  
  6. template <typename, typename> struct ExistsInPack;
  7.  
  8. template <typename T, template <typename...> class P>
  9. struct ExistsInPack<T, P<>> : std::false_type {};
  10.  
  11. template <typename T, template <typename...> class P, typename... Rest>
  12. struct ExistsInPack<T, P<T, Rest...>> : std::true_type {};
  13.  
  14. template <typename T, template <typename...> class P, typename First, typename... Rest>
  15. struct ExistsInPack<T, P<First, Rest...>> : ExistsInPack<T, P<Rest...>> {};
  16.  
  17. template <std::size_t N, typename T, typename Pack> struct CountHelper;
  18.  
  19. template <std::size_t N, typename T, template <typename...> class P>
  20. struct CountHelper<N, T, P<>> : std::integral_constant<std::size_t, N> {};
  21.  
  22. template <std::size_t N, typename T, template <typename...> class P, typename... Rest>
  23. struct CountHelper<N, T, P<T, Rest...>> : CountHelper<N+1, T, P<Rest...>> {};
  24.  
  25. template <std::size_t N, typename T, template <typename...> class P, typename First, typename... Rest>
  26. struct CountHelper<N, T, P<First, Rest...>> : CountHelper<N, T, P<Rest...>> {};
  27.  
  28. template <typename T, typename Pack>
  29. using Count = CountHelper<0, T, Pack>; // Count<T, Pack>::value is the number of occurrences of T in Pack.
  30.  
  31. template <typename Pack1, typename Pack2, typename AlreadyCounted> struct CountFirstType;
  32.  
  33. template <template <typename...> class P, typename Pack, typename AlreadyCounted>
  34. struct CountFirstType<P<>, Pack, AlreadyCounted> : std::true_type {};
  35.  
  36. template <template <typename...> class P, typename First, typename... Rest, typename Pack, typename... AlreadyCounted>
  37. struct CountFirstType<P<First, Rest...>, Pack, P<AlreadyCounted...>> : std::conditional_t<
  38. ExistsInPack<First, P<AlreadyCounted...>>::value,
  39. CountFirstType<P<Rest...>, Pack, P<AlreadyCounted...>>,
  40. std::conditional_t<
  41. Count<First, P<First, Rest...>>::value == Count<First, Pack>::value,
  42. CountFirstType<P<Rest...>, Pack, P<AlreadyCounted..., First>>,
  43. std::false_type
  44. >
  45. > {};
  46.  
  47. template <typename Pack1, typename Pack2> struct IsPermutation;
  48.  
  49. template <template <typename...> class P, typename... Ts, typename... Us>
  50. struct IsPermutation<P<Ts...>, P<Us...>> : CountFirstType<P<Ts...>, P<Us...>, P<>> {};
  51.  
  52. template <template <typename...> class P, typename First, typename... Rest1, typename... Rest2>
  53. struct IsPermutation<P<First, Rest1...>, P<First, Rest2...>> : IsPermutation<P<Rest1...>, P<Rest2...>> {};
  54.  
  55. template <template <typename...> class P>
  56. struct IsPermutation<P<>, P<>> : std::true_type {};
  57.  
  58. template <template <typename...> class P, typename... Ts>
  59. struct IsPermutation<P<>, P<Ts...>> : std::false_type {};
  60.  
  61. template <template <typename...> class P, typename... Ts>
  62. struct IsPermutation<P<Ts...>, P<>> : std::false_type {};
  63.  
  64. // Testing
  65. template <typename...> struct P;
  66.  
  67. int main() {
  68. std::cout << std::boolalpha << IsPermutation< P<int, char, bool>, P<int, char, bool> >::value << '\n'; // true
  69. std::cout << IsPermutation< P<int, char, bool>, P<int, char, bool, int> >::value << '\n'; // false
  70. std::cout << IsPermutation< P<int, char, bool, int>, P<int, char, bool> >::value << '\n'; // false
  71. std::cout << IsPermutation< P<int, char, bool, long>, P<int, char, long, bool> >::value << '\n'; // true
  72. std::cout << IsPermutation< P<int, char, bool, long, long, bool, long>, P<int, char, long, bool, long, long, bool> >::value << '\n'; // true
  73. std::cout << IsPermutation< P<int, char, bool, long>, P<int, char, long, bool, long> >::value << '\n'; // false
  74. }
  75.  
Success #stdin #stdout 0s 3412KB
stdin
Standard input is empty
stdout
true
false
false
true
true
false