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