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