fork download
  1. #include <type_traits>
  2. #include <cassert>
  3. #include <iostream>
  4.  
  5. template<typename...>
  6. struct toRecursiveList;
  7.  
  8. //a recursive list already
  9. template<template <typename...> class Pack, typename H, typename... T>
  10. struct toRecursiveList<Pack<H, Pack<T...>>>
  11. {
  12. using type = Pack<H, Pack<T...>>;
  13. };
  14.  
  15. //several elements
  16. template<template <typename...> class Pack, typename H, typename... T>
  17. struct toRecursiveList<Pack<H, T...>>
  18. {
  19. using type = Pack<H, Pack<T...>>;
  20. };
  21.  
  22. //one element
  23. template<template <typename...> class Pack, typename H>
  24. struct toRecursiveList<Pack<H> >
  25. {
  26. using type = Pack<H, Pack<>>;
  27. };
  28.  
  29. //empty
  30. template<template <typename...> class Pack>
  31. struct toRecursiveList<Pack<>>
  32. {
  33. using type = Pack<>;
  34. };
  35.  
  36. //missing pack
  37. template<typename H, typename... T>
  38. struct toRecursiveList<H, T...>
  39. {
  40. template<typename...>
  41. struct Pack;
  42. using type = Pack<H, Pack<T...>>;
  43. };
  44.  
  45. //base case - guarantees an initial recursive list
  46. template <template <typename...> class F, typename... L>
  47. struct any_n :
  48. any_n<F, typename toRecursiveList<L>::type...>
  49. {};
  50.  
  51. //main recursion
  52. template
  53. <
  54. template <typename...> class F,
  55. template <typename...> class... Pack, typename... H, typename... T
  56. >
  57. struct any_n <F, Pack <H, T>...> : //two elements each, no need for double pack expansion on T
  58. std::conditional<F<H...>{}, std::true_type, any_n<F, typename toRecursiveList<T>::type...>>::type
  59. // ^ ensures a recursive list is passed onto the next recursion step
  60. {};
  61.  
  62. //recursion guard
  63. template
  64. <
  65. template <typename...> class F,
  66. template <typename...> class Pack, typename... T
  67. >
  68. struct any_n<F, Pack <>, T...> :
  69. std::false_type
  70. {};
  71.  
  72. template<typename...>
  73. struct is_same_n;
  74.  
  75. template<typename A, typename B, typename... T>
  76. struct is_same_n<A, B, T...> :
  77. std::conditional<std::is_same<A, B>{}, is_same_n<B, T...>, std::false_type>::type
  78. {};
  79.  
  80. template<typename A, typename B>
  81. struct is_same_n<A, B> :
  82. std::is_same<A, B>
  83. {};
  84.  
  85. template<typename...>
  86. struct Pack;
  87.  
  88. int main()
  89. {
  90.  
  91. typedef Pack<int, float, double, void> A;
  92. typedef Pack<void, float, double, void> B;
  93. typedef Pack<float, bool, double, void> C;
  94. typedef Pack<float, int, char, void> D;
  95. typedef Pack<bool, char, void, double> E;
  96.  
  97. assert((any_n <is_same_n, A, B>())); // true
  98. assert((any_n <is_same_n, A, B, C>())); // true
  99. assert((any_n <is_same_n, A, B, C, D>())); // true
  100. assert(!(any_n <is_same_n, A, B, C, D, E>())); // false
  101.  
  102. std::cout << "PASSED!" << std::endl;
  103.  
  104. return 0;
  105. }
  106.  
Success #stdin #stdout 0s 3340KB
stdin
Standard input is empty
stdout
PASSED!