]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/yap/example/tarray.cpp
1 // Copyright (C) 2016-2018 T. Zachary Laine
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)
7 #include <boost/yap/algorithm.hpp>
8 #include <boost/yap/print.hpp>
14 template <boost::yap::expr_kind Kind
, typename Tuple
>
20 boost::yap::terminal
<tarray_expr
, int>
21 operator() (boost::yap::terminal
<tarray_expr
, std::array
<int, 3>> const & expr
);
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
>
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.
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."
44 static const boost::yap::expr_kind kind
= Kind
;
48 int operator[] (std::size_t n
) const
49 { return boost::yap::evaluate(boost::yap::transform(*this, take_nth
{n
})); }
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
)
59 boost::yap::terminal
<tarray_expr
, int>
60 take_nth::operator() (boost::yap::terminal
<tarray_expr
, std::array
<int, 3>> const & expr
)
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
));
69 // Stream-out operators for the two kinds of terminals we support.
71 std::ostream
& operator<< (std::ostream
& os
, boost::yap::terminal
<tarray_expr
, int> expr
)
72 { return os
<< '{' << boost::yap::value(expr
) << '}'; }
74 std::ostream
& operator<< (std::ostream
& os
, boost::yap::terminal
<tarray_expr
, std::array
<int, 3>> expr
)
76 std::array
<int, 3> const & a
= boost::yap::value(expr
);
77 return os
<< '{' << a
[0] << ", " << a
[1] << ", " << a
[2] << '}';
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.
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
); }
88 template <boost::yap::expr_kind Kind
, typename Tuple
>
89 std::ostream
& operator<< (std::ostream
& os
, tarray_expr
<Kind
, Tuple
> const & expr
)
91 if (Kind
== boost::yap::expr_kind::plus
|| Kind
== boost::yap::expr_kind::minus
)
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
)
100 // Since we want different behavior on terminals than on other kinds of
101 // expressions, we create a custom type that does so.
104 boost::yap::expr_kind::terminal
,
105 boost::hana::tuple
<std::array
<int, 3>>
108 explicit tarray (int i
= 0, int j
= 0, int k
= 0)
115 explicit tarray (std::array
<int, 3> a
)
122 int & operator[] (std::ptrdiff_t i
)
123 { return boost::yap::value(*this)[i
]; }
125 int const & operator[] (std::ptrdiff_t i
) const
126 { return boost::yap::value(*this)[i
]; }
128 template <typename T
>
129 tarray
& operator= (T
const & t
)
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
));
137 template <typename Expr
>
138 tarray
& printAssign (Expr
const & expr
)
141 std::cout
<< *this << " = " << expr
<< std::endl
;
146 template <typename Expr
>
147 tarray
& assign (Expr
const & expr
)
149 (*this)[0] = expr
[0];
150 (*this)[1] = expr
[1];
151 (*this)[2] = expr
[2];
163 std::cout
<< a
<< std::endl
;
164 std::cout
<< b
<< std::endl
;
166 b
[0] = 7; b
[1] = 33; b
[2] = -99;
170 std::cout
<< c
<< std::endl
;
174 std::cout
<< a
<< std::endl
;
175 std::cout
<< b
<< std::endl
;
176 std::cout
<< c
<< std::endl
;
180 std::cout
<< a
<< std::endl
;
182 a
.printAssign(b
+c
*(b
+ 3*c
));