]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/yap/detail/algorithm.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / yap / detail / algorithm.hpp
1 // Copyright (C) 2016-2018 T. Zachary Laine
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef BOOST_YAP_DETAIL_EXPRESSION_HPP_INCLUDED
7 #define BOOST_YAP_DETAIL_EXPRESSION_HPP_INCLUDED
8
9 #include <boost/yap/algorithm_fwd.hpp>
10
11 #include <boost/hana/size.hpp>
12 #include <boost/hana/tuple.hpp>
13
14 #include <memory>
15 #include <type_traits>
16
17
18 namespace boost { namespace yap { namespace detail {
19
20 // static_const
21
22 template<typename T>
23 struct static_const
24 {
25 static constexpr T value{};
26 };
27
28 template<typename T>
29 constexpr T static_const<T>::value;
30
31
32 // partial_decay
33
34 template<typename T>
35 struct partial_decay
36 {
37 using type = T;
38 };
39
40 template<typename T>
41 struct partial_decay<T[]>
42 {
43 using type = T *;
44 };
45 template<typename T, std::size_t N>
46 struct partial_decay<T[N]>
47 {
48 using type = T *;
49 };
50
51 template<typename T>
52 struct partial_decay<T (&)[]>
53 {
54 using type = T *;
55 };
56 template<typename T, std::size_t N>
57 struct partial_decay<T (&)[N]>
58 {
59 using type = T *;
60 };
61
62 template<typename R, typename... A>
63 struct partial_decay<R(A...)>
64 {
65 using type = R (*)(A...);
66 };
67 template<typename R, typename... A>
68 struct partial_decay<R(A..., ...)>
69 {
70 using type = R (*)(A..., ...);
71 };
72
73 template<typename R, typename... A>
74 struct partial_decay<R (&)(A...)>
75 {
76 using type = R (*)(A...);
77 };
78 template<typename R, typename... A>
79 struct partial_decay<R (&)(A..., ...)>
80 {
81 using type = R (*)(A..., ...);
82 };
83
84 template<typename R, typename... A>
85 struct partial_decay<R (*&)(A...)>
86 {
87 using type = R (*)(A...);
88 };
89 template<typename R, typename... A>
90 struct partial_decay<R (*&)(A..., ...)>
91 {
92 using type = R (*)(A..., ...);
93 };
94
95
96 // operand_value_type_phase_1
97
98 template<
99 typename T,
100 typename U = typename detail::partial_decay<T>::type,
101 bool AddRValueRef = std::is_same<T, U>::value && !std::is_const<U>::value>
102 struct operand_value_type_phase_1;
103
104 template<typename T, typename U>
105 struct operand_value_type_phase_1<T, U, true>
106 {
107 using type = U &&;
108 };
109
110 template<typename T, typename U>
111 struct operand_value_type_phase_1<T, U, false>
112 {
113 using type = U;
114 };
115
116
117 // expr_ref
118
119 template<template<expr_kind, class> class ExprTemplate, typename T>
120 struct expr_ref
121 {
122 using type = expression_ref<ExprTemplate, T>;
123 };
124
125 template<template<expr_kind, class> class ExprTemplate, typename Tuple>
126 struct expr_ref<ExprTemplate, ExprTemplate<expr_kind::expr_ref, Tuple> &>
127 {
128 using type = ExprTemplate<expr_kind::expr_ref, Tuple>;
129 };
130
131 template<template<expr_kind, class> class ExprTemplate, typename Tuple>
132 struct expr_ref<
133 ExprTemplate,
134 ExprTemplate<expr_kind::expr_ref, Tuple> const &>
135 {
136 using type = ExprTemplate<expr_kind::expr_ref, Tuple>;
137 };
138
139 template<template<expr_kind, class> class ExprTemplate, typename T>
140 using expr_ref_t = typename expr_ref<ExprTemplate, T>::type;
141
142 template<template<expr_kind, class> class ExprTemplate, typename T>
143 struct expr_ref_tuple;
144
145 template<template<expr_kind, class> class ExprTemplate, typename Tuple>
146 struct expr_ref_tuple<
147 ExprTemplate,
148 ExprTemplate<expr_kind::expr_ref, Tuple>>
149 {
150 using type = Tuple;
151 };
152
153 template<template<expr_kind, class> class ExprTemplate, typename T>
154 using expr_ref_tuple_t = typename expr_ref_tuple<ExprTemplate, T>::type;
155
156
157 // operand_type
158
159 template<
160 template<expr_kind, class> class ExprTemplate,
161 typename T,
162 typename U = typename operand_value_type_phase_1<T>::type,
163 bool RemoveRefs = std::is_rvalue_reference<U>::value,
164 bool IsExpr = is_expr<T>::value,
165 bool IsLRef = std::is_lvalue_reference<T>::value>
166 struct operand_type;
167
168 template<
169 template<expr_kind, class> class ExprTemplate,
170 typename T,
171 typename U,
172 bool RemoveRefs>
173 struct operand_type<ExprTemplate, T, U, RemoveRefs, true, false>
174 {
175 using type = remove_cv_ref_t<T>;
176 };
177
178 template<
179 template<expr_kind, class> class ExprTemplate,
180 typename T,
181 typename U,
182 bool RemoveRefs>
183 struct operand_type<ExprTemplate, T, U, RemoveRefs, true, true>
184 {
185 using type = expr_ref_t<ExprTemplate, T>;
186 };
187
188 template<
189 template<expr_kind, class> class ExprTemplate,
190 typename T,
191 typename U,
192 bool RemoveRefs,
193 bool IsLRef>
194 struct operand_type<ExprTemplate, T, U, RemoveRefs, true, IsLRef>
195 {
196 using type = remove_cv_ref_t<T>;
197 };
198
199 template<
200 template<expr_kind, class> class ExprTemplate,
201 typename T,
202 typename U,
203 bool IsLRef>
204 struct operand_type<ExprTemplate, T, U, true, false, IsLRef>
205 {
206 using type = terminal<ExprTemplate, std::remove_reference_t<U>>;
207 };
208
209 template<
210 template<expr_kind, class> class ExprTemplate,
211 typename T,
212 typename U,
213 bool IsLRef>
214 struct operand_type<ExprTemplate, T, U, false, false, IsLRef>
215 {
216 using type = terminal<ExprTemplate, U>;
217 };
218
219 template<template<expr_kind, class> class ExprTemplate, typename T>
220 using operand_type_t = typename operand_type<ExprTemplate, T>::type;
221
222
223 // make_operand
224
225 template<typename T>
226 struct make_operand
227 {
228 template<typename U>
229 auto operator()(U && u)
230 {
231 return T{static_cast<U &&>(u)};
232 }
233 };
234
235 template<template<expr_kind, class> class ExprTemplate, typename Tuple>
236 struct make_operand<ExprTemplate<expr_kind::expr_ref, Tuple>>
237 {
238 auto operator()(ExprTemplate<expr_kind::expr_ref, Tuple> expr)
239 {
240 return expr;
241 }
242
243 template<typename U>
244 auto operator()(U && u)
245 {
246 return ExprTemplate<expr_kind::expr_ref, Tuple>{
247 Tuple{std::addressof(u)}};
248 }
249 };
250
251
252 // free_binary_op_result
253
254 template<
255 template<expr_kind, class> class ExprTemplate,
256 expr_kind OpKind,
257 typename T,
258 typename U,
259 bool TNonExprUExpr = !is_expr<T>::value && is_expr<U>::value,
260 bool ULvalueRef = std::is_lvalue_reference<U>::value>
261 struct free_binary_op_result;
262
263 template<
264 template<expr_kind, class> class ExprTemplate,
265 expr_kind OpKind,
266 typename T,
267 typename U>
268 struct free_binary_op_result<ExprTemplate, OpKind, T, U, true, true>
269 {
270 using lhs_type = operand_type_t<ExprTemplate, T>;
271 using rhs_type = expr_ref_t<ExprTemplate, U>;
272 using rhs_tuple_type = expr_ref_tuple_t<ExprTemplate, rhs_type>;
273 using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
274 };
275
276 template<
277 template<expr_kind, class> class ExprTemplate,
278 expr_kind OpKind,
279 typename T,
280 typename U>
281 struct free_binary_op_result<ExprTemplate, OpKind, T, U, true, false>
282 {
283 using lhs_type = operand_type_t<ExprTemplate, T>;
284 using rhs_type = remove_cv_ref_t<U>;
285 using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
286 };
287
288 template<
289 template<expr_kind, class> class ExprTemplate,
290 expr_kind OpKind,
291 typename T,
292 typename U>
293 using free_binary_op_result_t =
294 typename free_binary_op_result<ExprTemplate, OpKind, T, U>::type;
295
296
297 // ternary_op_result
298
299 template<
300 template<expr_kind, class> class ExprTemplate,
301 typename T,
302 typename U,
303 typename V,
304 bool Valid =
305 is_expr<T>::value || is_expr<U>::value || is_expr<V>::value>
306 struct ternary_op_result;
307
308 template<
309 template<expr_kind, class> class ExprTemplate,
310 typename T,
311 typename U,
312 typename V>
313 struct ternary_op_result<ExprTemplate, T, U, V, true>
314 {
315 using cond_type = operand_type_t<ExprTemplate, T>;
316 using then_type = operand_type_t<ExprTemplate, U>;
317 using else_type = operand_type_t<ExprTemplate, V>;
318 using type = ExprTemplate<
319 expr_kind::if_else,
320 hana::tuple<cond_type, then_type, else_type>>;
321 };
322
323 template<
324 template<expr_kind, class> class ExprTemplate,
325 typename T,
326 typename U,
327 typename V>
328 using ternary_op_result_t =
329 typename ternary_op_result<ExprTemplate, T, U, V>::type;
330
331
332 // udt_any_ternary_op_result
333
334 template<
335 template<expr_kind, class> class ExprTemplate,
336 typename T,
337 typename U,
338 typename V,
339 template<class> class UdtTrait,
340 bool Valid = !is_expr<T>::value && !is_expr<U>::value &&
341 !is_expr<V>::value &&
342 (UdtTrait<remove_cv_ref_t<T>>::value ||
343 UdtTrait<remove_cv_ref_t<U>>::value ||
344 UdtTrait<remove_cv_ref_t<V>>::value)>
345 struct udt_any_ternary_op_result;
346
347 template<
348 template<expr_kind, class> class ExprTemplate,
349 typename T,
350 typename U,
351 typename V,
352 template<class> class UdtTrait>
353 struct udt_any_ternary_op_result<ExprTemplate, T, U, V, UdtTrait, true>
354 {
355 using cond_type = operand_type_t<ExprTemplate, T>;
356 using then_type = operand_type_t<ExprTemplate, U>;
357 using else_type = operand_type_t<ExprTemplate, V>;
358 using type = ExprTemplate<
359 expr_kind::if_else,
360 hana::tuple<cond_type, then_type, else_type>>;
361 };
362
363 template<
364 template<expr_kind, class> class ExprTemplate,
365 typename T,
366 typename U,
367 typename V,
368 template<class> class UdtTrait>
369 using udt_any_ternary_op_result_t =
370 typename udt_any_ternary_op_result<ExprTemplate, T, U, V, UdtTrait>::
371 type;
372
373
374 // udt_unary_op_result
375
376 template<
377 template<expr_kind, class> class ExprTemplate,
378 expr_kind OpKind,
379 typename T,
380 template<class> class UdtTrait,
381 bool Valid = !is_expr<T>::value && UdtTrait<remove_cv_ref_t<T>>::value>
382 struct udt_unary_op_result;
383
384 template<
385 template<expr_kind, class> class ExprTemplate,
386 expr_kind OpKind,
387 typename T,
388 template<class> class UdtTrait>
389 struct udt_unary_op_result<ExprTemplate, OpKind, T, UdtTrait, true>
390 {
391 using x_type = operand_type_t<ExprTemplate, T>;
392 using type = ExprTemplate<OpKind, hana::tuple<x_type>>;
393 };
394
395 template<
396 template<expr_kind, class> class ExprTemplate,
397 expr_kind OpKind,
398 typename T,
399 template<class> class UdtTrait>
400 using udt_unary_op_result_t =
401 typename udt_unary_op_result<ExprTemplate, OpKind, T, UdtTrait>::type;
402
403
404 // udt_udt_binary_op_result
405
406 template<typename T, template<class> class UdtTrait>
407 struct is_udt_arg
408 {
409 static bool const value =
410 !is_expr<T>::value && UdtTrait<remove_cv_ref_t<T>>::value;
411 };
412
413 template<
414 template<expr_kind, class> class ExprTemplate,
415 expr_kind OpKind,
416 typename T,
417 typename U,
418 template<class> class TUdtTrait,
419 template<class> class UUdtTrait,
420 bool Valid =
421 is_udt_arg<T, TUdtTrait>::value && is_udt_arg<U, UUdtTrait>::value>
422 struct udt_udt_binary_op_result;
423
424 template<
425 template<expr_kind, class> class ExprTemplate,
426 expr_kind OpKind,
427 typename T,
428 typename U,
429 template<class> class TUdtTrait,
430 template<class> class UUdtTrait>
431 struct udt_udt_binary_op_result<
432 ExprTemplate,
433 OpKind,
434 T,
435 U,
436 TUdtTrait,
437 UUdtTrait,
438 true>
439 {
440 using lhs_type = operand_type_t<ExprTemplate, T>;
441 using rhs_type = operand_type_t<ExprTemplate, U>;
442 using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
443 };
444
445 template<
446 template<expr_kind, class> class ExprTemplate,
447 expr_kind OpKind,
448 typename T,
449 typename U,
450 template<class> class TUdtTrait,
451 template<class> class UUdtTrait>
452 using udt_udt_binary_op_result_t = typename udt_udt_binary_op_result<
453 ExprTemplate,
454 OpKind,
455 T,
456 U,
457 TUdtTrait,
458 UUdtTrait>::type;
459
460
461 // udt_any_binary_op_result
462
463 template<
464 template<expr_kind, class> class ExprTemplate,
465 expr_kind OpKind,
466 typename T,
467 typename U,
468 template<class> class UdtTrait,
469 bool Valid = !is_expr<T>::value && !is_expr<U>::value &&
470 (UdtTrait<remove_cv_ref_t<T>>::value ||
471 UdtTrait<remove_cv_ref_t<U>>::value)>
472 struct udt_any_binary_op_result;
473
474 template<
475 template<expr_kind, class> class ExprTemplate,
476 expr_kind OpKind,
477 typename T,
478 typename U,
479 template<class> class UdtTrait>
480 struct udt_any_binary_op_result<ExprTemplate, OpKind, T, U, UdtTrait, true>
481 {
482 using lhs_type = operand_type_t<ExprTemplate, T>;
483 using rhs_type = operand_type_t<ExprTemplate, U>;
484 using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
485 };
486
487 template<
488 template<expr_kind, class> class ExprTemplate,
489 expr_kind OpKind,
490 typename T,
491 typename U,
492 template<class> class UdtTrait>
493 using udt_any_binary_op_result_t = typename udt_any_binary_op_result<
494 ExprTemplate,
495 OpKind,
496 T,
497 U,
498 UdtTrait>::type;
499
500
501 // not_copy_or_move
502
503 template<typename LeftT, typename RightT>
504 struct copy_or_move : std::false_type
505 {
506 };
507
508 template<typename T>
509 struct copy_or_move<T, T const &> : std::true_type
510 {
511 };
512
513 template<typename T>
514 struct copy_or_move<T, T &> : std::true_type
515 {
516 };
517
518 template<typename T>
519 struct copy_or_move<T, T &&> : std::true_type
520 {
521 };
522
523
524 // expr_arity
525
526 enum class expr_arity { invalid, one, two, three, n };
527
528 template<expr_kind Kind>
529 constexpr expr_arity arity_of()
530 {
531 switch (Kind) {
532 case expr_kind::expr_ref:
533
534 case expr_kind::terminal:
535
536 // unary
537 case expr_kind::unary_plus: // +
538 case expr_kind::negate: // -
539 case expr_kind::dereference: // *
540 case expr_kind::complement: // ~
541 case expr_kind::address_of: // &
542 case expr_kind::logical_not: // !
543 case expr_kind::pre_inc: // ++
544 case expr_kind::pre_dec: // --
545 case expr_kind::post_inc: // ++(int)
546 case expr_kind::post_dec: // --(int)
547 return expr_arity::one;
548
549 // binary
550 case expr_kind::shift_left: // <<
551 case expr_kind::shift_right: // >>
552 case expr_kind::multiplies: // *
553 case expr_kind::divides: // /
554 case expr_kind::modulus: // %
555 case expr_kind::plus: // +
556 case expr_kind::minus: // -
557 case expr_kind::less: // <
558 case expr_kind::greater: // >
559 case expr_kind::less_equal: // <=
560 case expr_kind::greater_equal: // >=
561 case expr_kind::equal_to: // ==
562 case expr_kind::not_equal_to: // !=
563 case expr_kind::logical_or: // ||
564 case expr_kind::logical_and: // &&
565 case expr_kind::bitwise_and: // &
566 case expr_kind::bitwise_or: // |
567 case expr_kind::bitwise_xor: // ^
568 case expr_kind::comma: // :
569 case expr_kind::mem_ptr: // ->*
570 case expr_kind::assign: // =
571 case expr_kind::shift_left_assign: // <<=
572 case expr_kind::shift_right_assign: // >>=
573 case expr_kind::multiplies_assign: // *=
574 case expr_kind::divides_assign: // /=
575 case expr_kind::modulus_assign: // %=
576 case expr_kind::plus_assign: // +=
577 case expr_kind::minus_assign: // -=
578 case expr_kind::bitwise_and_assign: // &=
579 case expr_kind::bitwise_or_assign: // |=
580 case expr_kind::bitwise_xor_assign: // ^=
581 case expr_kind::subscript: // []
582 return expr_arity::two;
583
584 // ternary
585 case expr_kind::if_else: // (analogous to) ?:
586 return expr_arity::three;
587
588 // n-ary
589 case expr_kind::call: // ()
590 return expr_arity::n;
591
592 default: return expr_arity::invalid;
593 }
594 }
595
596 }}}
597
598 #endif