]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/yap/example/future_group.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / yap / example / future_group.cpp
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 //[ future_group
7 #include <boost/yap/algorithm.hpp>
8
9 #include <boost/hana/concat.hpp>
10
11
12 // A custom expression template for future groups. It supports operators ||
13 // and &&.
14 template <boost::yap::expr_kind Kind, typename Tuple>
15 struct future_expr
16 {
17 static boost::yap::expr_kind const kind = Kind;
18
19 future_expr (Tuple && tuple) :
20 elements (std::forward<Tuple &&>(tuple))
21 {}
22
23 Tuple elements;
24
25 // Returns the transformed/flattened expression.
26 auto get () const;
27 };
28
29 BOOST_YAP_USER_BINARY_OPERATOR(logical_or, future_expr, future_expr)
30 BOOST_YAP_USER_BINARY_OPERATOR(logical_and, future_expr, future_expr)
31
32 // A special-cased future terminal that matches the semantics from the
33 // original Proto example.
34 template <typename T>
35 struct future :
36 future_expr<boost::yap::expr_kind::terminal, boost::hana::tuple<T>>
37 {
38 future (T const & t = T()) :
39 future_expr<boost::yap::expr_kind::terminal, boost::hana::tuple<T>> (boost::hana::tuple<T>{t})
40 {}
41
42 T get () const
43 { return boost::yap::value(*this); }
44 };
45
46 template <typename T>
47 using remove_cv_ref_t = std::remove_cv_t<std::remove_reference_t<T>>;
48
49 // A transform that flattens future expressions into a tuple.
50 struct future_transform
51 {
52 // Transform a terminal into its contained tuple.
53 template <typename T>
54 auto operator() (
55 future_expr<
56 boost::yap::expr_kind::terminal,
57 boost::hana::tuple<T>
58 > const & term
59 ) {
60 return term.elements;
61 }
62
63 //[ expr_xform
64 // Transform left || right -> transform(left).
65 template <typename T, typename U>
66 auto operator() (
67 future_expr<
68 boost::yap::expr_kind::logical_or,
69 boost::hana::tuple<T, U>
70 > const & or_expr
71 ) {
72 // Recursively transform the left side, and return the result.
73 // Without the recursion, we might return a terminal expression here
74 // insead of a tuple.
75 return boost::yap::transform(boost::yap::left(or_expr), *this);
76 }
77 //]
78
79 // Transform left && right -> concat(transform(left), transform(right)).
80 template <typename T, typename U>
81 auto operator() (
82 future_expr<
83 boost::yap::expr_kind::logical_and,
84 boost::hana::tuple<T, U>
85 > const & and_expr
86 ) {
87 // Recursively transform each side, then combine the resulting tuples
88 // into a single tuple result.
89 return boost::hana::concat(
90 boost::yap::transform(boost::yap::left(and_expr), *this),
91 boost::yap::transform(boost::yap::right(and_expr), *this)
92 );
93 }
94 };
95
96
97 template <boost::yap::expr_kind Kind, typename Tuple>
98 auto future_expr<Kind, Tuple>::get () const
99 { return boost::yap::transform(*this, future_transform{}); }
100
101
102 // TEST CASES
103 struct A {};
104 struct B {};
105 struct C {};
106
107 // Called "vector" just so the code in main() will match the original Proto
108 // example.
109 template <typename ...T>
110 using vector = boost::hana::tuple<T...>;
111
112 int main()
113 {
114 future<A> a;
115 future<B> b;
116 future<C> c;
117 future<vector<A,B> > ab;
118
119 // Verify that various future groups have the
120 // correct return types.
121 A t0 = a.get();
122 vector<A, B, C> t1 = (a && b && c).get();
123 vector<A, C> t2 = ((a || a) && c).get();
124 vector<A, B, C> t3 = ((a && b || a && b) && c).get();
125 vector<vector<A, B>, C> t4 = ((ab || ab) && c).get();
126
127 return 0;
128 }
129 //]