lambda.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #ifndef BOOST_MP11_LAMBDA_HPP_INCLUDED
  2. #define BOOST_MP11_LAMBDA_HPP_INCLUDED
  3. // Copyright 2024 Joaquin M Lopez Munoz.
  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/detail/config.hpp>
  10. #if BOOST_MP11_WORKAROUND(BOOST_MP11_MSVC, <= 1800)
  11. // mp_lambda not supported due to compiler limitations
  12. #else
  13. #include <boost/mp11/bind.hpp>
  14. #include <cstddef>
  15. #include <type_traits>
  16. #if defined(_MSC_VER) || defined(__GNUC__)
  17. # pragma push_macro( "I" )
  18. # undef I
  19. #endif
  20. namespace boost
  21. {
  22. namespace mp11
  23. {
  24. namespace detail
  25. {
  26. template<class T> struct lambda_impl;
  27. } // namespace detail
  28. // mp_lambda
  29. template<class T> using mp_lambda = typename detail::lambda_impl<T>::type;
  30. namespace detail
  31. {
  32. // base case (no placeholder replacement)
  33. template<class T> struct lambda_impl
  34. {
  35. template<class... U> using make = T;
  36. using type = mp_bind<make>;
  37. };
  38. // placeholders (behave directly as mp_bind expressions)
  39. template<std::size_t I> struct lambda_impl<mp_arg<I>>
  40. {
  41. using type = mp_arg<I>;
  42. };
  43. #define BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(name, compound_type) \
  44. template<class T> using lambda_make_##name = compound_type; \
  45. \
  46. template<class T> struct lambda_impl<compound_type> \
  47. { \
  48. using type = mp_bind<lambda_make_##name, mp_lambda<T>>; \
  49. };
  50. // [basic.type.qualifier]
  51. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(const, const T)
  52. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(volatile, volatile T)
  53. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(const_volatile, const volatile T)
  54. // [dcl.ptr]
  55. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(pointer, T*)
  56. // [dcl.ref]
  57. // GCC < 7 fails with template<class U> using make = U&;
  58. template<class T> struct lambda_impl<T&>
  59. {
  60. template<class U> using make = typename std::add_lvalue_reference<U>::type;
  61. using type = mp_bind<make, mp_lambda<T>>;
  62. };
  63. template<class T> struct lambda_impl<T&&>
  64. {
  65. template<class U> using make = typename std::add_rvalue_reference<U>::type;
  66. using type = mp_bind<make, mp_lambda<T>>;
  67. };
  68. // [dcl.array]
  69. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL(array, T[])
  70. #undef BOOST_MP11_SPECIALIZE_LAMBDA_IMPL
  71. template<class T, std::size_t N> struct lambda_impl<T[N]>
  72. {
  73. template<class Q> using make = Q[N];
  74. using type = mp_bind<make, mp_lambda<T>>;
  75. };
  76. // [dcl.fct], [dcl.mptr] (member functions)
  77. #define BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(name, qualifier) \
  78. template<class R, class... T> using lambda_make_fct_##name = R(T...) qualifier; \
  79. \
  80. template<class R, class... T> struct lambda_impl<R(T...) qualifier> \
  81. { \
  82. using type = mp_bind< \
  83. lambda_make_fct_##name, \
  84. mp_lambda<R>, mp_lambda<T>...>; \
  85. }; \
  86. \
  87. template<class R, class... T> using lambda_make_fct_##name##_ellipsis = \
  88. R(T..., ...) qualifier; \
  89. \
  90. template<class R, class... T> struct lambda_impl<R(T..., ...) qualifier> \
  91. { \
  92. using type = mp_bind< \
  93. lambda_make_fct_##name##_ellipsis, \
  94. mp_lambda<R>, mp_lambda<T>...>; \
  95. }; \
  96. \
  97. template<class R, class C, class... T> using lambda_make_mfptr_##name = \
  98. R (C::*)(T...) qualifier; \
  99. \
  100. template<class R, class C, class... T> struct lambda_impl<R (C::*)(T...) qualifier> \
  101. { \
  102. using type = mp_bind< \
  103. lambda_make_mfptr_##name, \
  104. mp_lambda<R>, mp_lambda<C>, mp_lambda<T>...>; \
  105. }; \
  106. \
  107. template<class R, class C, class... T> using lambda_make_mfptr_##name##_ellipsis = \
  108. R (C::*)(T..., ...) qualifier; \
  109. \
  110. template<class R, class C, class... T> struct lambda_impl<R (C::*)(T..., ...) qualifier> \
  111. { \
  112. using type = mp_bind< \
  113. lambda_make_mfptr_##name##_ellipsis, \
  114. mp_lambda<R>, mp_lambda<C>, mp_lambda<T>...>; \
  115. };
  116. #define BOOST_MP11_LAMBDA_EMPTY()
  117. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(no_qualifier, BOOST_MP11_LAMBDA_EMPTY())
  118. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const, const)
  119. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile, volatile)
  120. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile, const volatile)
  121. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(ref, &)
  122. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_ref, const&)
  123. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_ref, volatile&)
  124. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_ref, const volatile&)
  125. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(rvalue_ref, &&)
  126. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_rvalue_ref, const&&)
  127. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_rvalue_ref, volatile&&)
  128. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_rvalue_ref, const volatile&&)
  129. #if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L
  130. // P0012R1: exception specification as part of the type system
  131. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(noexcept, noexcept)
  132. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_noexcept, const noexcept)
  133. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_noexcept, volatile noexcept)
  134. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_noexcept, const volatile noexcept)
  135. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(ref_noexcept, & noexcept)
  136. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_ref_noexcept, const& noexcept)
  137. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_ref_noexcept, volatile& noexcept)
  138. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_ref_noexcept, const volatile& noexcept)
  139. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(rvalue_ref_noexcept, && noexcept)
  140. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_rvalue_ref_noexcept, const&& noexcept)
  141. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(volatile_rvalue_ref_noexcept, volatile&& noexcept)
  142. BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR(const_volatile_rvalue_ref_noexcept, const volatile&& noexcept)
  143. #endif // P0012R1
  144. #undef BOOST_MP11_LAMBDA_EMPTY
  145. #undef BOOST_MP11_SPECIALIZE_LAMBDA_IMPL_FCT_AND_MFPTR
  146. // [dcl.mptr] (data members)
  147. template<class T, class C> struct lambda_impl<T C::*>
  148. {
  149. template<class U, class D> using make = U D::*;
  150. using type = mp_bind<make, mp_lambda<T>, mp_lambda<C>>;
  151. };
  152. // template class instantiation
  153. template<template <class...> class C, class... Ts> struct lambda_impl<C<Ts...>>
  154. {
  155. using type = mp_bind<C, mp_lambda<Ts>...>;
  156. };
  157. } // namespace detail
  158. } // namespace mp11
  159. } // namespace boost
  160. #if defined(_MSC_VER) || defined(__GNUC__)
  161. # pragma pop_macro( "I" )
  162. #endif
  163. #endif // mp_lambda supported
  164. #endif // #ifndef BOOST_MP11_LAMBDA_HPP_INCLUDED