function.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. #elif defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
  65. template<class... T> using mp_all = mp_bool<(static_cast<bool>(T::value) && ...)>;
  66. #else
  67. template<class... T> using mp_all = mp_and<mp_to_bool<T>...>;
  68. #endif
  69. // mp_or<T...>
  70. namespace detail
  71. {
  72. template<class... T> struct mp_or_impl;
  73. } // namespace detail
  74. template<class... T> using mp_or = mp_to_bool< typename detail::mp_or_impl<T...>::type >;
  75. namespace detail
  76. {
  77. template<> struct mp_or_impl<>
  78. {
  79. using type = mp_false;
  80. };
  81. template<class T> struct mp_or_impl<T>
  82. {
  83. using type = T;
  84. };
  85. template<class T1, class... T> struct mp_or_impl<T1, T...>
  86. {
  87. using type = mp_eval_if< T1, T1, mp_or, T... >;
  88. };
  89. } // namespace detail
  90. // mp_any<T...>
  91. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356
  92. #if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
  93. template<class... T> using mp_any = mp_bool<(static_cast<bool>(T::value) || ...)>;
  94. #else
  95. template<class... T> using mp_any = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::value != 0 >;
  96. #endif
  97. // mp_same<T...>
  98. namespace detail
  99. {
  100. template<class... T> struct mp_same_impl;
  101. template<> struct mp_same_impl<>
  102. {
  103. using type = mp_true;
  104. };
  105. template<class T1, class... T> struct mp_same_impl<T1, T...>
  106. {
  107. using type = mp_all<std::is_same<T1, T>...>;
  108. };
  109. } // namespace detail
  110. template<class... T> using mp_same = typename detail::mp_same_impl<T...>::type;
  111. // mp_similar<T...>
  112. namespace detail
  113. {
  114. template<class... T> struct mp_similar_impl;
  115. template<> struct mp_similar_impl<>
  116. {
  117. using type = mp_true;
  118. };
  119. template<class T> struct mp_similar_impl<T>
  120. {
  121. using type = mp_true;
  122. };
  123. template<class T> struct mp_similar_impl<T, T>
  124. {
  125. using type = mp_true;
  126. };
  127. template<class T1, class T2> struct mp_similar_impl<T1, T2>
  128. {
  129. using type = mp_false;
  130. };
  131. template<template<class...> class L, class... T1, class... T2> struct mp_similar_impl<L<T1...>, L<T2...>>
  132. {
  133. using type = mp_true;
  134. };
  135. template<template<class...> class L, class... T> struct mp_similar_impl<L<T...>, L<T...>>
  136. {
  137. using type = mp_true;
  138. };
  139. template<class T1, class T2, class T3, class... T> struct mp_similar_impl<T1, T2, T3, T...>
  140. {
  141. 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... >;
  142. };
  143. } // namespace detail
  144. template<class... T> using mp_similar = typename detail::mp_similar_impl<T...>::type;
  145. #if BOOST_MP11_GCC
  146. # pragma GCC diagnostic push
  147. # pragma GCC diagnostic ignored "-Wsign-compare"
  148. #endif
  149. // mp_less<T1, T2>
  150. 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))>;
  151. #if BOOST_MP11_GCC
  152. # pragma GCC diagnostic pop
  153. #endif
  154. // mp_min<T...>
  155. template<class T1, class... T> using mp_min = mp_min_element<mp_list<T1, T...>, mp_less>;
  156. // mp_max<T...>
  157. template<class T1, class... T> using mp_max = mp_max_element<mp_list<T1, T...>, mp_less>;
  158. } // namespace mp11
  159. } // namespace boost
  160. #endif // #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED