]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/yap/example/tarray.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / yap / example / tarray.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 //[ tarray
7 #include <boost/yap/algorithm.hpp>
8 #include <boost/yap/print.hpp>
9
10 #include <array>
11 #include <iostream>
12
13
14 template <boost::yap::expr_kind Kind, typename Tuple>
15 struct tarray_expr;
16
17
18 struct take_nth
19 {
20 boost::yap::terminal<tarray_expr, int>
21 operator() (boost::yap::terminal<tarray_expr, std::array<int, 3>> const & expr);
22
23 std::size_t n;
24 };
25
26 // Another custom expression template. In this case, we static_assert() that
27 // it only gets instantiated with terminals with pre-approved value types.
28 template <boost::yap::expr_kind Kind, typename Tuple>
29 struct tarray_expr
30 {
31 // Make sure that, if this expression is a terminal, its value is one we
32 // want to support. Note that the presence of expr_kind::expr_ref makes
33 // life slightly more difficult; we have to account for int const & and
34 // int & as well as int.
35 static_assert(
36 Kind != boost::yap::expr_kind::terminal ||
37 std::is_same<Tuple, boost::hana::tuple<int const &>>{} ||
38 std::is_same<Tuple, boost::hana::tuple<int &>>{} ||
39 std::is_same<Tuple, boost::hana::tuple<int>>{} ||
40 std::is_same<Tuple, boost::hana::tuple<std::array<int, 3>>>{},
41 "tarray_expr instantiated with an unsupported terminal type."
42 );
43
44 static const boost::yap::expr_kind kind = Kind;
45
46 Tuple elements;
47
48 int operator[] (std::size_t n) const
49 { return boost::yap::evaluate(boost::yap::transform(*this, take_nth{n})); }
50 };
51
52 // Define operators +, -, *, and /.
53 BOOST_YAP_USER_BINARY_OPERATOR(plus, tarray_expr, tarray_expr)
54 BOOST_YAP_USER_BINARY_OPERATOR(minus, tarray_expr, tarray_expr)
55 BOOST_YAP_USER_BINARY_OPERATOR(multiplies, tarray_expr, tarray_expr)
56 BOOST_YAP_USER_BINARY_OPERATOR(divides, tarray_expr, tarray_expr)
57
58
59 boost::yap::terminal<tarray_expr, int>
60 take_nth::operator() (boost::yap::terminal<tarray_expr, std::array<int, 3>> const & expr)
61 {
62 int x = boost::yap::value(expr)[n];
63 // Again, this is the move hack to get x into the resulting terminal as a
64 // value instead of a reference.
65 return boost::yap::make_terminal<tarray_expr>(std::move(x));
66 }
67
68
69 // Stream-out operators for the two kinds of terminals we support.
70
71 std::ostream & operator<< (std::ostream & os, boost::yap::terminal<tarray_expr, int> expr)
72 { return os << '{' << boost::yap::value(expr) << '}'; }
73
74 std::ostream & operator<< (std::ostream & os, boost::yap::terminal<tarray_expr, std::array<int, 3>> expr)
75 {
76 std::array<int, 3> const & a = boost::yap::value(expr);
77 return os << '{' << a[0] << ", " << a[1] << ", " << a[2] << '}';
78 }
79
80 // Stream-out operators for general expressions. Note that we have to treat
81 // the reference case separately; this also could have been done using
82 // constexpr if in a single function template.
83
84 template <typename Tuple>
85 std::ostream & operator<< (std::ostream & os, tarray_expr<boost::yap::expr_kind::expr_ref, Tuple> const & expr)
86 { return os << boost::yap::deref(expr); }
87
88 template <boost::yap::expr_kind Kind, typename Tuple>
89 std::ostream & operator<< (std::ostream & os, tarray_expr<Kind, Tuple> const & expr)
90 {
91 if (Kind == boost::yap::expr_kind::plus || Kind == boost::yap::expr_kind::minus)
92 os << '(';
93 os << boost::yap::left(expr) << " " << op_string(Kind) << " " << boost::yap::right(expr);
94 if (Kind == boost::yap::expr_kind::plus || Kind == boost::yap::expr_kind::minus)
95 os << ')';
96 return os;
97 }
98
99
100 // Since we want different behavior on terminals than on other kinds of
101 // expressions, we create a custom type that does so.
102 struct tarray :
103 tarray_expr<
104 boost::yap::expr_kind::terminal,
105 boost::hana::tuple<std::array<int, 3>>
106 >
107 {
108 explicit tarray (int i = 0, int j = 0, int k = 0)
109 {
110 (*this)[0] = i;
111 (*this)[1] = j;
112 (*this)[2] = k;
113 }
114
115 explicit tarray (std::array<int, 3> a)
116 {
117 (*this)[0] = a[0];
118 (*this)[1] = a[1];
119 (*this)[2] = a[2];
120 }
121
122 int & operator[] (std::ptrdiff_t i)
123 { return boost::yap::value(*this)[i]; }
124
125 int const & operator[] (std::ptrdiff_t i) const
126 { return boost::yap::value(*this)[i]; }
127
128 template <typename T>
129 tarray & operator= (T const & t)
130 {
131 // We use as_expr() here to make sure that the value passed to
132 // assign() is an expression. as_expr() simply forwards expressions
133 // through, and wraps non-expressions as terminals.
134 return assign(boost::yap::as_expr< ::tarray_expr>(t));
135 }
136
137 template <typename Expr>
138 tarray & printAssign (Expr const & expr)
139 {
140 *this = expr;
141 std::cout << *this << " = " << expr << std::endl;
142 return *this;
143 }
144
145 private:
146 template <typename Expr>
147 tarray & assign (Expr const & expr)
148 {
149 (*this)[0] = expr[0];
150 (*this)[1] = expr[1];
151 (*this)[2] = expr[2];
152 return *this;
153 }
154 };
155
156
157 int main()
158 {
159 tarray a(3,1,2);
160
161 tarray b;
162
163 std::cout << a << std::endl;
164 std::cout << b << std::endl;
165
166 b[0] = 7; b[1] = 33; b[2] = -99;
167
168 tarray c(a);
169
170 std::cout << c << std::endl;
171
172 a = 0;
173
174 std::cout << a << std::endl;
175 std::cout << b << std::endl;
176 std::cout << c << std::endl;
177
178 a = b + c;
179
180 std::cout << a << std::endl;
181
182 a.printAssign(b+c*(b + 3*c));
183
184 return 0;
185 }
186 //]