function.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 100000 )
  62. template<class... T> using mp_all = mp_bool< mp_count_if< mp_list<T...>, mp_not >::value == 0 >;
  63. #elif defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
  64. template<class... T> using mp_all = mp_bool<(static_cast<bool>(T::value) && ...)>;
  65. #else
  66. template<class... T> using mp_all = mp_and<mp_to_bool<T>...>;
  67. #endif
  68. // mp_or<T...>
  69. namespace detail
  70. {
  71. template<class... T> struct mp_or_impl;
  72. } // namespace detail
  73. template<class... T> using mp_or = mp_to_bool< typename detail::mp_or_impl<T...>::type >;
  74. namespace detail
  75. {
  76. template<> struct mp_or_impl<>
  77. {
  78. using type = mp_false;
  79. };
  80. template<class T> struct mp_or_impl<T>
  81. {
  82. using type = T;
  83. };
  84. template<class T1, class... T> struct mp_or_impl<T1, T...>
  85. {
  86. using type = mp_eval_if< T1, T1, mp_or, T... >;
  87. };
  88. } // namespace detail
  89. // mp_any<T...>
  90. #if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 100000 ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
  91. template<class... T> using mp_any = mp_bool<(static_cast<bool>(T::value) || ...)>;
  92. #else
  93. template<class... T> using mp_any = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::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_all<std::is_same<T1, 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<class T1, class T2, class T3, class... T> struct mp_similar_impl<T1, T2, T3, T...>
  134. {
  135. 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... >;
  136. };
  137. } // namespace detail
  138. template<class... T> using mp_similar = typename detail::mp_similar_impl<T...>::type;
  139. #if BOOST_MP11_GCC
  140. # pragma GCC diagnostic push
  141. # pragma GCC diagnostic ignored "-Wsign-compare"
  142. #endif
  143. // mp_less<T1, T2>
  144. 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))>;
  145. #if BOOST_MP11_GCC
  146. # pragma GCC diagnostic pop
  147. #endif
  148. // mp_min<T...>
  149. template<class T1, class... T> using mp_min = mp_min_element<mp_list<T1, T...>, mp_less>;
  150. // mp_max<T...>
  151. template<class T1, class... T> using mp_max = mp_max_element<mp_list<T1, T...>, mp_less>;
  152. } // namespace mp11
  153. } // namespace boost
  154. #endif // #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED