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_EXPRESSION_HPP_INCLUDED
7 #define BOOST_YAP_EXPRESSION_HPP_INCLUDED
8 
9 #include <boost/yap/algorithm.hpp>
10 
11 
12 namespace boost { namespace yap {
13 
14     /** Reference expression template that provides all operator overloads.
15 
16         \note Due to a limitation of Doxygen, each of the
17         <code>value()</code>, <code>left()</code>, <code>right()</code>, and
18         operator overloads listed here is a stand-in for three member
19         functions.  For each function <code>f</code>, the listing here is:
20         \code return_type f (); \endcode  However, there are actually three
21         functions:
22         \code
23         return_type f () const &;
24         return_type f () &;
25         return_type f () &&;
26         \endcode
27     */
28     template<expr_kind Kind, typename Tuple>
29     struct expression
30     {
31         using tuple_type = Tuple;
32 
33         static const expr_kind kind = Kind;
34 
35         /** Default constructor.  Does nothing. */
expressionboost::yap::expression36         constexpr expression() {}
37 
38         /** Moves \a rhs into the only data mamber, \c elements. */
expressionboost::yap::expression39         constexpr expression(tuple_type && rhs) :
40             elements(static_cast<tuple_type &&>(rhs))
41         {}
42 
43         tuple_type elements;
44 
45         /** A convenience member function that dispatches to the free function
46             <code>value()</code>. */
valueboost::yap::expression47         constexpr decltype(auto) value() &
48         {
49             return ::boost::yap::value(*this);
50         }
51 
52 #ifndef BOOST_YAP_DOXYGEN
53 
valueboost::yap::expression54         constexpr decltype(auto) value() const &
55         {
56             return ::boost::yap::value(*this);
57         }
58 
valueboost::yap::expression59         constexpr decltype(auto) value() &&
60         {
61             return ::boost::yap::value(std::move(*this));
62         }
63 
64 #endif
65 
66         /** A convenience member function that dispatches to the free function
67             <code>left()</code>. */
leftboost::yap::expression68         constexpr decltype(auto) left() & { return ::boost::yap::left(*this); }
69 
70 #ifndef BOOST_YAP_DOXYGEN
71 
leftboost::yap::expression72         constexpr decltype(auto) left() const &
73         {
74             return ::boost::yap::left(*this);
75         }
76 
leftboost::yap::expression77         constexpr decltype(auto) left() &&
78         {
79             return ::boost::yap::left(std::move(*this));
80         }
81 
82 #endif
83 
84         /** A convenience member function that dispatches to the free function
85             <code>right()</code>. */
rightboost::yap::expression86         constexpr decltype(auto) right() &
87         {
88             return ::boost::yap::right(*this);
89         }
90 
91 #ifndef BOOST_YAP_DOXYGEN
92 
rightboost::yap::expression93         constexpr decltype(auto) right() const &
94         {
95             return ::boost::yap::right(*this);
96         }
97 
rightboost::yap::expression98         constexpr decltype(auto) right() &&
99         {
100             return ::boost::yap::right(std::move(*this));
101         }
102 
103 #endif
104 
105         BOOST_YAP_USER_ASSIGN_OPERATOR(
106             expression, ::boost::yap::expression)                   // =
107         BOOST_YAP_USER_SUBSCRIPT_OPERATOR(::boost::yap::expression) // []
108         BOOST_YAP_USER_CALL_OPERATOR(::boost::yap::expression)      // ()
109     };
110 
111     /** Terminal expression specialization of the reference expression
112         template.
113 
114         \note Due to a limitation of Doxygen, the <code>value()</code> member
115         and each of the operator overloads listed here is a stand-in for three
116         member functions.  For each function <code>f</code>, the listing here
117         is: \code return_type f (); \endcode However, there are actually three
118         functions:
119         \code
120         return_type f () const &;
121         return_type f () &;
122         return_type f () &&;
123         \endcode
124     */
125     template<typename T>
126     struct expression<expr_kind::terminal, hana::tuple<T>>
127     {
128         using tuple_type = hana::tuple<T>;
129 
130         static const expr_kind kind = expr_kind::terminal;
131 
132         /** Default constructor.  Does nothing. */
expressionboost::yap::expression133         constexpr expression() {}
134 
135         /** Forwards \a t into \c elements. */
expressionboost::yap::expression136         constexpr expression(T && t) : elements(static_cast<T &&>(t)) {}
137 
138         /** Copies \a rhs into the only data mamber, \c elements. */
expressionboost::yap::expression139         constexpr expression(hana::tuple<T> const & rhs) : elements(rhs) {}
140 
141         /** Moves \a rhs into the only data mamber, \c elements. */
expressionboost::yap::expression142         constexpr expression(hana::tuple<T> && rhs) : elements(std::move(rhs))
143         {}
144 
145         tuple_type elements;
146 
147         /** A convenience member function that dispatches to the free function
148             <code>value()</code>. */
valueboost::yap::expression149         constexpr decltype(auto) value() &
150         {
151             return ::boost::yap::value(*this);
152         }
153 
154 #ifndef BOOST_YAP_DOXYGEN
155 
valueboost::yap::expression156         constexpr decltype(auto) value() const &
157         {
158             return ::boost::yap::value(*this);
159         }
160 
valueboost::yap::expression161         constexpr decltype(auto) value() &&
162         {
163             return ::boost::yap::value(std::move(*this));
164         }
165 
166 #endif
167 
168         BOOST_YAP_USER_ASSIGN_OPERATOR(
169             expression, ::boost::yap::expression)                   // =
170         BOOST_YAP_USER_SUBSCRIPT_OPERATOR(::boost::yap::expression) // []
171         BOOST_YAP_USER_CALL_OPERATOR(::boost::yap::expression)      // ()
172     };
173 
174 #ifndef BOOST_YAP_DOXYGEN
175 
BOOST_YAP_USER_UNARY_OPERATOR(unary_plus,expression,expression)176     BOOST_YAP_USER_UNARY_OPERATOR(unary_plus, expression, expression)  // +
177     BOOST_YAP_USER_UNARY_OPERATOR(negate, expression, expression)      // -
178     BOOST_YAP_USER_UNARY_OPERATOR(dereference, expression, expression) // *
179     BOOST_YAP_USER_UNARY_OPERATOR(complement, expression, expression)  // ~
180     BOOST_YAP_USER_UNARY_OPERATOR(address_of, expression, expression)  // &
181     BOOST_YAP_USER_UNARY_OPERATOR(logical_not, expression, expression) // !
182     BOOST_YAP_USER_UNARY_OPERATOR(pre_inc, expression, expression)     // ++
183     BOOST_YAP_USER_UNARY_OPERATOR(pre_dec, expression, expression)     // --
184     BOOST_YAP_USER_UNARY_OPERATOR(post_inc, expression, expression)    // ++(int)
185     BOOST_YAP_USER_UNARY_OPERATOR(post_dec, expression, expression)    // --(int)
186 
187     BOOST_YAP_USER_BINARY_OPERATOR(shift_left, expression, expression)         // <<
188     BOOST_YAP_USER_BINARY_OPERATOR(shift_right, expression, expression)        // >>
189     BOOST_YAP_USER_BINARY_OPERATOR(multiplies, expression, expression)         // *
190     BOOST_YAP_USER_BINARY_OPERATOR(divides, expression, expression)            // /
191     BOOST_YAP_USER_BINARY_OPERATOR(modulus, expression, expression)            // %
192     BOOST_YAP_USER_BINARY_OPERATOR(plus, expression, expression)               // +
193     BOOST_YAP_USER_BINARY_OPERATOR(minus, expression, expression)              // -
194     BOOST_YAP_USER_BINARY_OPERATOR(less, expression, expression)               // <
195     BOOST_YAP_USER_BINARY_OPERATOR(greater, expression, expression)            // >
196     BOOST_YAP_USER_BINARY_OPERATOR(less_equal, expression, expression)         // <=
197     BOOST_YAP_USER_BINARY_OPERATOR(greater_equal, expression, expression)      // >=
198     BOOST_YAP_USER_BINARY_OPERATOR(equal_to, expression, expression)           // ==
199     BOOST_YAP_USER_BINARY_OPERATOR(not_equal_to, expression, expression)       // !=
200     BOOST_YAP_USER_BINARY_OPERATOR(logical_or, expression, expression)         // ||
201     BOOST_YAP_USER_BINARY_OPERATOR(logical_and, expression, expression)        // &&
202     BOOST_YAP_USER_BINARY_OPERATOR(bitwise_and, expression, expression)        // &
203     BOOST_YAP_USER_BINARY_OPERATOR(bitwise_or, expression, expression)         // |
204     BOOST_YAP_USER_BINARY_OPERATOR(bitwise_xor, expression, expression)        // ^
205     BOOST_YAP_USER_BINARY_OPERATOR(comma, expression, expression)              // ,
206     BOOST_YAP_USER_BINARY_OPERATOR(mem_ptr, expression, expression)            // ->*
207     BOOST_YAP_USER_BINARY_OPERATOR(shift_left_assign, expression, expression)  // <<=
208     BOOST_YAP_USER_BINARY_OPERATOR(shift_right_assign, expression, expression) // >>=
209     BOOST_YAP_USER_BINARY_OPERATOR(multiplies_assign, expression, expression)  // *=
210     BOOST_YAP_USER_BINARY_OPERATOR(divides_assign, expression, expression)     // /=
211     BOOST_YAP_USER_BINARY_OPERATOR(modulus_assign, expression, expression)     // %=
212     BOOST_YAP_USER_BINARY_OPERATOR(plus_assign, expression, expression)        // +=
213     BOOST_YAP_USER_BINARY_OPERATOR(minus_assign, expression, expression)       // -=
214     BOOST_YAP_USER_BINARY_OPERATOR(bitwise_and_assign, expression, expression) // &=
215     BOOST_YAP_USER_BINARY_OPERATOR(bitwise_or_assign, expression, expression)  // |=
216     BOOST_YAP_USER_BINARY_OPERATOR(bitwise_xor_assign, expression, expression) // ^=
217 
218     BOOST_YAP_USER_EXPR_IF_ELSE(expression)
219 
220 #else
221 
222     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
223     template<typename Expr>
224     constexpr auto operator+(Expr &&);
225     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
226     template<typename Expr>
227     constexpr auto operator-(Expr &&);
228     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
229     template<typename Expr>
230     constexpr auto operator*(Expr &&);
231     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
232     template<typename Expr>
233     constexpr auto operator~(Expr &&);
234     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
235     template<typename Expr>
236     constexpr auto operator&(Expr &&);
237     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
238     template<typename Expr>
239     constexpr auto operator!(Expr &&);
240     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
241     template<typename Expr>
242     constexpr auto operator++(Expr &&);
243     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
244     template<typename Expr>
245     constexpr auto operator--(Expr &&);
246     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
247     template<typename Expr>
248     constexpr auto operator++(Expr &&, int);
249     /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
250     template<typename Expr>
251     constexpr auto operator--(Expr &&, int);
252 
253     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
254     template<typename LExpr, typename RExpr>
255     constexpr auto operator<<(LExpr && lhs, RExpr && rhs);
256     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
257     template<typename LExpr, typename RExpr>
258     constexpr auto operator>>(LExpr && lhs, RExpr && rhs);
259     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
260     template<typename LExpr, typename RExpr>
261     constexpr auto operator*(LExpr && lhs, RExpr && rhs);
262     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
263     template<typename LExpr, typename RExpr>
264     constexpr auto operator/(LExpr && lhs, RExpr && rhs);
265     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
266     template<typename LExpr, typename RExpr>
267     constexpr auto operator%(LExpr && lhs, RExpr && rhs);
268     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
269     template<typename LExpr, typename RExpr>
270     constexpr auto operator+(LExpr && lhs, RExpr && rhs);
271     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
272     template<typename LExpr, typename RExpr>
273     constexpr auto operator-(LExpr && lhs, RExpr && rhs);
274     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
275     template<typename LExpr, typename RExpr>
276     constexpr auto operator<(LExpr && lhs, RExpr && rhs);
277     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
278     template<typename LExpr, typename RExpr>
279     constexpr auto operator>(LExpr && lhs, RExpr && rhs);
280     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
281     template<typename LExpr, typename RExpr>
282     constexpr auto operator<=(LExpr && lhs, RExpr && rhs);
283     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
284     template<typename LExpr, typename RExpr>
285     constexpr auto operator>=(LExpr && lhs, RExpr && rhs);
286     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
287     template<typename LExpr, typename RExpr>
288     constexpr auto operator==(LExpr && lhs, RExpr && rhs);
289     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
290     template<typename LExpr, typename RExpr>
291     constexpr auto operator!=(LExpr && lhs, RExpr && rhs);
292     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
293     template<typename LExpr, typename RExpr>
294     constexpr auto operator||(LExpr && lhs, RExpr && rhs);
295     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
296     template<typename LExpr, typename RExpr>
297     constexpr auto operator&&(LExpr && lhs, RExpr && rhs);
298     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
299     template<typename LExpr, typename RExpr>
300     constexpr auto operator&(LExpr && lhs, RExpr && rhs);
301     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
302     template<typename LExpr, typename RExpr>
303     constexpr auto operator|(LExpr && lhs, RExpr && rhs);
304     /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
305     template<typename LExpr, typename RExpr>
306     constexpr auto operator^(LExpr && lhs, RExpr && rhs);
307 
308     /** \see BOOST_YAP_USER_EXPR_IF_ELSE for full semantics. */
309     template<typename Expr1, typename Expr2, typename Expr3>
310     constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3);
311 
312 #endif
313 
314     /** Returns <code>make_expression<boost::yap::expression, Kind>(...)</code>.
315      */
316     template<expr_kind Kind, typename... T>
317     constexpr auto make_expression(T &&... t)
318     {
319         return make_expression<expression, Kind>(static_cast<T &&>(t)...);
320     }
321 
322     /** Returns <code>make_terminal<boost::yap::expression>(t)</code>. */
323     template<typename T>
make_terminal(T && t)324     constexpr auto make_terminal(T && t)
325     {
326         return make_terminal<expression>(static_cast<T &&>(t));
327     }
328 
329     /** Returns <code>as_expr<boost::yap::expression>(t)</code>. */
330     template<typename T>
as_expr(T && t)331     constexpr decltype(auto) as_expr(T && t)
332     {
333         return as_expr<expression>(static_cast<T &&>(t));
334     }
335 
336 }}
337 
338 #endif
339