Skip to content

Commit ead27ca

Browse files
authored
Feature/lambda (#96)
* added mp_lambda * launched GHA * skipped ICE-generating test in GCC < 4.9 * fixed GCC detection in workaround * test-skipped and documented GCC 4.8 bug * added missing s/const/CONST * tempirarily expanded macro to isolate problem with VS2017 * tried workaround for C3546 * tried another workaround * wrapped workaround up * dropped unnecessary devoiding in variadic (member) functions * temporary code to check VS compliance wrt function qualifiers * removed version printer * checked compliance with qualified (member) function partial specialization * checked each partial specialization individually * wrapped up VS2013 investigation * left variadics out of VS2013 * skipped noexcept-involving tests for VS2013 (keyword not supported) * given up on VS2013 support for mp_lambda * dropped lambda_devoid_args
1 parent 03a2d3a commit ead27ca

File tree

7 files changed

+397
-4
lines changed

7 files changed

+397
-4
lines changed

doc/mp11/changelog.adoc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
////
2-
Copyright 2019-2023 Peter Dimov
2+
Copyright 2019-2024 Peter Dimov
33

44
Distributed under the Boost Software License, Version 1.0.
55

@@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt
1010
[#changelog]
1111
# Revision History
1212

13+
## Changes in 1.87.0
14+
15+
* Added `mp_lambda`
16+
1317
## Changes in 1.85.0
1418

1519
* Added `mp_sliding_fold`, a generalization of `mp_pairwise_fold` (contributed by Braden Ganetsky)

doc/mp11/lambda.adoc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
////
2+
Copyright 2024 Joaquin M Lopez Munoz
3+
4+
Distributed under the Boost Software License, Version 1.0.
5+
6+
See accompanying file LICENSE_1_0.txt or copy at
7+
http://www.boost.org/LICENSE_1_0.txt
8+
////
9+
10+
[#lambda]
11+
# Lambda, <boost/mp11/lambda.hpp>
12+
:toc:
13+
:toc-title:
14+
:idprefix:
15+
16+
## mp_lambda<T>
17+
18+
template<class T> using mp_lambda = /*...*/;
19+
20+
`mp_lambda<T>` is a quoted metafunction whose nested template `fn<U...>`
21+
returns a type `V` with the same syntactic definition as `T`, except
22+
that occurrences of placeholders in `T` are replaced by the corresponding
23+
element of `U...`.
24+
25+
For example, `mp_lambda<std::pair<_1, _2*>>::fn<int, char>` is `std::pair<int, char*>`.
26+
27+
Replacement does not happen inside those constituent parts of `T` resulting
28+
from the instantiation of a class template with non-type template parameters.
29+
30+
NOTE: In GCC 4.8, a compiler bug results in `const` and `volatile` qualifiers
31+
being stripped from the returned type `V` (except when they are applied to
32+
function or member function types).
33+
34+
NOTE: `mp_lambda` is not supported in VS2013 and prior due to compiler limitations.

doc/mp11/reference.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
////
2-
Copyright 2017 Peter Dimov
2+
Copyright 2017-2024 Peter Dimov
33

44
Distributed under the Boost Software License, Version 1.0.
55

@@ -33,6 +33,8 @@ include::function.adoc[]
3333

3434
include::bind.adoc[]
3535

36+
include::lambda.adoc[]
37+
3638
include::integer_sequence.adoc[]
3739

3840
include::tuple.adoc[]

include/boost/mp11.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef BOOST_MP11_HPP_INCLUDED
22
#define BOOST_MP11_HPP_INCLUDED
33

4-
// Copyright 2015 Peter Dimov.
4+
// Copyright 2015-2024 Peter Dimov.
55
//
66
// Distributed under the Boost Software License, Version 1.0.
77
//
@@ -16,6 +16,7 @@
1616
#include <boost/mp11/map.hpp>
1717
#include <boost/mp11/set.hpp>
1818
#include <boost/mp11/bind.hpp>
19+
#include <boost/mp11/lambda.hpp>
1920
#include <boost/mp11/integer_sequence.hpp>
2021
#include <boost/mp11/tuple.hpp>
2122

include/boost/mp11/lambda.hpp

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
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

test/Jamfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Boost.Mp11 Library Test Jamfile
22
#
3-
# Copyright 2015-2019 Peter Dimov
3+
# Copyright 2015-2024 Peter Dimov
44
#
55
# Distributed under the Boost Software License, Version 1.0.
66
# See accompanying file LICENSE_1_0.txt or copy at
@@ -264,6 +264,9 @@ run mp_bind_q.cpp ;
264264
run mp_bind_front.cpp ;
265265
run mp_bind_back.cpp ;
266266

267+
# lambda
268+
run mp_lambda.cpp ;
269+
267270
# mpl
268271
run mpl.cpp : ;
269272
run mpl_list.cpp : ;

0 commit comments

Comments
 (0)