// Copyright (C) 2016-2018 T. Zachary Laine // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_YAP_USER_MACROS_HPP_INCLUDED #define BOOST_YAP_USER_MACROS_HPP_INCLUDED #include #include #include #include #ifndef BOOST_YAP_DOXYGEN // unary #define BOOST_YAP_OPERATOR_unary_plus(...) +(__VA_ARGS__) #define BOOST_YAP_OPERATOR_negate(...) -(__VA_ARGS__) #define BOOST_YAP_OPERATOR_dereference(...) *(__VA_ARGS__) #define BOOST_YAP_OPERATOR_complement(...) ~(__VA_ARGS__) #define BOOST_YAP_OPERATOR_address_of(...) &(__VA_ARGS__) #define BOOST_YAP_OPERATOR_logical_not(...) !(__VA_ARGS__) #define BOOST_YAP_OPERATOR_pre_inc(...) ++(__VA_ARGS__) #define BOOST_YAP_OPERATOR_pre_dec(...) --(__VA_ARGS__) #define BOOST_YAP_OPERATOR_post_inc(...) ++(__VA_ARGS__, int) #define BOOST_YAP_OPERATOR_post_dec(...) --(__VA_ARGS__, int) // binary #define BOOST_YAP_OPERATOR_shift_left(...) <<(__VA_ARGS__) #define BOOST_YAP_OPERATOR_shift_right(...) >>(__VA_ARGS__) #define BOOST_YAP_OPERATOR_multiplies(...) *(__VA_ARGS__) #define BOOST_YAP_OPERATOR_divides(...) /(__VA_ARGS__) #define BOOST_YAP_OPERATOR_modulus(...) %(__VA_ARGS__) #define BOOST_YAP_OPERATOR_plus(...) +(__VA_ARGS__) #define BOOST_YAP_OPERATOR_minus(...) -(__VA_ARGS__) #define BOOST_YAP_OPERATOR_less(...) <(__VA_ARGS__) #define BOOST_YAP_OPERATOR_greater(...) >(__VA_ARGS__) #define BOOST_YAP_OPERATOR_less_equal(...) <=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_greater_equal(...) >=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_equal_to(...) ==(__VA_ARGS__) #define BOOST_YAP_OPERATOR_not_equal_to(...) !=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_logical_or(...) ||(__VA_ARGS__) #define BOOST_YAP_OPERATOR_logical_and(...) &&(__VA_ARGS__) #define BOOST_YAP_OPERATOR_bitwise_and(...) &(__VA_ARGS__) #define BOOST_YAP_OPERATOR_bitwise_or(...) |(__VA_ARGS__) #define BOOST_YAP_OPERATOR_bitwise_xor(...) ^(__VA_ARGS__) #define BOOST_YAP_OPERATOR_comma(...) ,(__VA_ARGS__) #define BOOST_YAP_OPERATOR_mem_ptr(...) ->*(__VA_ARGS__) #define BOOST_YAP_OPERATOR_assign(...) =(__VA_ARGS__) #define BOOST_YAP_OPERATOR_shift_left_assign(...) <<=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_shift_right_assign(...) >>=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_multiplies_assign(...) *=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_divides_assign(...) /=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_modulus_assign(...) %=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_plus_assign(...) +=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_minus_assign(...) -=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_bitwise_and_assign(...) &=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_bitwise_or_assign(...) |=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_bitwise_xor_assign(...) ^=(__VA_ARGS__) #define BOOST_YAP_OPERATOR_subscript(...) [](__VA_ARGS__) #define BOOST_YAP_INDIRECT_CALL(macro) BOOST_PP_CAT(BOOST_YAP_OPERATOR_, macro) #endif // BOOST_YAP_DOXYGEN /** Defines operator overloads for unary operator \a op_name that each take an expression instantiated from \a expr_template and return an expression instantiated from the \a result_expr_template expression template. One overload is defined for each of the qualifiers const &, &, and &&. For the lvalue reference overloads, the argument is captured by reference into the resulting expression. For the rvalue reference overload, the argument is moved into the resulting expression. Example: \snippet user_macros_snippets.cpp USER_UNARY_OPERATOR \param op_name The operator to be overloaded; this must be one of the \b unary enumerators in expr_kind, without the expr_kind:: qualification. \param expr_template The expression template to which the overloads apply. \a expr_template must be an \ref ExpressionTemplate. \param result_expr_template The expression template to use to instantiate the result expression. \a result_expr_template must be an \ref ExpressionTemplate. */ #define BOOST_YAP_USER_UNARY_OPERATOR( \ op_name, expr_template, result_expr_template) \ template<::boost::yap::expr_kind Kind, typename Tuple> \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ expr_template const & x) \ { \ using lhs_type = ::boost::yap::detail::operand_type_t< \ result_expr_template, \ expr_template const &>; \ using tuple_type = ::boost::hana::tuple; \ return result_expr_template< \ ::boost::yap::expr_kind::op_name, \ tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(x)}}; \ } \ template<::boost::yap::expr_kind Kind, typename Tuple> \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ expr_template & x) \ { \ using lhs_type = ::boost::yap::detail::operand_type_t< \ result_expr_template, \ expr_template &>; \ using tuple_type = ::boost::hana::tuple; \ return result_expr_template< \ ::boost::yap::expr_kind::op_name, \ tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(x)}}; \ } \ template<::boost::yap::expr_kind Kind, typename Tuple> \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ expr_template && x) \ { \ using tuple_type = ::boost::hana::tuple>; \ return result_expr_template< \ ::boost::yap::expr_kind::op_name, \ tuple_type>{tuple_type{std::move(x)}}; \ } /** Defines operator overloads for binary operator \a op_name that each produce an expression instantiated from the \a expr_template expression template. One overload is defined for each of the qualifiers const &, &, and &&. For the lvalue reference overloads, *this is captured by reference into the resulting expression. For the rvalue reference overload, *this is moved into the resulting expression. Note that this does not work for yap::expr_kinds assign, subscript, or call. Use BOOST_YAP_USER_ASSIGN_OPERATOR, BOOST_YAP_USER_SUBSCRIPT_OPERATOR, or BOOST_YAP_USER_CALL_OPERATOR for those, respectively. Example: \snippet user_macros_snippets.cpp USER_BINARY_OPERATOR \param op_name The operator to be overloaded; this must be one of the \b binary enumerators in expr_kind, except assign, subscript, or call, without the expr_kind:: qualification. \param expr_template The expression template to which the overloads apply. \a expr_template must be an \ref ExpressionTemplate. \param result_expr_template The expression template to use to instantiate the result expression. \a result_expr_template must be an \ref ExpressionTemplate. */ #define BOOST_YAP_USER_BINARY_OPERATOR( \ op_name, expr_template, result_expr_template) \ template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ expr_template const & lhs, Expr && rhs) \ { \ using lhs_type = ::boost::yap::detail::operand_type_t< \ result_expr_template, \ expr_template const &>; \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return result_expr_template< \ ::boost::yap::expr_kind::op_name, \ tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(lhs), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } \ template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ expr_template & lhs, Expr && rhs) \ { \ using lhs_type = ::boost::yap::detail::operand_type_t< \ result_expr_template, \ expr_template &>; \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return result_expr_template< \ ::boost::yap::expr_kind::op_name, \ tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(lhs), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } \ template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ expr_template && lhs, Expr && rhs) \ { \ using lhs_type = ::boost::yap::detail::remove_cv_ref_t< \ expr_template &&>; \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return result_expr_template< \ ::boost::yap::expr_kind::op_name, \ tuple_type>{ \ tuple_type{std::move(lhs), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } \ template \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ T && lhs, expr_template && rhs) \ ->::boost::yap::detail::free_binary_op_result_t< \ result_expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ expr_template &&> \ { \ using result_types = ::boost::yap::detail::free_binary_op_result< \ result_expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ expr_template &&>; \ using lhs_type = typename result_types::lhs_type; \ using rhs_type = typename result_types::rhs_type; \ using tuple_type = ::boost::hana::tuple; \ return {tuple_type{lhs_type{static_cast(lhs)}, std::move(rhs)}}; \ } \ template \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ T && lhs, expr_template const & rhs) \ ->::boost::yap::detail::free_binary_op_result_t< \ result_expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ expr_template const &> \ { \ using result_types = ::boost::yap::detail::free_binary_op_result< \ result_expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ expr_template const &>; \ using lhs_type = typename result_types::lhs_type; \ using rhs_type = typename result_types::rhs_type; \ using tuple_type = ::boost::hana::tuple; \ using rhs_tuple_type = typename result_types::rhs_tuple_type; \ return {tuple_type{lhs_type{static_cast(lhs)}, \ rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \ } \ template \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ T && lhs, expr_template & rhs) \ ->::boost::yap::detail::free_binary_op_result_t< \ result_expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ expr_template &> \ { \ using result_types = ::boost::yap::detail::free_binary_op_result< \ result_expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ expr_template &>; \ using lhs_type = typename result_types::lhs_type; \ using rhs_type = typename result_types::rhs_type; \ using tuple_type = ::boost::hana::tuple; \ using rhs_tuple_type = typename result_types::rhs_tuple_type; \ return {tuple_type{lhs_type{static_cast(lhs)}, \ rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \ } /** Defines operator overloads for \a operator=() that each produce an expression instantiated from the \a expr_template expression template. One overload is defined for each of the qualifiers const &, &, and &&. For the lvalue reference overloads, *this is captured by reference into the resulting expression. For the rvalue reference overload, *this is moved into the resulting expression. The \a rhs parameter to each of the defined overloads may be any type, including an expression, except that the overloads are constrained by std::enable_if<> not to conflict with the assignment and move assignement operators. If \a rhs is a non-expression, it is wrapped in a terminal expression. Example: \snippet user_macros_snippets.cpp USER_ASSIGN_OPERATOR \param this_type The type of the class the operator is a member of; this is required to avoid clashing with the assignment and move assignement operators. \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. */ #define BOOST_YAP_USER_ASSIGN_OPERATOR(this_type, expr_template) \ template< \ typename Expr, \ typename = std::enable_if_t< \ !::boost::yap::detail::copy_or_move::value>> \ constexpr auto operator=(Expr && rhs) const & \ { \ using lhs_type = ::boost::yap::detail:: \ operand_type_t; \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(*this), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } \ template< \ typename Expr, \ typename = std::enable_if_t< \ !::boost::yap::detail::copy_or_move::value>> \ constexpr auto operator=(Expr && rhs) & \ { \ using lhs_type = ::boost::yap::detail:: \ operand_type_t; \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(*this), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } \ template< \ typename Expr, \ typename = std::enable_if_t< \ !::boost::yap::detail::copy_or_move::value>> \ constexpr auto operator=(Expr && rhs) && \ { \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ tuple_type{std::move(*this), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } /** Defines operator overloads for \a operator[]() that each produce an expression instantiated from the \a expr_template expression template. One overload is defined for each of the qualifiers const &, &, and &&. For the lvalue reference overloads, *this is captured by reference into the resulting expression. For the rvalue reference overload, *this is moved into the resulting expression. The \a rhs parameter to each of the defined overloads may be any type, including an expression, except that the overloads are constrained by std::enable_if<> not to conflict with the assignment and move assignement operators. If \a rhs is a non-expression, it is wrapped in a terminal expression. Example: \snippet user_macros_snippets.cpp USER_SUBSCRIPT_OPERATOR \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. */ #define BOOST_YAP_USER_SUBSCRIPT_OPERATOR(expr_template) \ template \ constexpr auto operator[](Expr && rhs) const & \ { \ using lhs_type = ::boost::yap::detail:: \ operand_type_t; \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(*this), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } \ template \ constexpr auto operator[](Expr && rhs) & \ { \ using lhs_type = ::boost::yap::detail:: \ operand_type_t; \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(*this), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } \ template \ constexpr auto operator[](Expr && rhs) && \ { \ using lhs_type = \ ::boost::yap::detail::remove_cv_ref_t; \ using rhs_type = \ ::boost::yap::detail::operand_type_t; \ using tuple_type = ::boost::hana::tuple; \ return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ tuple_type{std::move(*this), \ ::boost::yap::detail::make_operand{}( \ static_cast(rhs))}}; \ } /** Defines operator overloads for the call operator taking any number of parameters ("operator()") that each produce an expression instantiated from the \a expr_template expression template. One overload is defined for each of the qualifiers const &, &, and &&. For the lvalue reference overloads, *this is captured by reference into the resulting expression. For the rvalue reference overload, *this is moved into the resulting expression. The \a u parameters to each of the defined overloads may be any type, including an expression. Each non-expression is wrapped in a terminal expression. Example: \snippet user_macros_snippets.cpp USER_CALL_OPERATOR \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. */ #define BOOST_YAP_USER_CALL_OPERATOR(expr_template) \ template \ constexpr auto operator()(U &&... u) const & \ { \ using lhs_type = ::boost::yap::detail:: \ operand_type_t; \ using tuple_type = ::boost::hana::tuple< \ lhs_type, \ ::boost::yap::detail::operand_type_t...>; \ return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ tuple_type{ \ ::boost::yap::detail::make_operand{}(*this), \ ::boost::yap::detail::make_operand< \ ::boost::yap::detail::operand_type_t>{}( \ static_cast(u))...}}; \ } \ template \ constexpr auto operator()(U &&... u) & \ { \ using lhs_type = ::boost::yap::detail:: \ operand_type_t; \ using tuple_type = ::boost::hana::tuple< \ lhs_type, \ ::boost::yap::detail::operand_type_t...>; \ return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ tuple_type{ \ ::boost::yap::detail::make_operand{}(*this), \ ::boost::yap::detail::make_operand< \ ::boost::yap::detail::operand_type_t>{}( \ static_cast(u))...}}; \ } \ template \ constexpr auto operator()(U &&... u) && \ { \ using this_type = \ ::boost::yap::detail::remove_cv_ref_t; \ using tuple_type = ::boost::hana::tuple< \ this_type, \ ::boost::yap::detail::operand_type_t...>; \ return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ tuple_type{ \ std::move(*this), \ ::boost::yap::detail::make_operand< \ ::boost::yap::detail::operand_type_t>{}( \ static_cast(u))...}}; \ } #ifndef BOOST_YAP_DOXYGEN #define BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T(z, n, expr_template) \ ::boost::yap::detail::operand_type_t #define BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND(z, n, expr_template) \ ::boost::yap::detail::make_operand<::boost::yap::detail::operand_type_t< \ expr_template, \ BOOST_PP_CAT(U, n)>>{}( \ static_cast(BOOST_PP_CAT(u, n))) #endif /** Defines operator overloads for the call operator taking N parameters ("operator()(t0, t1, ... tn-1)") that each produce an expression instantiated from the \a expr_template expression template. One overload is defined for each of the qualifiers const &, &, and &&. For the lvalue reference overloads, *this is captured by reference into the resulting expression. For the rvalue reference overload, *this is moved into the resulting expression. The \a u parameters to each of the defined overloads may be any type, including an expression. Each non-expression is wrapped in a terminal expression. Example: \snippet user_macros_snippets.cpp USER_CALL_OPERATOR \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. \param n The number of parameters accepted by the operator() overloads. n must be <= BOOST_PP_LIMIT_REPEAT. */ #define BOOST_YAP_USER_CALL_OPERATOR_N(expr_template, n) \ template \ constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) const & \ { \ using lhs_type = ::boost::yap::detail:: \ operand_type_t; \ using tuple_type = ::boost::hana::tuple< \ lhs_type, \ BOOST_PP_ENUM( \ n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \ return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(*this), \ BOOST_PP_ENUM( \ n, \ BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ expr_template)}}; \ } \ template \ constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) & \ { \ using lhs_type = ::boost::yap::detail:: \ operand_type_t; \ using tuple_type = ::boost::hana::tuple< \ lhs_type, \ BOOST_PP_ENUM( \ n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \ return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ tuple_type{::boost::yap::detail::make_operand{}(*this), \ BOOST_PP_ENUM( \ n, \ BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ expr_template)}}; \ } \ template \ constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) && \ { \ using this_type = \ ::boost::yap::detail::remove_cv_ref_t; \ using tuple_type = ::boost::hana::tuple< \ this_type, \ BOOST_PP_ENUM( \ n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \ return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ tuple_type{std::move(*this), \ BOOST_PP_ENUM( \ n, \ BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ expr_template)}}; \ } /** Defines a 3-parameter function if_else() that acts as an analogue to the ternary operator (?:), since the ternary operator is not user-overloadable. The return type of if_else() is an expression instantiated from the \a expr_template expression template. At least one parameter to if_else() must be an expression. For each parameter E passed to if_else(), if E is an rvalue, E is moved into the result, and otherwise E is captured by reference into the result. Example: \snippet user_macros_snippets.cpp USER_EXPR_IF_ELSE \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. */ #define BOOST_YAP_USER_EXPR_IF_ELSE(expr_template) \ template \ constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \ ->::boost::yap::detail:: \ ternary_op_result_t \ { \ using result_types = ::boost::yap::detail:: \ ternary_op_result; \ using cond_type = typename result_types::cond_type; \ using then_type = typename result_types::then_type; \ using else_type = typename result_types::else_type; \ using tuple_type = \ ::boost::hana::tuple; \ return {tuple_type{::boost::yap::detail::make_operand{}( \ static_cast(expr1)), \ ::boost::yap::detail::make_operand{}( \ static_cast(expr2)), \ ::boost::yap::detail::make_operand{}( \ static_cast(expr3))}}; \ } /** Defines a function if_else() that acts as an analogue to the ternary operator (?:), since the ternary operator is not user-overloadable. The return type of if_else() is an expression instantiated from the \a expr_template expression template. Each parameter to if_else() may be any type that is \b not an expression. At least on parameter must be a type T for which \code udt_trait>>::value \endcode is true. Each parameter is wrapped in a terminal expression. Example: \snippet user_macros_snippets.cpp USER_UDT_ANY_IF_ELSE \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. \param udt_trait A trait template to use to constrain which types are accepted as template parameters to if_else(). */ #define BOOST_YAP_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait) \ template \ constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \ ->::boost::yap::detail::udt_any_ternary_op_result_t< \ expr_template, \ Expr1, \ Expr2, \ Expr3, \ udt_trait> \ { \ using result_types = ::boost::yap::detail::udt_any_ternary_op_result< \ expr_template, \ Expr1, \ Expr2, \ Expr3, \ udt_trait>; \ using cond_type = typename result_types::cond_type; \ using then_type = typename result_types::then_type; \ using else_type = typename result_types::else_type; \ using tuple_type = \ ::boost::hana::tuple; \ return {tuple_type{::boost::yap::detail::make_operand{}( \ static_cast(expr1)), \ ::boost::yap::detail::make_operand{}( \ static_cast(expr2)), \ ::boost::yap::detail::make_operand{}( \ static_cast(expr3))}}; \ } /** Defines a free/non-member operator overload for unary operator \a op_name that produces an expression instantiated from the \a expr_template expression template. The parameter to the defined operator overload may be any type that is \b not an expression and for which \code udt_trait>>::value \endcode is true. The parameter is wrapped in a terminal expression. Example: \snippet user_macros_snippets.cpp USER_UDT_UNARY_OPERATOR \param op_name The operator to be overloaded; this must be one of the \b unary enumerators in expr_kind, without the expr_kind:: qualification. \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. \param udt_trait A trait template to use to constrain which types are accepted as template parameters to the defined operator overload. */ #define BOOST_YAP_USER_UDT_UNARY_OPERATOR(op_name, expr_template, udt_trait) \ template \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && x) \ ->::boost::yap::detail::udt_unary_op_result_t< \ expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ udt_trait> \ { \ using result_types = ::boost::yap::detail::udt_unary_op_result< \ expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ udt_trait>; \ using x_type = typename result_types::x_type; \ using tuple_type = ::boost::hana::tuple; \ return {tuple_type{x_type{static_cast(x)}}}; \ } /** Defines a free/non-member operator overload for binary operator \a op_name that produces an expression instantiated from the \a expr_template expression template. The \a lhs parameter to the defined operator overload may be any type that is \b not an expression and for which \code t_udt_trait>>::value \endcode is true. The parameter is wrapped in a terminal expression. The \a rhs parameter to the defined operator overload may be any type that is \b not an expression and for which \code u_udt_trait>>::value \endcode is true. The parameter is wrapped in a terminal expression. Example: \snippet user_macros_snippets.cpp USER_UDT_UDT_BINARY_OPERATOR \param op_name The operator to be overloaded; this must be one of the \b binary enumerators in expr_kind, without the expr_kind:: qualification. \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. \param t_udt_trait A trait template to use to constrain which types are accepted as \a T template parameters to the defined operator overload. \param u_udt_trait A trait template to use to constrain which types are accepted as \a U template parameters to the defined operator overload. */ #define BOOST_YAP_USER_UDT_UDT_BINARY_OPERATOR( \ op_name, expr_template, t_udt_trait, u_udt_trait) \ template \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \ ->::boost::yap::detail::udt_udt_binary_op_result_t< \ expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ U, \ t_udt_trait, \ u_udt_trait> \ { \ using result_types = ::boost::yap::detail::udt_udt_binary_op_result< \ expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ U, \ t_udt_trait, \ u_udt_trait>; \ using lhs_type = typename result_types::lhs_type; \ using rhs_type = typename result_types::rhs_type; \ using tuple_type = ::boost::hana::tuple; \ return {tuple_type{ \ lhs_type{static_cast(lhs)}, \ rhs_type{static_cast(rhs)}, \ }}; \ } /** Defines a free/non-member operator overload for binary operator \a op_name that produces an expression instantiated from the \a expr_template expression template. The \a lhs and \a rhs parameters to the defined operator overload may be any types that are \b not expressions. Each parameter is wrapped in a terminal expression. At least one of the parameters to the defined operator overload must be a type \c T for which \code udt_trait>>::value \endcode is true. Example: \snippet user_macros_snippets.cpp USER_UDT_ANY_BINARY_OPERATOR \param op_name The operator to be overloaded; this must be one of the \b binary enumerators in expr_kind, without the expr_kind:: qualification. \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. \param udt_trait A trait template to use to constrain which types are accepted as template parameters to the defined operator overload. */ #define BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( \ op_name, expr_template, udt_trait) \ template \ constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \ ->::boost::yap::detail::udt_any_binary_op_result_t< \ expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ U, \ udt_trait> \ { \ using result_types = ::boost::yap::detail::udt_any_binary_op_result< \ expr_template, \ ::boost::yap::expr_kind::op_name, \ T, \ U, \ udt_trait>; \ using lhs_type = typename result_types::lhs_type; \ using rhs_type = typename result_types::rhs_type; \ using tuple_type = ::boost::hana::tuple; \ return {tuple_type{lhs_type{static_cast(lhs)}, \ rhs_type{static_cast(rhs)}}}; \ } /** Defines user defined literal template that creates literal placeholders instantiated from the \a expr_template expression template. It is recommended that you put this in its own namespace. \param expr_template The expression template to use to instantiate the result expression. \a expr_template must be an \ref ExpressionTemplate. */ #define BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR(expr_template) \ template \ constexpr auto operator"" _p() \ { \ using i = ::boost::hana::llong< \ ::boost::hana::ic_detail::parse({c...})>; \ static_assert(1 <= i::value, "Placeholders must be >= 1."); \ return expr_template< \ ::boost::yap::expr_kind::terminal, \ ::boost::hana::tuple<::boost::yap::placeholder>>{}; \ } #endif