function.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED
  2. #define BOOST_MP11_FUNCTION_HPP_INCLUDED
  3. // Copyright 2015-2019 Peter Dimov.
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. //
  7. // See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt
  9. #include <boost/mp11/integral.hpp>
  10. #include <boost/mp11/utility.hpp>
  11. #include <boost/mp11/detail/mp_list.hpp>
  12. #include <boost/mp11/detail/mp_count.hpp>
  13. #include <boost/mp11/detail/mp_plus.hpp>
  14. #include <boost/mp11/detail/mp_min_element.hpp>
  15. #include <boost/mp11/detail/mp_void.hpp>
  16. #include <boost/mp11/detail/config.hpp>
  17. #include <type_traits>
  18. namespace boost
  19. {
  20. namespace mp11
  21. {
  22. // mp_void<T...>
  23. // in detail/mp_void.hpp
  24. // mp_and<T...>
  25. #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1910 )
  26. namespace detail
  27. {
  28. template<class... T> struct mp_and_impl;
  29. } // namespace detail
  30. template<class... T> using mp_and = mp_to_bool< typename detail::mp_and_impl<T...>::type >;
  31. namespace detail
  32. {
  33. template<> struct mp_and_impl<>
  34. {
  35. using type = mp_true;
  36. };
  37. template<class T> struct mp_and_impl<T>
  38. {
  39. using type = T;
  40. };
  41. template<class T1, class... T> struct mp_and_impl<T1, T...>
  42. {
  43. using type = mp_eval_if< mp_not<T1>, T1, mp_and, T... >;
  44. };
  45. } // namespace detail
  46. #else
  47. namespace detail
  48. {
  49. template<class L, class E = void> struct mp_and_impl
  50. {
  51. using type = mp_false;
  52. };
  53. template<class... T> struct mp_and_impl< mp_list<T...>, mp_void<mp_if<T, void>...> >
  54. {
  55. using type = mp_true;
  56. };
  57. } // namespace detail
  58. template<class... T> using mp_and = typename detail::mp_and_impl<mp_list<T...>>::type;
  59. #endif
  60. // mp_all<T...>
  61. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86355
  62. #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 )
  63. template<class... T> using mp_all = mp_bool< mp_count_if< mp_list<T...>, mp_not >::value == 0 >;
  64. #else
  65. template<class... T> using mp_all = mp_bool< mp_count< mp_list<mp_to_bool<T>...>, mp_false >::value == 0 >;
  66. #endif
  67. // mp_or<T...>
  68. namespace detail
  69. {
  70. template<class... T> struct mp_or_impl;
  71. } // namespace detail
  72. template<class... T> using mp_or = mp_to_bool< typename detail::mp_or_impl<T...>::type >;
  73. namespace detail
  74. {
  75. template<> struct mp_or_impl<>
  76. {
  77. using type = mp_false;
  78. };
  79. template<class T> struct mp_or_impl<T>
  80. {
  81. using type = T;
  82. };
  83. template<class T1, class... T> struct mp_or_impl<T1, T...>
  84. {
  85. using type = mp_eval_if< T1, T1, mp_or, T... >;
  86. };
  87. } // namespace detail
  88. // mp_any<T...>
  89. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356
  90. #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 )
  91. template<class... T> using mp_any = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::value != 0 >;
  92. #else
  93. template<class... T> using mp_any = mp_bool< mp_count< mp_list<mp_to_bool<T>...>, mp_true >::value != 0 >;
  94. #endif
  95. // mp_same<T...>
  96. namespace detail
  97. {
  98. template<class... T> struct mp_same_impl;
  99. template<> struct mp_same_impl<>
  100. {
  101. using type = mp_true;
  102. };
  103. template<class T1, class... T> struct mp_same_impl<T1, T...>
  104. {
  105. using type = mp_bool< mp_count<mp_list<T...>, T1>::value == sizeof...(T) >;
  106. };
  107. } // namespace detail
  108. template<class... T> using mp_same = typename detail::mp_same_impl<T...>::type;
  109. // mp_similar<T...>
  110. namespace detail
  111. {
  112. template<class... T> struct mp_similar_impl;
  113. template<> struct mp_similar_impl<>
  114. {
  115. using type = mp_true;
  116. };
  117. template<class T> struct mp_similar_impl<T>
  118. {
  119. using type = mp_true;
  120. };
  121. template<class T> struct mp_similar_impl<T, T>
  122. {
  123. using type = mp_true;
  124. };
  125. template<class T1, class T2> struct mp_similar_impl<T1, T2>
  126. {
  127. using type = mp_false;
  128. };
  129. template<template<class...> class L, class... T1, class... T2> struct mp_similar_impl<L<T1...>, L<T2...>>
  130. {
  131. using type = mp_true;
  132. };
  133. template<template<class...> class L, class... T> struct mp_similar_impl<L<T...>, L<T...>>
  134. {
  135. using type = mp_true;
  136. };
  137. template<class T1, class T2, class T3, class... T> struct mp_similar_impl<T1, T2, T3, T...>
  138. {
  139. using type = mp_all< typename mp_similar_impl<T1, T2>::type, typename mp_similar_impl<T1, T3>::type, typename mp_similar_impl<T1, T>::type... >;
  140. };
  141. } // namespace detail
  142. template<class... T> using mp_similar = typename detail::mp_similar_impl<T...>::type;
  143. #if BOOST_MP11_GCC
  144. # pragma GCC diagnostic push
  145. # pragma GCC diagnostic ignored "-Wsign-compare"
  146. #endif
  147. // mp_less<T1, T2>
  148. template<class T1, class T2> using mp_less = mp_bool<(T1::value < 0 && T2::value >= 0) || ((T1::value < T2::value) && !(T1::value >= 0 && T2::value < 0))>;
  149. #if BOOST_MP11_GCC
  150. # pragma GCC diagnostic pop
  151. #endif
  152. // mp_min<T...>
  153. template<class T1, class... T> using mp_min = mp_min_element<mp_list<T1, T...>, mp_less>;
  154. // mp_max<T...>
  155. template<class T1, class... T> using mp_max = mp_max_element<mp_list<T1, T...>, mp_less>;
  156. } // namespace mp11
  157. } // namespace boost
  158. #endif // #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED