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_USER_MACROS_HPP_INCLUDED 7 #define BOOST_YAP_USER_MACROS_HPP_INCLUDED 8 9 #include <boost/preprocessor/cat.hpp> 10 #include <boost/preprocessor/repetition/enum_params.hpp> 11 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 12 #include <boost/preprocessor/repetition/enum.hpp> 13 14 15 #ifndef BOOST_YAP_DOXYGEN 16 17 // unary 18 #define BOOST_YAP_OPERATOR_unary_plus(...) +(__VA_ARGS__) 19 #define BOOST_YAP_OPERATOR_negate(...) -(__VA_ARGS__) 20 #define BOOST_YAP_OPERATOR_dereference(...) *(__VA_ARGS__) 21 #define BOOST_YAP_OPERATOR_complement(...) ~(__VA_ARGS__) 22 #define BOOST_YAP_OPERATOR_address_of(...) &(__VA_ARGS__) 23 #define BOOST_YAP_OPERATOR_logical_not(...) !(__VA_ARGS__) 24 #define BOOST_YAP_OPERATOR_pre_inc(...) ++(__VA_ARGS__) 25 #define BOOST_YAP_OPERATOR_pre_dec(...) --(__VA_ARGS__) 26 #define BOOST_YAP_OPERATOR_post_inc(...) ++(__VA_ARGS__, int) 27 #define BOOST_YAP_OPERATOR_post_dec(...) --(__VA_ARGS__, int) 28 29 // binary 30 #define BOOST_YAP_OPERATOR_shift_left(...) <<(__VA_ARGS__) 31 #define BOOST_YAP_OPERATOR_shift_right(...) >>(__VA_ARGS__) 32 #define BOOST_YAP_OPERATOR_multiplies(...) *(__VA_ARGS__) 33 #define BOOST_YAP_OPERATOR_divides(...) /(__VA_ARGS__) 34 #define BOOST_YAP_OPERATOR_modulus(...) %(__VA_ARGS__) 35 #define BOOST_YAP_OPERATOR_plus(...) +(__VA_ARGS__) 36 #define BOOST_YAP_OPERATOR_minus(...) -(__VA_ARGS__) 37 #define BOOST_YAP_OPERATOR_less(...) <(__VA_ARGS__) 38 #define BOOST_YAP_OPERATOR_greater(...) >(__VA_ARGS__) 39 #define BOOST_YAP_OPERATOR_less_equal(...) <=(__VA_ARGS__) 40 #define BOOST_YAP_OPERATOR_greater_equal(...) >=(__VA_ARGS__) 41 #define BOOST_YAP_OPERATOR_equal_to(...) ==(__VA_ARGS__) 42 #define BOOST_YAP_OPERATOR_not_equal_to(...) !=(__VA_ARGS__) 43 #define BOOST_YAP_OPERATOR_logical_or(...) ||(__VA_ARGS__) 44 #define BOOST_YAP_OPERATOR_logical_and(...) &&(__VA_ARGS__) 45 #define BOOST_YAP_OPERATOR_bitwise_and(...) &(__VA_ARGS__) 46 #define BOOST_YAP_OPERATOR_bitwise_or(...) |(__VA_ARGS__) 47 #define BOOST_YAP_OPERATOR_bitwise_xor(...) ^(__VA_ARGS__) 48 #define BOOST_YAP_OPERATOR_comma(...) ,(__VA_ARGS__) 49 #define BOOST_YAP_OPERATOR_mem_ptr(...) ->*(__VA_ARGS__) 50 #define BOOST_YAP_OPERATOR_assign(...) =(__VA_ARGS__) 51 #define BOOST_YAP_OPERATOR_shift_left_assign(...) <<=(__VA_ARGS__) 52 #define BOOST_YAP_OPERATOR_shift_right_assign(...) >>=(__VA_ARGS__) 53 #define BOOST_YAP_OPERATOR_multiplies_assign(...) *=(__VA_ARGS__) 54 #define BOOST_YAP_OPERATOR_divides_assign(...) /=(__VA_ARGS__) 55 #define BOOST_YAP_OPERATOR_modulus_assign(...) %=(__VA_ARGS__) 56 #define BOOST_YAP_OPERATOR_plus_assign(...) +=(__VA_ARGS__) 57 #define BOOST_YAP_OPERATOR_minus_assign(...) -=(__VA_ARGS__) 58 #define BOOST_YAP_OPERATOR_bitwise_and_assign(...) &=(__VA_ARGS__) 59 #define BOOST_YAP_OPERATOR_bitwise_or_assign(...) |=(__VA_ARGS__) 60 #define BOOST_YAP_OPERATOR_bitwise_xor_assign(...) ^=(__VA_ARGS__) 61 #define BOOST_YAP_OPERATOR_subscript(...) [](__VA_ARGS__) 62 63 #define BOOST_YAP_INDIRECT_CALL(macro) BOOST_PP_CAT(BOOST_YAP_OPERATOR_, macro) 64 65 #endif // BOOST_YAP_DOXYGEN 66 67 68 /** Defines operator overloads for unary operator \a op_name that each take an 69 expression instantiated from \a expr_template and return an expression 70 instantiated from the \a result_expr_template expression template. One 71 overload is defined for each of the qualifiers <code>const &</code>, 72 <code>&</code>, and <code>&&</code>. For the lvalue reference overloads, 73 the argument is captured by reference into the resulting expression. For 74 the rvalue reference overload, the argument is moved into the resulting 75 expression. 76 77 Example: 78 \snippet user_macros_snippets.cpp USER_UNARY_OPERATOR 79 80 \param op_name The operator to be overloaded; this must be one of the \b 81 unary enumerators in <code>expr_kind</code>, without the 82 <code>expr_kind::</code> qualification. 83 84 \param expr_template The expression template to which the overloads apply. 85 \a expr_template must be an \ref ExpressionTemplate. 86 87 \param result_expr_template The expression template to use to instantiate 88 the result expression. \a result_expr_template must be an \ref 89 ExpressionTemplate. 90 */ 91 #define BOOST_YAP_USER_UNARY_OPERATOR( \ 92 op_name, expr_template, result_expr_template) \ 93 template<::boost::yap::expr_kind Kind, typename Tuple> \ 94 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 95 expr_template<Kind, Tuple> const & x) \ 96 { \ 97 using lhs_type = ::boost::yap::detail::operand_type_t< \ 98 result_expr_template, \ 99 expr_template<Kind, Tuple> const &>; \ 100 using tuple_type = ::boost::hana::tuple<lhs_type>; \ 101 return result_expr_template< \ 102 ::boost::yap::expr_kind::op_name, \ 103 tuple_type>{ \ 104 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}}; \ 105 } \ 106 template<::boost::yap::expr_kind Kind, typename Tuple> \ 107 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 108 expr_template<Kind, Tuple> & x) \ 109 { \ 110 using lhs_type = ::boost::yap::detail::operand_type_t< \ 111 result_expr_template, \ 112 expr_template<Kind, Tuple> &>; \ 113 using tuple_type = ::boost::hana::tuple<lhs_type>; \ 114 return result_expr_template< \ 115 ::boost::yap::expr_kind::op_name, \ 116 tuple_type>{ \ 117 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}}; \ 118 } \ 119 template<::boost::yap::expr_kind Kind, typename Tuple> \ 120 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 121 expr_template<Kind, Tuple> && x) \ 122 { \ 123 using tuple_type = ::boost::hana::tuple<expr_template<Kind, Tuple>>; \ 124 return result_expr_template< \ 125 ::boost::yap::expr_kind::op_name, \ 126 tuple_type>{tuple_type{std::move(x)}}; \ 127 } 128 129 130 /** Defines operator overloads for binary operator \a op_name that each 131 produce an expression instantiated from the \a expr_template expression 132 template. One overload is defined for each of the qualifiers <code>const 133 &</code>, <code>&</code>, and <code>&&</code>. For the lvalue reference 134 overloads, <code>*this</code> is captured by reference into the resulting 135 expression. For the rvalue reference overload, <code>*this</code> is 136 moved into the resulting expression. 137 138 Note that this does not work for yap::expr_kinds assign, subscript, or 139 call. Use BOOST_YAP_USER_ASSIGN_OPERATOR, 140 BOOST_YAP_USER_SUBSCRIPT_OPERATOR, or BOOST_YAP_USER_CALL_OPERATOR for 141 those, respectively. 142 143 Example: 144 \snippet user_macros_snippets.cpp USER_BINARY_OPERATOR 145 146 \param op_name The operator to be overloaded; this must be one of the \b 147 binary enumerators in <code>expr_kind</code>, except assign, subscript, or 148 call, without the <code>expr_kind::</code> qualification. 149 150 \param expr_template The expression template to which the overloads apply. 151 \a expr_template must be an \ref ExpressionTemplate. 152 153 \param result_expr_template The expression template to use to instantiate 154 the result expression. \a result_expr_template must be an \ref 155 ExpressionTemplate. 156 */ 157 #define BOOST_YAP_USER_BINARY_OPERATOR( \ 158 op_name, expr_template, result_expr_template) \ 159 template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ 160 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 161 expr_template<Kind, Tuple> const & lhs, Expr && rhs) \ 162 { \ 163 using lhs_type = ::boost::yap::detail::operand_type_t< \ 164 result_expr_template, \ 165 expr_template<Kind, Tuple> const &>; \ 166 using rhs_type = \ 167 ::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \ 168 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 169 return result_expr_template< \ 170 ::boost::yap::expr_kind::op_name, \ 171 tuple_type>{ \ 172 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs), \ 173 ::boost::yap::detail::make_operand<rhs_type>{}( \ 174 static_cast<Expr &&>(rhs))}}; \ 175 } \ 176 template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ 177 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 178 expr_template<Kind, Tuple> & lhs, Expr && rhs) \ 179 { \ 180 using lhs_type = ::boost::yap::detail::operand_type_t< \ 181 result_expr_template, \ 182 expr_template<Kind, Tuple> &>; \ 183 using rhs_type = \ 184 ::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \ 185 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 186 return result_expr_template< \ 187 ::boost::yap::expr_kind::op_name, \ 188 tuple_type>{ \ 189 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs), \ 190 ::boost::yap::detail::make_operand<rhs_type>{}( \ 191 static_cast<Expr &&>(rhs))}}; \ 192 } \ 193 template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ 194 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 195 expr_template<Kind, Tuple> && lhs, Expr && rhs) \ 196 { \ 197 using lhs_type = ::boost::yap::detail::remove_cv_ref_t< \ 198 expr_template<Kind, Tuple> &&>; \ 199 using rhs_type = \ 200 ::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \ 201 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 202 return result_expr_template< \ 203 ::boost::yap::expr_kind::op_name, \ 204 tuple_type>{ \ 205 tuple_type{std::move(lhs), \ 206 ::boost::yap::detail::make_operand<rhs_type>{}( \ 207 static_cast<Expr &&>(rhs))}}; \ 208 } \ 209 template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \ 210 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 211 T && lhs, expr_template<Kind, Tuple> && rhs) \ 212 ->::boost::yap::detail::free_binary_op_result_t< \ 213 result_expr_template, \ 214 ::boost::yap::expr_kind::op_name, \ 215 T, \ 216 expr_template<Kind, Tuple> &&> \ 217 { \ 218 using result_types = ::boost::yap::detail::free_binary_op_result< \ 219 result_expr_template, \ 220 ::boost::yap::expr_kind::op_name, \ 221 T, \ 222 expr_template<Kind, Tuple> &&>; \ 223 using lhs_type = typename result_types::lhs_type; \ 224 using rhs_type = typename result_types::rhs_type; \ 225 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 226 return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, std::move(rhs)}}; \ 227 } \ 228 template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \ 229 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 230 T && lhs, expr_template<Kind, Tuple> const & rhs) \ 231 ->::boost::yap::detail::free_binary_op_result_t< \ 232 result_expr_template, \ 233 ::boost::yap::expr_kind::op_name, \ 234 T, \ 235 expr_template<Kind, Tuple> const &> \ 236 { \ 237 using result_types = ::boost::yap::detail::free_binary_op_result< \ 238 result_expr_template, \ 239 ::boost::yap::expr_kind::op_name, \ 240 T, \ 241 expr_template<Kind, Tuple> const &>; \ 242 using lhs_type = typename result_types::lhs_type; \ 243 using rhs_type = typename result_types::rhs_type; \ 244 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 245 using rhs_tuple_type = typename result_types::rhs_tuple_type; \ 246 return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \ 247 rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \ 248 } \ 249 template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \ 250 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ 251 T && lhs, expr_template<Kind, Tuple> & rhs) \ 252 ->::boost::yap::detail::free_binary_op_result_t< \ 253 result_expr_template, \ 254 ::boost::yap::expr_kind::op_name, \ 255 T, \ 256 expr_template<Kind, Tuple> &> \ 257 { \ 258 using result_types = ::boost::yap::detail::free_binary_op_result< \ 259 result_expr_template, \ 260 ::boost::yap::expr_kind::op_name, \ 261 T, \ 262 expr_template<Kind, Tuple> &>; \ 263 using lhs_type = typename result_types::lhs_type; \ 264 using rhs_type = typename result_types::rhs_type; \ 265 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 266 using rhs_tuple_type = typename result_types::rhs_tuple_type; \ 267 return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \ 268 rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \ 269 } 270 271 272 /** Defines operator overloads for \a operator=() that each produce an 273 expression instantiated from the \a expr_template expression template. 274 One overload is defined for each of the qualifiers <code>const &</code>, 275 <code>&</code>, and <code>&&</code>. For the lvalue reference overloads, 276 <code>*this</code> is captured by reference into the resulting expression. 277 For the rvalue reference overload, <code>*this</code> is moved into the 278 resulting expression. 279 280 The \a rhs parameter to each of the defined overloads may be any type, 281 including an expression, except that the overloads are constrained by 282 std::enable_if<> not to conflict with the assignment and move assignement 283 operators. If \a rhs is a non-expression, it is wrapped in a terminal 284 expression. 285 286 Example: 287 \snippet user_macros_snippets.cpp USER_ASSIGN_OPERATOR 288 289 \param this_type The type of the class the operator is a member of; this 290 is required to avoid clashing with the assignment and move assignement 291 operators. 292 293 \param expr_template The expression template to use to instantiate the 294 result expression. \a expr_template must be an \ref 295 ExpressionTemplate. 296 */ 297 #define BOOST_YAP_USER_ASSIGN_OPERATOR(this_type, expr_template) \ 298 template< \ 299 typename Expr, \ 300 typename = std::enable_if_t< \ 301 !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \ 302 constexpr auto operator=(Expr && rhs) const & \ 303 { \ 304 using lhs_type = ::boost::yap::detail:: \ 305 operand_type_t<expr_template, this_type const &>; \ 306 using rhs_type = \ 307 ::boost::yap::detail::operand_type_t<expr_template, Expr>; \ 308 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 309 return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ 310 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \ 311 ::boost::yap::detail::make_operand<rhs_type>{}( \ 312 static_cast<Expr &&>(rhs))}}; \ 313 } \ 314 template< \ 315 typename Expr, \ 316 typename = std::enable_if_t< \ 317 !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \ 318 constexpr auto operator=(Expr && rhs) & \ 319 { \ 320 using lhs_type = ::boost::yap::detail:: \ 321 operand_type_t<expr_template, decltype(*this)>; \ 322 using rhs_type = \ 323 ::boost::yap::detail::operand_type_t<expr_template, Expr>; \ 324 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 325 return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ 326 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \ 327 ::boost::yap::detail::make_operand<rhs_type>{}( \ 328 static_cast<Expr &&>(rhs))}}; \ 329 } \ 330 template< \ 331 typename Expr, \ 332 typename = std::enable_if_t< \ 333 !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \ 334 constexpr auto operator=(Expr && rhs) && \ 335 { \ 336 using rhs_type = \ 337 ::boost::yap::detail::operand_type_t<expr_template, Expr>; \ 338 using tuple_type = ::boost::hana::tuple<this_type, rhs_type>; \ 339 return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ 340 tuple_type{std::move(*this), \ 341 ::boost::yap::detail::make_operand<rhs_type>{}( \ 342 static_cast<Expr &&>(rhs))}}; \ 343 } 344 345 346 /** Defines operator overloads for \a operator[]() that each produce an 347 expression instantiated from the \a expr_template expression template. 348 One overload is defined for each of the qualifiers <code>const &</code>, 349 <code>&</code>, and <code>&&</code>. For the lvalue reference overloads, 350 <code>*this</code> is captured by reference into the resulting expression. 351 For the rvalue reference overload, <code>*this</code> is moved into the 352 resulting expression. 353 354 The \a rhs parameter to each of the defined overloads may be any type, 355 including an expression, except that the overloads are constrained by 356 std::enable_if<> not to conflict with the assignment and move assignement 357 operators. If \a rhs is a non-expression, it is wrapped in a terminal 358 expression. 359 360 Example: 361 \snippet user_macros_snippets.cpp USER_SUBSCRIPT_OPERATOR 362 363 \param expr_template The expression template to use to instantiate the 364 result expression. \a expr_template must be an \ref 365 ExpressionTemplate. 366 */ 367 #define BOOST_YAP_USER_SUBSCRIPT_OPERATOR(expr_template) \ 368 template<typename Expr> \ 369 constexpr auto operator[](Expr && rhs) const & \ 370 { \ 371 using lhs_type = ::boost::yap::detail:: \ 372 operand_type_t<expr_template, decltype(*this)>; \ 373 using rhs_type = \ 374 ::boost::yap::detail::operand_type_t<expr_template, Expr>; \ 375 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 376 return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ 377 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \ 378 ::boost::yap::detail::make_operand<rhs_type>{}( \ 379 static_cast<Expr &&>(rhs))}}; \ 380 } \ 381 template<typename Expr> \ 382 constexpr auto operator[](Expr && rhs) & \ 383 { \ 384 using lhs_type = ::boost::yap::detail:: \ 385 operand_type_t<expr_template, decltype(*this)>; \ 386 using rhs_type = \ 387 ::boost::yap::detail::operand_type_t<expr_template, Expr>; \ 388 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 389 return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ 390 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \ 391 ::boost::yap::detail::make_operand<rhs_type>{}( \ 392 static_cast<Expr &&>(rhs))}}; \ 393 } \ 394 template<typename Expr> \ 395 constexpr auto operator[](Expr && rhs) && \ 396 { \ 397 using lhs_type = \ 398 ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \ 399 using rhs_type = \ 400 ::boost::yap::detail::operand_type_t<expr_template, Expr>; \ 401 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 402 return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ 403 tuple_type{std::move(*this), \ 404 ::boost::yap::detail::make_operand<rhs_type>{}( \ 405 static_cast<Expr &&>(rhs))}}; \ 406 } 407 408 409 /** Defines operator overloads for the call operator taking any number of 410 parameters ("operator()") that each produce an expression instantiated 411 from the \a expr_template expression template. One overload is defined 412 for each of the qualifiers <code>const &</code>, <code>&</code>, and 413 <code>&&</code>. For the lvalue reference overloads, <code>*this</code> 414 is captured by reference into the resulting expression. For the rvalue 415 reference overload, <code>*this</code> is moved into the resulting 416 expression. 417 418 The \a u parameters to each of the defined overloads may be any type, 419 including an expression. Each non-expression is wrapped in a terminal 420 expression. 421 422 Example: 423 \snippet user_macros_snippets.cpp USER_CALL_OPERATOR 424 425 \param expr_template The expression template to use to instantiate the 426 result expression. \a expr_template must be an \ref 427 ExpressionTemplate. 428 */ 429 #define BOOST_YAP_USER_CALL_OPERATOR(expr_template) \ 430 template<typename... U> \ 431 constexpr auto operator()(U &&... u) const & \ 432 { \ 433 using lhs_type = ::boost::yap::detail:: \ 434 operand_type_t<expr_template, decltype(*this)>; \ 435 using tuple_type = ::boost::hana::tuple< \ 436 lhs_type, \ 437 ::boost::yap::detail::operand_type_t<expr_template, U>...>; \ 438 return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ 439 tuple_type{ \ 440 ::boost::yap::detail::make_operand<lhs_type>{}(*this), \ 441 ::boost::yap::detail::make_operand< \ 442 ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \ 443 static_cast<U &&>(u))...}}; \ 444 } \ 445 template<typename... U> \ 446 constexpr auto operator()(U &&... u) & \ 447 { \ 448 using lhs_type = ::boost::yap::detail:: \ 449 operand_type_t<expr_template, decltype(*this)>; \ 450 using tuple_type = ::boost::hana::tuple< \ 451 lhs_type, \ 452 ::boost::yap::detail::operand_type_t<expr_template, U>...>; \ 453 return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ 454 tuple_type{ \ 455 ::boost::yap::detail::make_operand<lhs_type>{}(*this), \ 456 ::boost::yap::detail::make_operand< \ 457 ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \ 458 static_cast<U &&>(u))...}}; \ 459 } \ 460 template<typename... U> \ 461 constexpr auto operator()(U &&... u) && \ 462 { \ 463 using this_type = \ 464 ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \ 465 using tuple_type = ::boost::hana::tuple< \ 466 this_type, \ 467 ::boost::yap::detail::operand_type_t<expr_template, U>...>; \ 468 return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ 469 tuple_type{ \ 470 std::move(*this), \ 471 ::boost::yap::detail::make_operand< \ 472 ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \ 473 static_cast<U &&>(u))...}}; \ 474 } 475 476 477 #ifndef BOOST_YAP_DOXYGEN 478 479 #define BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T(z, n, expr_template) \ 480 ::boost::yap::detail::operand_type_t<expr_template, BOOST_PP_CAT(U, n)> 481 #define BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND(z, n, expr_template) \ 482 ::boost::yap::detail::make_operand<::boost::yap::detail::operand_type_t< \ 483 expr_template, \ 484 BOOST_PP_CAT(U, n)>>{}( \ 485 static_cast<BOOST_PP_CAT(U, n) &&>(BOOST_PP_CAT(u, n))) 486 487 #endif 488 489 /** Defines operator overloads for the call operator taking N parameters 490 ("operator()(t0, t1, ... tn-1)") that each produce an expression 491 instantiated from the \a expr_template expression template. One overload 492 is defined for each of the qualifiers <code>const &</code>, 493 <code>&</code>, and <code>&&</code>. For the lvalue reference overloads, 494 <code>*this</code> is captured by reference into the resulting expression. 495 For the rvalue reference overload, <code>*this</code> is moved into the 496 resulting expression. 497 498 The \a u parameters to each of the defined overloads may be any type, 499 including an expression. Each non-expression is wrapped in a terminal 500 expression. 501 502 Example: 503 \snippet user_macros_snippets.cpp USER_CALL_OPERATOR 504 505 \param expr_template The expression template to use to instantiate the 506 result expression. \a expr_template must be an \ref 507 ExpressionTemplate. 508 509 \param n The number of parameters accepted by the operator() overloads. n 510 must be <= BOOST_PP_LIMIT_REPEAT. 511 */ 512 #define BOOST_YAP_USER_CALL_OPERATOR_N(expr_template, n) \ 513 template<BOOST_PP_ENUM_PARAMS(n, typename U)> \ 514 constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) const & \ 515 { \ 516 using lhs_type = ::boost::yap::detail:: \ 517 operand_type_t<expr_template, decltype(*this)>; \ 518 using tuple_type = ::boost::hana::tuple< \ 519 lhs_type, \ 520 BOOST_PP_ENUM( \ 521 n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \ 522 return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ 523 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \ 524 BOOST_PP_ENUM( \ 525 n, \ 526 BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ 527 expr_template)}}; \ 528 } \ 529 template<BOOST_PP_ENUM_PARAMS(n, typename U)> \ 530 constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) & \ 531 { \ 532 using lhs_type = ::boost::yap::detail:: \ 533 operand_type_t<expr_template, decltype(*this)>; \ 534 using tuple_type = ::boost::hana::tuple< \ 535 lhs_type, \ 536 BOOST_PP_ENUM( \ 537 n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \ 538 return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ 539 tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \ 540 BOOST_PP_ENUM( \ 541 n, \ 542 BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ 543 expr_template)}}; \ 544 } \ 545 template<BOOST_PP_ENUM_PARAMS(n, typename U)> \ 546 constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) && \ 547 { \ 548 using this_type = \ 549 ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \ 550 using tuple_type = ::boost::hana::tuple< \ 551 this_type, \ 552 BOOST_PP_ENUM( \ 553 n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \ 554 return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ 555 tuple_type{std::move(*this), \ 556 BOOST_PP_ENUM( \ 557 n, \ 558 BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ 559 expr_template)}}; \ 560 } 561 562 563 /** Defines a 3-parameter function <code>if_else()</code> that acts as an 564 analogue to the ternary operator (<code>?:</code>), since the ternary 565 operator is not user-overloadable. The return type of 566 <code>if_else()</code> is an expression instantiated from the \a 567 expr_template expression template. 568 569 At least one parameter to <code>if_else()</code> must be an expression. 570 571 For each parameter E passed to <code>if_else()</code>, if E is an rvalue, 572 E is moved into the result, and otherwise E is captured by reference into 573 the result. 574 575 Example: 576 \snippet user_macros_snippets.cpp USER_EXPR_IF_ELSE 577 578 \param expr_template The expression template to use to instantiate the 579 result expression. \a expr_template must be an \ref 580 ExpressionTemplate. 581 */ 582 #define BOOST_YAP_USER_EXPR_IF_ELSE(expr_template) \ 583 template<typename Expr1, typename Expr2, typename Expr3> \ 584 constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \ 585 ->::boost::yap::detail:: \ 586 ternary_op_result_t<expr_template, Expr1, Expr2, Expr3> \ 587 { \ 588 using result_types = ::boost::yap::detail:: \ 589 ternary_op_result<expr_template, Expr1, Expr2, Expr3>; \ 590 using cond_type = typename result_types::cond_type; \ 591 using then_type = typename result_types::then_type; \ 592 using else_type = typename result_types::else_type; \ 593 using tuple_type = \ 594 ::boost::hana::tuple<cond_type, then_type, else_type>; \ 595 return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}( \ 596 static_cast<Expr1 &&>(expr1)), \ 597 ::boost::yap::detail::make_operand<then_type>{}( \ 598 static_cast<Expr2 &&>(expr2)), \ 599 ::boost::yap::detail::make_operand<else_type>{}( \ 600 static_cast<Expr3 &&>(expr3))}}; \ 601 } 602 603 604 /** Defines a function <code>if_else()</code> that acts as an analogue to the 605 ternary operator (<code>?:</code>), since the ternary operator is not 606 user-overloadable. The return type of <code>if_else()</code> is an 607 expression instantiated from the \a expr_template expression template. 608 609 Each parameter to <code>if_else()</code> may be any type that is \b not an 610 expression. At least on parameter must be a type <code>T</code> for which 611 \code udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value 612 \endcode is true. Each parameter is wrapped in a terminal expression. 613 614 Example: 615 \snippet user_macros_snippets.cpp USER_UDT_ANY_IF_ELSE 616 617 \param expr_template The expression template to use to instantiate the 618 result expression. \a expr_template must be an \ref 619 ExpressionTemplate. 620 621 \param udt_trait A trait template to use to constrain which types are 622 accepted as template parameters to <code>if_else()</code>. 623 */ 624 #define BOOST_YAP_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait) \ 625 template<typename Expr1, typename Expr2, typename Expr3> \ 626 constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \ 627 ->::boost::yap::detail::udt_any_ternary_op_result_t< \ 628 expr_template, \ 629 Expr1, \ 630 Expr2, \ 631 Expr3, \ 632 udt_trait> \ 633 { \ 634 using result_types = ::boost::yap::detail::udt_any_ternary_op_result< \ 635 expr_template, \ 636 Expr1, \ 637 Expr2, \ 638 Expr3, \ 639 udt_trait>; \ 640 using cond_type = typename result_types::cond_type; \ 641 using then_type = typename result_types::then_type; \ 642 using else_type = typename result_types::else_type; \ 643 using tuple_type = \ 644 ::boost::hana::tuple<cond_type, then_type, else_type>; \ 645 return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}( \ 646 static_cast<Expr1 &&>(expr1)), \ 647 ::boost::yap::detail::make_operand<then_type>{}( \ 648 static_cast<Expr2 &&>(expr2)), \ 649 ::boost::yap::detail::make_operand<else_type>{}( \ 650 static_cast<Expr3 &&>(expr3))}}; \ 651 } 652 653 654 /** Defines a free/non-member operator overload for unary operator \a op_name 655 that produces an expression instantiated from the \a expr_template 656 expression template. 657 658 The parameter to the defined operator overload may be any type that is \b 659 not an expression and for which \code 660 udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is 661 true. The parameter is wrapped in a terminal expression. 662 663 Example: 664 \snippet user_macros_snippets.cpp USER_UDT_UNARY_OPERATOR 665 666 \param op_name The operator to be overloaded; this must be one of the \b 667 unary enumerators in <code>expr_kind</code>, without the 668 <code>expr_kind::</code> qualification. 669 670 \param expr_template The expression template to use to instantiate the 671 result expression. \a expr_template must be an \ref 672 ExpressionTemplate. 673 674 \param udt_trait A trait template to use to constrain which types are 675 accepted as template parameters to the defined operator overload. 676 */ 677 #define BOOST_YAP_USER_UDT_UNARY_OPERATOR(op_name, expr_template, udt_trait) \ 678 template<typename T> \ 679 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && x) \ 680 ->::boost::yap::detail::udt_unary_op_result_t< \ 681 expr_template, \ 682 ::boost::yap::expr_kind::op_name, \ 683 T, \ 684 udt_trait> \ 685 { \ 686 using result_types = ::boost::yap::detail::udt_unary_op_result< \ 687 expr_template, \ 688 ::boost::yap::expr_kind::op_name, \ 689 T, \ 690 udt_trait>; \ 691 using x_type = typename result_types::x_type; \ 692 using tuple_type = ::boost::hana::tuple<x_type>; \ 693 return {tuple_type{x_type{static_cast<T &&>(x)}}}; \ 694 } 695 696 697 /** Defines a free/non-member operator overload for binary operator \a op_name 698 that produces an expression instantiated from the \a expr_template 699 expression template. 700 701 The \a lhs parameter to the defined operator overload may be any type that 702 is \b not an expression and for which \code 703 t_udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is 704 true. The parameter is wrapped in a terminal expression. 705 706 The \a rhs parameter to the defined operator overload may be any type that 707 is \b not an expression and for which \code 708 u_udt_trait<std::remove_cv_t<std::remove_reference_t<U>>>::value \endcode is 709 true. The parameter is wrapped in a terminal expression. 710 711 Example: 712 \snippet user_macros_snippets.cpp USER_UDT_UDT_BINARY_OPERATOR 713 714 \param op_name The operator to be overloaded; this must be one of the \b 715 binary enumerators in <code>expr_kind</code>, without the 716 <code>expr_kind::</code> qualification. 717 718 \param expr_template The expression template to use to instantiate the 719 result expression. \a expr_template must be an \ref 720 ExpressionTemplate. 721 722 \param t_udt_trait A trait template to use to constrain which types are 723 accepted as \a T template parameters to the defined operator overload. 724 725 \param u_udt_trait A trait template to use to constrain which types are 726 accepted as \a U template parameters to the defined operator overload. 727 */ 728 #define BOOST_YAP_USER_UDT_UDT_BINARY_OPERATOR( \ 729 op_name, expr_template, t_udt_trait, u_udt_trait) \ 730 template<typename T, typename U> \ 731 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \ 732 ->::boost::yap::detail::udt_udt_binary_op_result_t< \ 733 expr_template, \ 734 ::boost::yap::expr_kind::op_name, \ 735 T, \ 736 U, \ 737 t_udt_trait, \ 738 u_udt_trait> \ 739 { \ 740 using result_types = ::boost::yap::detail::udt_udt_binary_op_result< \ 741 expr_template, \ 742 ::boost::yap::expr_kind::op_name, \ 743 T, \ 744 U, \ 745 t_udt_trait, \ 746 u_udt_trait>; \ 747 using lhs_type = typename result_types::lhs_type; \ 748 using rhs_type = typename result_types::rhs_type; \ 749 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 750 return {tuple_type{ \ 751 lhs_type{static_cast<T &&>(lhs)}, \ 752 rhs_type{static_cast<U &&>(rhs)}, \ 753 }}; \ 754 } 755 756 757 /** Defines a free/non-member operator overload for binary operator \a op_name 758 that produces an expression instantiated from the \a expr_template 759 expression template. 760 761 The \a lhs and \a rhs parameters to the defined operator overload may be any 762 types that are \b not expressions. Each parameter is wrapped in a terminal 763 expression. 764 765 At least one of the parameters to the defined operator overload must be a 766 type \c T for which \code 767 udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is 768 true. 769 770 Example: 771 \snippet user_macros_snippets.cpp USER_UDT_ANY_BINARY_OPERATOR 772 773 \param op_name The operator to be overloaded; this must be one of the \b 774 binary enumerators in <code>expr_kind</code>, without the 775 <code>expr_kind::</code> qualification. 776 777 \param expr_template The expression template to use to instantiate the 778 result expression. \a expr_template must be an \ref 779 ExpressionTemplate. 780 781 \param udt_trait A trait template to use to constrain which types are 782 accepted as template parameters to the defined operator overload. 783 */ 784 #define BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( \ 785 op_name, expr_template, udt_trait) \ 786 template<typename T, typename U> \ 787 constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \ 788 ->::boost::yap::detail::udt_any_binary_op_result_t< \ 789 expr_template, \ 790 ::boost::yap::expr_kind::op_name, \ 791 T, \ 792 U, \ 793 udt_trait> \ 794 { \ 795 using result_types = ::boost::yap::detail::udt_any_binary_op_result< \ 796 expr_template, \ 797 ::boost::yap::expr_kind::op_name, \ 798 T, \ 799 U, \ 800 udt_trait>; \ 801 using lhs_type = typename result_types::lhs_type; \ 802 using rhs_type = typename result_types::rhs_type; \ 803 using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \ 804 return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \ 805 rhs_type{static_cast<U &&>(rhs)}}}; \ 806 } 807 808 809 /** Defines user defined literal template that creates literal placeholders 810 instantiated from the \a expr_template expression template. It is 811 recommended that you put this in its own namespace. 812 813 \param expr_template The expression template to use to instantiate the 814 result expression. \a expr_template must be an \ref 815 ExpressionTemplate. 816 */ 817 #define BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR(expr_template) \ 818 template<char... c> \ 819 constexpr auto operator"" _p() \ 820 { \ 821 using i = ::boost::hana::llong< \ 822 ::boost::hana::ic_detail::parse<sizeof...(c)>({c...})>; \ 823 static_assert(1 <= i::value, "Placeholders must be >= 1."); \ 824 return expr_template< \ 825 ::boost::yap::expr_kind::terminal, \ 826 ::boost::hana::tuple<::boost::yap::placeholder<i::value>>>{}; \ 827 } 828 829 #endif 830