]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/hana/functional/placeholder.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / hana / functional / placeholder.hpp
1 /*!
2 @file
3 Defines `boost::hana::_`.
4
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 */
9
10 #ifndef BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
11 #define BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
12
13 #include <boost/hana/basic_tuple.hpp>
14 #include <boost/hana/config.hpp>
15 #include <boost/hana/detail/create.hpp>
16 #include <boost/hana/detail/decay.hpp>
17
18 #include <cstddef>
19 #include <utility>
20
21
22 BOOST_HANA_NAMESPACE_BEGIN
23 //! @ingroup group-functional
24 //! Create simple functions representing C++ operators inline.
25 //!
26 //! Specifically, `_` is an object used as a placeholder to build
27 //! function objects representing calls to C++ operators. It works
28 //! by overloading the operators between `_` and any object so that
29 //! they return a function object which actually calls the corresponding
30 //! operator on its argument(s). Hence, for any supported operator `@`:
31 //! @code
32 //! (_ @ _)(x, y) == x @ y
33 //! @endcode
34 //!
35 //! Operators may also be partially applied to one argument inline:
36 //! @code
37 //! (x @ _)(y) == x @ y
38 //! (_ @ y)(x) == x @ y
39 //! @endcode
40 //!
41 //! When invoked with more arguments than required, functions created with
42 //! `_` will discard the superfluous instead of triggering an error:
43 //! @code
44 //! (_ @ _)(x, y, z...) == x @ y
45 //! @endcode
46 //!
47 //! This makes functions created with `_` easier to use in higher-order
48 //! algorithms, which sometime provide more information than necessary
49 //! to their callbacks.
50 //!
51 //! ### Supported operators
52 //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
53 //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
54 //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
55 //! - %Logical: `||`, `&&`, `!`
56 //! - Member access: `*` (dereference), `[]` (array subscript)
57 //! - Other: `()` (function call)
58 //!
59 //! More complex functionality like the ability to compose placeholders
60 //! into larger function objects inline are not supported. This is on
61 //! purpose; you should either use C++14 generic lambdas or a library
62 //! like [Boost.Phoenix][] if you need bigger guns. The goal here is
63 //! to save you a couple of characters in simple situations.
64 //!
65 //! ### Example
66 //! @include example/functional/placeholder.cpp
67 //!
68 //! [Boost.Phoenix]: http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html
69 #ifdef BOOST_HANA_DOXYGEN_INVOKED
70 constexpr unspecified _{};
71 #else
72 namespace placeholder_detail {
73 template <typename I>
74 struct subscript {
75 I i;
76
77 template <typename Xs, typename ...Z>
78 constexpr auto operator()(Xs&& xs, Z const& ...) const&
79 -> decltype(static_cast<Xs&&>(xs)[i])
80 { return static_cast<Xs&&>(xs)[i]; }
81
82 template <typename Xs, typename ...Z>
83 constexpr auto operator()(Xs&& xs, Z const& ...) &
84 -> decltype(static_cast<Xs&&>(xs)[i])
85 { return static_cast<Xs&&>(xs)[i]; }
86
87 template <typename Xs, typename ...Z>
88 constexpr auto operator()(Xs&& xs, Z const& ...) &&
89 -> decltype(static_cast<Xs&&>(xs)[std::declval<I>()])
90 { return static_cast<Xs&&>(xs)[std::move(i)]; }
91 };
92
93 template <typename F, typename Xs, std::size_t ...i>
94 constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence<i...>) {
95 return static_cast<F&&>(f)(hana::at_c<i>(static_cast<Xs&&>(xs).storage_)...);
96 }
97
98 template <typename ...X>
99 struct invoke;
100
101 struct placeholder {
102 struct secret { };
103
104 template <typename X>
105 constexpr decltype(auto) operator[](X&& x) const
106 { return detail::create<subscript>{}(static_cast<X&&>(x)); }
107
108 template <typename ...X>
109 constexpr invoke<typename detail::decay<X>::type...>
110 operator()(X&& ...x) const {
111 return {secret{}, static_cast<X&&>(x)...};
112 }
113 };
114
115 template <typename ...X>
116 struct invoke {
117 template <typename ...Y>
118 constexpr invoke(placeholder::secret, Y&& ...y)
119 : storage_{static_cast<Y&&>(y)...}
120 { }
121
122 basic_tuple<X...> storage_;
123
124 template <typename F, typename ...Z>
125 constexpr auto operator()(F&& f, Z const& ...) const& -> decltype(
126 static_cast<F&&>(f)(std::declval<X const&>()...)
127 ) {
128 return invoke_impl(static_cast<F&&>(f), *this,
129 std::make_index_sequence<sizeof...(X)>{});
130 }
131
132 template <typename F, typename ...Z>
133 constexpr auto operator()(F&& f, Z const& ...) & -> decltype(
134 static_cast<F&&>(f)(std::declval<X&>()...)
135 ) {
136 return invoke_impl(static_cast<F&&>(f), *this,
137 std::make_index_sequence<sizeof...(X)>{});
138 }
139
140 template <typename F, typename ...Z>
141 constexpr auto operator()(F&& f, Z const& ...) && -> decltype(
142 static_cast<F&&>(f)(std::declval<X&&>()...)
143 ) {
144 return invoke_impl(static_cast<F&&>(f), static_cast<invoke&&>(*this),
145 std::make_index_sequence<sizeof...(X)>{});
146 }
147 };
148
149 #define BOOST_HANA_PLACEHOLDER_BINARY_OP(op, op_name) \
150 template <typename X> \
151 struct op_name ## _left { \
152 X x; \
153 \
154 template <typename Y, typename ...Z> \
155 constexpr auto operator()(Y&& y, Z const& ...) const& -> decltype( \
156 std::declval<X const&>() op static_cast<Y&&>(y)) \
157 { return x op static_cast<Y&&>(y); } \
158 \
159 template <typename Y, typename ...Z> \
160 constexpr auto operator()(Y&& y, Z const& ...) & -> decltype( \
161 std::declval<X&>() op static_cast<Y&&>(y)) \
162 { return x op static_cast<Y&&>(y); } \
163 \
164 template <typename Y, typename ...Z> \
165 constexpr auto operator()(Y&& y, Z const& ...) && -> decltype( \
166 std::declval<X>() op static_cast<Y&&>(y)) \
167 { return std::move(x) op static_cast<Y&&>(y); } \
168 }; \
169 \
170 template <typename Y> \
171 struct op_name ## _right { \
172 Y y; \
173 \
174 template <typename X, typename ...Z> \
175 constexpr auto operator()(X&& x, Z const& ...) const& -> decltype( \
176 static_cast<X&&>(x) op std::declval<Y const&>()) \
177 { return static_cast<X&&>(x) op y; } \
178 \
179 template <typename X, typename ...Z> \
180 constexpr auto operator()(X&& x, Z const& ...) & -> decltype( \
181 static_cast<X&&>(x) op std::declval<Y&>()) \
182 { return static_cast<X&&>(x) op y; } \
183 \
184 template <typename X, typename ...Z> \
185 constexpr auto operator()(X&& x, Z const& ...) && -> decltype( \
186 static_cast<X&&>(x) op std::declval<Y>()) \
187 { return static_cast<X&&>(x) op std::move(y); } \
188 }; \
189 \
190 struct op_name { \
191 template <typename X, typename Y, typename ...Z> \
192 constexpr auto operator()(X&& x, Y&& y, Z const& ...) const -> decltype(\
193 static_cast<X&&>(x) op static_cast<Y&&>(y)) \
194 { return static_cast<X&&>(x) op static_cast<Y&&>(y); } \
195 }; \
196 \
197 template <typename X> \
198 constexpr decltype(auto) operator op (X&& x, placeholder) \
199 { return detail::create<op_name ## _left>{}(static_cast<X&&>(x)); } \
200 \
201 template <typename Y> \
202 constexpr decltype(auto) operator op (placeholder, Y&& y) \
203 { return detail::create<op_name ## _right>{}(static_cast<Y&&>(y)); } \
204 \
205 inline constexpr decltype(auto) operator op (placeholder, placeholder) \
206 { return op_name{}; } \
207 /**/
208
209 #define BOOST_HANA_PLACEHOLDER_UNARY_OP(op, op_name) \
210 struct op_name { \
211 template <typename X, typename ...Z> \
212 constexpr auto operator()(X&& x, Z const& ...) const \
213 -> decltype(op static_cast<X&&>(x)) \
214 { return op static_cast<X&&>(x); } \
215 }; \
216 \
217 inline constexpr decltype(auto) operator op (placeholder) \
218 { return op_name{}; } \
219 /**/
220 // Arithmetic
221 BOOST_HANA_PLACEHOLDER_UNARY_OP(+, unary_plus)
222 BOOST_HANA_PLACEHOLDER_UNARY_OP(-, unary_minus)
223 BOOST_HANA_PLACEHOLDER_BINARY_OP(+, plus)
224 BOOST_HANA_PLACEHOLDER_BINARY_OP(-, minus)
225 BOOST_HANA_PLACEHOLDER_BINARY_OP(*, times)
226 BOOST_HANA_PLACEHOLDER_BINARY_OP(/, divide)
227 BOOST_HANA_PLACEHOLDER_BINARY_OP(%, modulo)
228
229 // Bitwise
230 BOOST_HANA_PLACEHOLDER_UNARY_OP(~, bitwise_not)
231 BOOST_HANA_PLACEHOLDER_BINARY_OP(&, bitwise_and)
232 BOOST_HANA_PLACEHOLDER_BINARY_OP(|, bitwise_or)
233 BOOST_HANA_PLACEHOLDER_BINARY_OP(^, bitwise_xor)
234 BOOST_HANA_PLACEHOLDER_BINARY_OP(<<, left_shift)
235 BOOST_HANA_PLACEHOLDER_BINARY_OP(>>, right_shift)
236
237 // Comparison
238 BOOST_HANA_PLACEHOLDER_BINARY_OP(==, equal)
239 BOOST_HANA_PLACEHOLDER_BINARY_OP(!=, not_equal)
240 BOOST_HANA_PLACEHOLDER_BINARY_OP(<, less)
241 BOOST_HANA_PLACEHOLDER_BINARY_OP(<=, less_equal)
242 BOOST_HANA_PLACEHOLDER_BINARY_OP(>, greater)
243 BOOST_HANA_PLACEHOLDER_BINARY_OP(>=, greater_equal)
244
245 // Logical
246 BOOST_HANA_PLACEHOLDER_BINARY_OP(||, logical_or)
247 BOOST_HANA_PLACEHOLDER_BINARY_OP(&&, logical_and)
248 BOOST_HANA_PLACEHOLDER_UNARY_OP(!, logical_not)
249
250 // Member access (array subscript is a member function)
251 BOOST_HANA_PLACEHOLDER_UNARY_OP(*, dereference)
252
253 // Other (function call is a member function)
254
255 #undef BOOST_HANA_PREFIX_PLACEHOLDER_OP
256 #undef BOOST_HANA_BINARY_PLACEHOLDER_OP
257 } // end namespace placeholder_detail
258
259 constexpr placeholder_detail::placeholder _{};
260 #endif
261 BOOST_HANA_NAMESPACE_END
262
263 #endif // !BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP