1/*=============================================================================
2 Copyright (c) 2014 Paul Fultz II
3 placeholders.h
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6==============================================================================*/
7
8#ifndef BOOST_HOF_GUARD_FUNCTION_PLACEHOLDERS_H
9#define BOOST_HOF_GUARD_FUNCTION_PLACEHOLDERS_H
10
11/// placeholders
12/// ============
13///
14/// Description
15/// -----------
16///
17/// The placeholders provide `std::bind` compatible placeholders that
18/// additionally provide basic C++ operators that creates bind expressions.
19/// Each bind expression supports `constexpr` function evaluation.
20///
21/// Synopsis
22/// --------
23///
24/// namespace placeholders {
25/// placeholder<1> _1 = {};
26/// placeholder<2> _2 = {};
27/// placeholder<3> _3 = {};
28/// placeholder<4> _4 = {};
29/// placeholder<5> _5 = {};
30/// placeholder<6> _6 = {};
31/// placeholder<7> _7 = {};
32/// placeholder<8> _8 = {};
33/// placeholder<9> _9 = {};
34/// }
35///
36/// Operators
37/// ---------
38///
39/// * Binary operators: +,-,*,/,%,>>,<<,>,<,<=,>=,==,!=,&,^,|,&&,||
40/// * Assign operators: +=,-=,*=,/=,%=,>>=,<<=,&=,|=,^=
41/// * Unary operators: !,~,+,-,*,++,--
42///
43///
44/// Example
45/// -------
46///
47/// #include <boost/hof.hpp>
48/// #include <cassert>
49/// using namespace boost::hof;
50///
51/// int main() {
52/// auto sum = _1 + _2;
53/// assert(3 == sum(1, 2));
54/// }
55///
56///
57/// unamed placeholder
58/// ==================
59///
60/// Description
61/// -----------
62///
63/// The unamed placeholder can be used to build simple functions from C++
64/// operators.
65///
66/// Note: The function produced by the unamed placeholder is not a bind expression.
67///
68/// Synopsis
69/// --------
70///
71/// namespace placeholders {
72/// /* unspecified */ _ = {};
73/// }
74///
75/// Example
76/// -------
77///
78/// #include <boost/hof.hpp>
79/// #include <cassert>
80/// using namespace boost::hof;
81///
82/// int main() {
83/// auto sum = _ + _;
84/// assert(3 == sum(1, 2));
85/// }
86///
87
88#include <boost/hof/returns.hpp>
89#include <boost/hof/lazy.hpp>
90#include <boost/hof/protect.hpp>
91
92#if defined(_MSC_VER) && _MSC_VER >= 1910
93#include <boost/hof/detail/pp.hpp>
94#endif
95
96namespace boost { namespace hof { namespace detail {
97 template<int N>
98 struct simple_placeholder
99 {};
100}}} // namespace boost::hof
101
102namespace std {
103 template<int N>
104 struct is_placeholder<boost::hof::detail::simple_placeholder<N>>
105 : std::integral_constant<int, N>
106 {};
107}
108
109
110namespace boost { namespace hof {
111
112#define BOOST_HOF_FOREACH_BINARY_OP(m) \
113 m(+, add) \
114 m(-, subtract) \
115 m(*, multiply) \
116 m(/, divide) \
117 m(%, remainder) \
118 m(>>, shift_right) \
119 m(<<, shift_left) \
120 m(>, greater_than) \
121 m(<, less_than) \
122 m(<=, less_than_equal) \
123 m(>=, greater_than_equal) \
124 m(==, equal) \
125 m(!=, not_equal) \
126 m(&, bit_and) \
127 m(^, xor_) \
128 m(|, bit_or) \
129 m(&&, and_) \
130 m(||, or_)
131
132#define BOOST_HOF_FOREACH_ASSIGN_OP(m) \
133 m(+=, assign_add) \
134 m(-=, assign_subtract) \
135 m(*=, assign_multiply) \
136 m(/=, assign_divide) \
137 m(%=, assign_remainder) \
138 m(>>=, assign_right_shift) \
139 m(<<=, assign_left_shift) \
140 m(&=, assign_bit_and) \
141 m(|=, assign_bit_or) \
142 m(^=, assign_xor)
143
144#ifndef _MSC_VER
145#define BOOST_HOF_FOREACH_UNARY_OP(m) \
146 m(!, not_) \
147 m(~, compl_) \
148 m(+, unary_plus) \
149 m(-, unary_subtract) \
150 m(*, dereference) \
151 m(++, increment) \
152 m(--, decrement)
153#else
154#define BOOST_HOF_FOREACH_UNARY_OP(m) \
155 m(!, not_) \
156 m(~, compl_) \
157 m(+, unary_plus) \
158 m(-, unary_subtract) \
159 m(*, dereference)
160#endif
161
162namespace operators {
163
164struct call
165{
166 template<class F, class... Ts>
167 constexpr auto operator()(F&& f, Ts&&... xs) const BOOST_HOF_RETURNS
168 (f(BOOST_HOF_FORWARD(Ts)(xs)...));
169};
170
171// MSVC 2017 ICEs on && and || in conxtexpr, so we fallback on bitwise operators
172#if defined(_MSC_VER) && _MSC_VER >= 1910
173#define BOOST_HOF_BINARY_OP_SKIP_and_ ()
174#define BOOST_HOF_BINARY_OP_SKIP_or_ ()
175
176struct and_
177{
178 template<class T, class U>
179 constexpr auto operator()(T&& x, U&& y) const
180 noexcept(noexcept(BOOST_HOF_FORWARD(T)(x) && BOOST_HOF_FORWARD(U)(y)))
181 -> decltype(BOOST_HOF_FORWARD(T)(x) && BOOST_HOF_FORWARD(U)(y))
182 { return BOOST_HOF_FORWARD(T)(x) & BOOST_HOF_FORWARD(U)(y); }
183};
184
185struct or_
186{
187 template<class T, class U>
188 constexpr auto operator()(T&& x, U&& y) const
189 noexcept(noexcept(BOOST_HOF_FORWARD(T)(x) || BOOST_HOF_FORWARD(U)(y)))
190 -> decltype(BOOST_HOF_FORWARD(T)(x) || BOOST_HOF_FORWARD(U)(y))
191 { return BOOST_HOF_FORWARD(T)(x) | BOOST_HOF_FORWARD(U)(y); }
192};
193
194#define BOOST_HOF_BINARY_OP_IMPL(op, name) \
195 struct name \
196 { \
197 template<class T, class U> \
198 BOOST_HOF_USING(ex_failure, decltype(std::declval<T>() op std::declval<U>())); \
199 struct failure : as_failure<ex_failure> {}; \
200 template<class T, class U> \
201 constexpr auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS \
202 (BOOST_HOF_FORWARD(T)(x) op BOOST_HOF_FORWARD(U)(y)); \
203 };
204
205#define BOOST_HOF_BINARY_OP(op, name) \
206 BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_PP_CAT(BOOST_HOF_BINARY_OP_SKIP_, name))) \
207 (BOOST_HOF_PP_EMPTY, BOOST_HOF_BINARY_OP_IMPL)(op, name)
208
209#else
210
211#define BOOST_HOF_BINARY_OP(op, name) \
212 struct name \
213 { \
214 template<class T, class U> \
215 constexpr auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS \
216 (BOOST_HOF_FORWARD(T)(x) op BOOST_HOF_FORWARD(U)(y)); \
217 };
218
219#endif
220
221BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_BINARY_OP)
222BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_BINARY_OP)
223
224#define BOOST_HOF_UNARY_OP(op, name) \
225 struct name \
226 { \
227 template<class T> \
228 constexpr auto operator()(T&& x) const BOOST_HOF_RETURNS \
229 (op(BOOST_HOF_FORWARD(T)(x))); \
230 };
231
232
233BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_UNARY_OP)
234
235
236}
237
238template<int N>
239struct placeholder
240{
241#if BOOST_HOF_HAS_MANGLE_OVERLOAD
242 template<class... Ts>
243 constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
244 ( boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(Ts)(xs)...) );
245#else
246 template<class... Ts>
247 struct result_call
248 { typedef decltype(boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), std::declval<Ts>()...)) type; };
249 template<class... Ts>
250 constexpr typename result_call<Ts...>::type operator()(Ts&&... xs) const
251 { return boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(Ts)(xs)...); };
252
253#endif
254
255#define BOOST_HOF_PLACEHOLDER_UNARY_OP(op, name) \
256 constexpr auto operator op () const BOOST_HOF_RETURNS \
257 ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>()) );
258
259BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_PLACEHOLDER_UNARY_OP)
260
261#define BOOST_HOF_PLACEHOLDER_ASSIGN_OP(op, name) \
262 template<class T> \
263 constexpr auto operator op (T&& x) const BOOST_HOF_RETURNS \
264 ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)) );
265
266BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_PLACEHOLDER_ASSIGN_OP)
267
268};
269
270#if BOOST_HOF_HAS_MANGLE_OVERLOAD
271
272#define BOOST_HOF_PLACEHOLDER_BINARY_OP(op, name) \
273 template<class T, int N> \
274 constexpr inline auto operator op (const placeholder<N>&, T&& x) BOOST_HOF_RETURNS \
275 ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)) ); \
276 template<class T, int N> \
277 constexpr inline auto operator op (T&& x, const placeholder<N>&) BOOST_HOF_RETURNS \
278 ( boost::hof::lazy(operators::name())(BOOST_HOF_FORWARD(T)(x), detail::simple_placeholder<N>()) ); \
279 template<int N, int M> \
280 constexpr inline auto operator op (const placeholder<N>&, const placeholder<M>&) BOOST_HOF_RETURNS \
281 ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), detail::simple_placeholder<M>()) );
282
283#else
284
285#define BOOST_HOF_PLACEHOLDER_BINARY_OP(op, name) \
286 template<class T, class U> \
287 struct result_ ## name \
288 { typedef decltype(boost::hof::lazy(operators::name())(std::declval<T>(), std::declval<U>())) type; }; \
289 template<class T, int N> \
290 constexpr inline typename result_ ## name<detail::simple_placeholder<N>, T>::type operator op (const placeholder<N>&, T&& x) \
291 { return boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)); } \
292 template<class T, int N> \
293 constexpr inline typename result_ ## name<T, detail::simple_placeholder<N>>::type operator op (T&& x, const placeholder<N>&) \
294 { return boost::hof::lazy(operators::name())(BOOST_HOF_FORWARD(T)(x), detail::simple_placeholder<N>()); } \
295 template<int N, int M> \
296 constexpr inline typename result_ ## name<detail::simple_placeholder<N>, detail::simple_placeholder<M>>::type operator op (const placeholder<N>&, const placeholder<M>&) \
297 { return boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), detail::simple_placeholder<M>()); }
298
299#endif
300
301BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_PLACEHOLDER_BINARY_OP)
302
303namespace placeholders {
304BOOST_HOF_DECLARE_STATIC_VAR(_1, placeholder<1>);
305BOOST_HOF_DECLARE_STATIC_VAR(_2, placeholder<2>);
306BOOST_HOF_DECLARE_STATIC_VAR(_3, placeholder<3>);
307BOOST_HOF_DECLARE_STATIC_VAR(_4, placeholder<4>);
308BOOST_HOF_DECLARE_STATIC_VAR(_5, placeholder<5>);
309BOOST_HOF_DECLARE_STATIC_VAR(_6, placeholder<6>);
310BOOST_HOF_DECLARE_STATIC_VAR(_7, placeholder<7>);
311BOOST_HOF_DECLARE_STATIC_VAR(_8, placeholder<8>);
312BOOST_HOF_DECLARE_STATIC_VAR(_9, placeholder<9>);
313}
314
315using placeholders::_1;
316using placeholders::_2;
317using placeholders::_3;
318using placeholders::_4;
319using placeholders::_5;
320using placeholders::_6;
321using placeholders::_7;
322using placeholders::_8;
323using placeholders::_9;
324
325namespace detail {
326
327
328
329struct unamed_placeholder
330{
331template<class T, class Invoker>
332struct partial_ap
333{
334 T val;
335
336 BOOST_HOF_INHERIT_DEFAULT_EMPTY(partial_ap, T)
337
338 template<class X, class... Xs, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, X&&, Xs&&...)>
339 constexpr partial_ap(X&& x, Xs&&... xs) : val(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(Xs)(xs)...)
340 {}
341
342 BOOST_HOF_RETURNS_CLASS(partial_ap);
343
344 struct partial_ap_failure
345 {
346 template<class Failure>
347 struct apply
348 {
349 template<class... Xs>
350 struct of;
351
352 template<class X>
353 struct of<X>
354 : Failure::template of<typename std::add_const<T>::type, X>
355 {};
356 };
357 };
358
359 struct failure
360 : failure_map<partial_ap_failure, Invoker>
361 {};
362
363 template<class X>
364 constexpr BOOST_HOF_SFINAE_RESULT(const Invoker&, id_<T>, id_<X>)
365 operator()(X&& x) const BOOST_HOF_SFINAE_RETURNS
366 (
367 Invoker()(BOOST_HOF_CONST_THIS->val, BOOST_HOF_FORWARD(X)(x))
368 );
369};
370
371template<class Invoker, class T>
372static constexpr partial_ap<T, Invoker> make_partial_ap(T&& x)
373{
374 return {BOOST_HOF_FORWARD(T)(x)};
375}
376
377template<class Op>
378struct left
379{
380 struct failure
381 : failure_for<Op>
382 {};
383 template<class T, class X>
384 constexpr BOOST_HOF_SFINAE_RESULT(const Op&, id_<T>, id_<X>)
385 operator()(T&& val, X&& x) const BOOST_HOF_SFINAE_RETURNS
386 (Op()(BOOST_HOF_FORWARD(T)(val), BOOST_HOF_FORWARD(X)(x)));
387};
388
389template<class Op>
390struct right
391{
392 struct right_failure
393 {
394 template<class Failure>
395 struct apply
396 {
397 template<class T, class U, class... Ts>
398 struct of
399 : Failure::template of<U, T, Ts...>
400 {};
401 };
402 };
403
404 struct failure
405 : failure_map<right_failure, Op>
406 {};
407
408 template<class T, class X>
409 constexpr BOOST_HOF_SFINAE_RESULT(const Op&, id_<X>, id_<T>)
410 operator()(T&& val, X&& x) const BOOST_HOF_SFINAE_RETURNS
411 (Op()(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(T)(val)));
412};
413
414#define BOOST_HOF_UNAMED_PLACEHOLDER_UNARY_OP(op, name) \
415 constexpr auto operator op () const BOOST_HOF_RETURNS \
416 ( operators::name() );
417
418BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_UNAMED_PLACEHOLDER_UNARY_OP)
419
420#define BOOST_HOF_UNAMED_PLACEHOLDER_ASSIGN_OP(op, name) \
421 template<class T> \
422 constexpr auto operator op (const T& x) const BOOST_HOF_RETURNS \
423 ( partial_ap<T, left<operators::name>>(x) );
424
425BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_UNAMED_PLACEHOLDER_ASSIGN_OP)
426};
427#define BOOST_HOF_UNAMED_PLACEHOLDER_BINARY_OP(op, name) \
428 template<class T> \
429 constexpr inline auto operator op (const unamed_placeholder&, const T& x) BOOST_HOF_RETURNS \
430 ( unamed_placeholder::make_partial_ap<unamed_placeholder::right<operators::name>>(boost::hof::decay(x)) ); \
431 template<class T> \
432 constexpr inline auto operator op (const T& x, const unamed_placeholder&) BOOST_HOF_RETURNS \
433 ( unamed_placeholder::make_partial_ap<unamed_placeholder::left<operators::name>>(boost::hof::decay(x)) ); \
434 constexpr inline auto operator op (const unamed_placeholder&, const unamed_placeholder&) BOOST_HOF_RETURNS \
435 ( operators::name() );
436
437BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_UNAMED_PLACEHOLDER_BINARY_OP)
438}
439
440namespace placeholders {
441BOOST_HOF_DECLARE_STATIC_VAR(_, detail::unamed_placeholder);
442}
443
444using placeholders::_;
445
446}} // namespace boost::hof
447
448namespace std {
449 template<int N>
450 struct is_placeholder<boost::hof::placeholder<N>>
451 : std::integral_constant<int, N>
452 {};
453}
454
455namespace boost {
456
457 template<class T>
458 struct is_placeholder;
459
460 template<int N>
461 struct is_placeholder<boost::hof::placeholder<N>>
462 : std::integral_constant<int, N>
463 {};
464
465
466}
467
468#endif
469

source code of boost/libs/hof/include/boost/hof/placeholders.hpp