Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:56

0001 // Copyright (C) 2016-2018 T. Zachary Laine
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 #ifndef BOOST_YAP_USER_MACROS_HPP_INCLUDED
0007 #define BOOST_YAP_USER_MACROS_HPP_INCLUDED
0008 
0009 #include <boost/preprocessor/cat.hpp>
0010 #include <boost/preprocessor/repetition/enum_params.hpp>
0011 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
0012 #include <boost/preprocessor/repetition/enum.hpp>
0013 
0014 
0015 #ifndef BOOST_YAP_DOXYGEN
0016 
0017 // unary
0018 #define BOOST_YAP_OPERATOR_unary_plus(...) +(__VA_ARGS__)
0019 #define BOOST_YAP_OPERATOR_negate(...) -(__VA_ARGS__)
0020 #define BOOST_YAP_OPERATOR_dereference(...) *(__VA_ARGS__)
0021 #define BOOST_YAP_OPERATOR_complement(...) ~(__VA_ARGS__)
0022 #define BOOST_YAP_OPERATOR_address_of(...) &(__VA_ARGS__)
0023 #define BOOST_YAP_OPERATOR_logical_not(...) !(__VA_ARGS__)
0024 #define BOOST_YAP_OPERATOR_pre_inc(...) ++(__VA_ARGS__)
0025 #define BOOST_YAP_OPERATOR_pre_dec(...) --(__VA_ARGS__)
0026 #define BOOST_YAP_OPERATOR_post_inc(...) ++(__VA_ARGS__, int)
0027 #define BOOST_YAP_OPERATOR_post_dec(...) --(__VA_ARGS__, int)
0028 
0029 // binary
0030 #define BOOST_YAP_OPERATOR_shift_left(...) <<(__VA_ARGS__)
0031 #define BOOST_YAP_OPERATOR_shift_right(...) >>(__VA_ARGS__)
0032 #define BOOST_YAP_OPERATOR_multiplies(...) *(__VA_ARGS__)
0033 #define BOOST_YAP_OPERATOR_divides(...) /(__VA_ARGS__)
0034 #define BOOST_YAP_OPERATOR_modulus(...) %(__VA_ARGS__)
0035 #define BOOST_YAP_OPERATOR_plus(...) +(__VA_ARGS__)
0036 #define BOOST_YAP_OPERATOR_minus(...) -(__VA_ARGS__)
0037 #define BOOST_YAP_OPERATOR_less(...) <(__VA_ARGS__)
0038 #define BOOST_YAP_OPERATOR_greater(...) >(__VA_ARGS__)
0039 #define BOOST_YAP_OPERATOR_less_equal(...) <=(__VA_ARGS__)
0040 #define BOOST_YAP_OPERATOR_greater_equal(...) >=(__VA_ARGS__)
0041 #define BOOST_YAP_OPERATOR_equal_to(...) ==(__VA_ARGS__)
0042 #define BOOST_YAP_OPERATOR_not_equal_to(...) !=(__VA_ARGS__)
0043 #define BOOST_YAP_OPERATOR_logical_or(...) ||(__VA_ARGS__)
0044 #define BOOST_YAP_OPERATOR_logical_and(...) &&(__VA_ARGS__)
0045 #define BOOST_YAP_OPERATOR_bitwise_and(...) &(__VA_ARGS__)
0046 #define BOOST_YAP_OPERATOR_bitwise_or(...) |(__VA_ARGS__)
0047 #define BOOST_YAP_OPERATOR_bitwise_xor(...) ^(__VA_ARGS__)
0048 #define BOOST_YAP_OPERATOR_comma(...) ,(__VA_ARGS__)
0049 #define BOOST_YAP_OPERATOR_mem_ptr(...) ->*(__VA_ARGS__)
0050 #define BOOST_YAP_OPERATOR_assign(...) =(__VA_ARGS__)
0051 #define BOOST_YAP_OPERATOR_shift_left_assign(...) <<=(__VA_ARGS__)
0052 #define BOOST_YAP_OPERATOR_shift_right_assign(...) >>=(__VA_ARGS__)
0053 #define BOOST_YAP_OPERATOR_multiplies_assign(...) *=(__VA_ARGS__)
0054 #define BOOST_YAP_OPERATOR_divides_assign(...) /=(__VA_ARGS__)
0055 #define BOOST_YAP_OPERATOR_modulus_assign(...) %=(__VA_ARGS__)
0056 #define BOOST_YAP_OPERATOR_plus_assign(...) +=(__VA_ARGS__)
0057 #define BOOST_YAP_OPERATOR_minus_assign(...) -=(__VA_ARGS__)
0058 #define BOOST_YAP_OPERATOR_bitwise_and_assign(...) &=(__VA_ARGS__)
0059 #define BOOST_YAP_OPERATOR_bitwise_or_assign(...) |=(__VA_ARGS__)
0060 #define BOOST_YAP_OPERATOR_bitwise_xor_assign(...) ^=(__VA_ARGS__)
0061 #define BOOST_YAP_OPERATOR_subscript(...) [](__VA_ARGS__)
0062 
0063 #define BOOST_YAP_INDIRECT_CALL(macro) BOOST_PP_CAT(BOOST_YAP_OPERATOR_, macro)
0064 
0065 #endif // BOOST_YAP_DOXYGEN
0066 
0067 
0068 /** Defines operator overloads for unary operator \a op_name that each take an
0069     expression instantiated from \a expr_template and return an expression
0070     instantiated from the \a result_expr_template expression template.  One
0071     overload is defined for each of the qualifiers <code>const &</code>,
0072     <code>&</code>, and <code>&&</code>.  For the lvalue reference overloads,
0073     the argument is captured by reference into the resulting expression.  For
0074     the rvalue reference overload, the argument is moved into the resulting
0075     expression.
0076 
0077     Example:
0078     \snippet user_macros_snippets.cpp USER_UNARY_OPERATOR
0079 
0080     \param op_name The operator to be overloaded; this must be one of the \b
0081     unary enumerators in <code>expr_kind</code>, without the
0082     <code>expr_kind::</code> qualification.
0083 
0084     \param expr_template The expression template to which the overloads apply.
0085     \a expr_template must be an \ref ExpressionTemplate.
0086 
0087     \param result_expr_template The expression template to use to instantiate
0088     the result expression.  \a result_expr_template must be an \ref
0089     ExpressionTemplate.
0090 */
0091 #define BOOST_YAP_USER_UNARY_OPERATOR(                                         \
0092     op_name, expr_template, result_expr_template)                              \
0093     template<::boost::yap::expr_kind Kind, typename Tuple>                     \
0094     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0095         expr_template<Kind, Tuple> const & x)                                  \
0096     {                                                                          \
0097         using lhs_type = ::boost::yap::detail::operand_type_t<                 \
0098             result_expr_template,                                              \
0099             expr_template<Kind, Tuple> const &>;                               \
0100         using tuple_type = ::boost::hana::tuple<lhs_type>;                     \
0101         return result_expr_template<                                           \
0102             ::boost::yap::expr_kind::op_name,                                  \
0103             tuple_type>{                                                       \
0104             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}};    \
0105     }                                                                          \
0106     template<::boost::yap::expr_kind Kind, typename Tuple>                     \
0107     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0108         expr_template<Kind, Tuple> & x)                                        \
0109     {                                                                          \
0110         using lhs_type = ::boost::yap::detail::operand_type_t<                 \
0111             result_expr_template,                                              \
0112             expr_template<Kind, Tuple> &>;                                     \
0113         using tuple_type = ::boost::hana::tuple<lhs_type>;                     \
0114         return result_expr_template<                                           \
0115             ::boost::yap::expr_kind::op_name,                                  \
0116             tuple_type>{                                                       \
0117             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}};    \
0118     }                                                                          \
0119     template<::boost::yap::expr_kind Kind, typename Tuple>                     \
0120     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0121         expr_template<Kind, Tuple> && x)                                       \
0122     {                                                                          \
0123         using tuple_type = ::boost::hana::tuple<expr_template<Kind, Tuple>>;   \
0124         return result_expr_template<                                           \
0125             ::boost::yap::expr_kind::op_name,                                  \
0126             tuple_type>{tuple_type{std::move(x)}};                             \
0127     }
0128 
0129 
0130 /** Defines operator overloads for binary operator \a op_name that each
0131     produce an expression instantiated from the \a expr_template expression
0132     template.  One overload is defined for each of the qualifiers <code>const
0133     &</code>, <code>&</code>, and <code>&&</code>.  For the lvalue reference
0134     overloads, <code>*this</code> is captured by reference into the resulting
0135     expression.  For the rvalue reference overload, <code>*this</code> is
0136     moved into the resulting expression.
0137 
0138     Note that this does not work for yap::expr_kinds assign, subscript, or
0139     call.  Use BOOST_YAP_USER_ASSIGN_OPERATOR,
0140     BOOST_YAP_USER_SUBSCRIPT_OPERATOR, or BOOST_YAP_USER_CALL_OPERATOR for
0141     those, respectively.
0142 
0143     Example:
0144     \snippet user_macros_snippets.cpp USER_BINARY_OPERATOR
0145 
0146     \param op_name The operator to be overloaded; this must be one of the \b
0147     binary enumerators in <code>expr_kind</code>, except assign, subscript, or
0148     call, without the <code>expr_kind::</code> qualification.
0149 
0150     \param expr_template The expression template to which the overloads apply.
0151     \a expr_template must be an \ref ExpressionTemplate.
0152 
0153     \param result_expr_template The expression template to use to instantiate
0154     the result expression.  \a result_expr_template must be an \ref
0155     ExpressionTemplate.
0156 */
0157 #define BOOST_YAP_USER_BINARY_OPERATOR(                                        \
0158     op_name, expr_template, result_expr_template)                              \
0159     template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr>      \
0160     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0161         expr_template<Kind, Tuple> const & lhs, Expr && rhs)                   \
0162     {                                                                          \
0163         using lhs_type = ::boost::yap::detail::operand_type_t<                 \
0164             result_expr_template,                                              \
0165             expr_template<Kind, Tuple> const &>;                               \
0166         using rhs_type =                                                       \
0167             ::boost::yap::detail::operand_type_t<result_expr_template, Expr>;  \
0168         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0169         return result_expr_template<                                           \
0170             ::boost::yap::expr_kind::op_name,                                  \
0171             tuple_type>{                                                       \
0172             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs),    \
0173                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0174                            static_cast<Expr &&>(rhs))}};                       \
0175     }                                                                          \
0176     template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr>      \
0177     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0178         expr_template<Kind, Tuple> & lhs, Expr && rhs)                         \
0179     {                                                                          \
0180         using lhs_type = ::boost::yap::detail::operand_type_t<                 \
0181             result_expr_template,                                              \
0182             expr_template<Kind, Tuple> &>;                                     \
0183         using rhs_type =                                                       \
0184             ::boost::yap::detail::operand_type_t<result_expr_template, Expr>;  \
0185         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0186         return result_expr_template<                                           \
0187             ::boost::yap::expr_kind::op_name,                                  \
0188             tuple_type>{                                                       \
0189             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs),    \
0190                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0191                            static_cast<Expr &&>(rhs))}};                       \
0192     }                                                                          \
0193     template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr>      \
0194     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0195         expr_template<Kind, Tuple> && lhs, Expr && rhs)                        \
0196     {                                                                          \
0197         using lhs_type = ::boost::yap::detail::remove_cv_ref_t<                \
0198             expr_template<Kind, Tuple> &&>;                                    \
0199         using rhs_type =                                                       \
0200             ::boost::yap::detail::operand_type_t<result_expr_template, Expr>;  \
0201         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0202         return result_expr_template<                                           \
0203             ::boost::yap::expr_kind::op_name,                                  \
0204             tuple_type>{                                                       \
0205             tuple_type{std::move(lhs),                                         \
0206                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0207                            static_cast<Expr &&>(rhs))}};                       \
0208     }                                                                          \
0209     template<typename T, ::boost::yap::expr_kind Kind, typename Tuple>         \
0210     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0211         T && lhs, expr_template<Kind, Tuple> && rhs)                           \
0212         ->::boost::yap::detail::free_binary_op_result_t<                       \
0213             result_expr_template,                                              \
0214             ::boost::yap::expr_kind::op_name,                                  \
0215             T,                                                                 \
0216             expr_template<Kind, Tuple> &&>                                     \
0217     {                                                                          \
0218         using result_types = ::boost::yap::detail::free_binary_op_result<      \
0219             result_expr_template,                                              \
0220             ::boost::yap::expr_kind::op_name,                                  \
0221             T,                                                                 \
0222             expr_template<Kind, Tuple> &&>;                                    \
0223         using lhs_type = typename result_types::lhs_type;                      \
0224         using rhs_type = typename result_types::rhs_type;                      \
0225         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0226         return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, std::move(rhs)}}; \
0227     }                                                                          \
0228     template<typename T, ::boost::yap::expr_kind Kind, typename Tuple>         \
0229     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0230         T && lhs, expr_template<Kind, Tuple> const & rhs)                      \
0231         ->::boost::yap::detail::free_binary_op_result_t<                       \
0232             result_expr_template,                                              \
0233             ::boost::yap::expr_kind::op_name,                                  \
0234             T,                                                                 \
0235             expr_template<Kind, Tuple> const &>                                \
0236     {                                                                          \
0237         using result_types = ::boost::yap::detail::free_binary_op_result<      \
0238             result_expr_template,                                              \
0239             ::boost::yap::expr_kind::op_name,                                  \
0240             T,                                                                 \
0241             expr_template<Kind, Tuple> const &>;                               \
0242         using lhs_type = typename result_types::lhs_type;                      \
0243         using rhs_type = typename result_types::rhs_type;                      \
0244         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0245         using rhs_tuple_type = typename result_types::rhs_tuple_type;          \
0246         return {tuple_type{lhs_type{static_cast<T &&>(lhs)},                   \
0247                            rhs_type{rhs_tuple_type{std::addressof(rhs)}}}};    \
0248     }                                                                          \
0249     template<typename T, ::boost::yap::expr_kind Kind, typename Tuple>         \
0250     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
0251         T && lhs, expr_template<Kind, Tuple> & rhs)                            \
0252         ->::boost::yap::detail::free_binary_op_result_t<                       \
0253             result_expr_template,                                              \
0254             ::boost::yap::expr_kind::op_name,                                  \
0255             T,                                                                 \
0256             expr_template<Kind, Tuple> &>                                      \
0257     {                                                                          \
0258         using result_types = ::boost::yap::detail::free_binary_op_result<      \
0259             result_expr_template,                                              \
0260             ::boost::yap::expr_kind::op_name,                                  \
0261             T,                                                                 \
0262             expr_template<Kind, Tuple> &>;                                     \
0263         using lhs_type = typename result_types::lhs_type;                      \
0264         using rhs_type = typename result_types::rhs_type;                      \
0265         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0266         using rhs_tuple_type = typename result_types::rhs_tuple_type;          \
0267         return {tuple_type{lhs_type{static_cast<T &&>(lhs)},                   \
0268                            rhs_type{rhs_tuple_type{std::addressof(rhs)}}}};    \
0269     }
0270 
0271 
0272 /** Defines operator overloads for \a operator=() that each produce an
0273     expression instantiated from the \a expr_template expression template.
0274     One overload is defined for each of the qualifiers <code>const &</code>,
0275     <code>&</code>, and <code>&&</code>.  For the lvalue reference overloads,
0276     <code>*this</code> is captured by reference into the resulting expression.
0277     For the rvalue reference overload, <code>*this</code> is moved into the
0278     resulting expression.
0279 
0280     The \a rhs parameter to each of the defined overloads may be any type,
0281     including an expression, except that the overloads are constrained by
0282     std::enable_if<> not to conflict with the assignment and move assignement
0283     operators.  If \a rhs is a non-expression, it is wrapped in a terminal
0284     expression.
0285 
0286     Example:
0287     \snippet user_macros_snippets.cpp USER_ASSIGN_OPERATOR
0288 
0289     \param this_type The type of the class the operator is a member of; this
0290     is required to avoid clashing with the assignment and move assignement
0291     operators.
0292 
0293     \param expr_template The expression template to use to instantiate the
0294     result expression.  \a expr_template must be an \ref
0295     ExpressionTemplate.
0296 */
0297 #define BOOST_YAP_USER_ASSIGN_OPERATOR(this_type, expr_template)               \
0298     template<                                                                  \
0299         typename Expr,                                                         \
0300         typename = std::enable_if_t<                                           \
0301             !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>>   \
0302     constexpr auto operator=(Expr && rhs) const &                              \
0303     {                                                                          \
0304         using lhs_type = ::boost::yap::detail::                                \
0305             operand_type_t<expr_template, this_type const &>;                  \
0306         using rhs_type =                                                       \
0307             ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
0308         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0309         return expr_template<::boost::yap::expr_kind::assign, tuple_type>{     \
0310             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
0311                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0312                            static_cast<Expr &&>(rhs))}};                       \
0313     }                                                                          \
0314     template<                                                                  \
0315         typename Expr,                                                         \
0316         typename = std::enable_if_t<                                           \
0317             !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>>   \
0318     constexpr auto operator=(Expr && rhs) &                                    \
0319     {                                                                          \
0320         using lhs_type = ::boost::yap::detail::                                \
0321             operand_type_t<expr_template, decltype(*this)>;                    \
0322         using rhs_type =                                                       \
0323             ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
0324         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0325         return expr_template<::boost::yap::expr_kind::assign, tuple_type>{     \
0326             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
0327                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0328                            static_cast<Expr &&>(rhs))}};                       \
0329     }                                                                          \
0330     template<                                                                  \
0331         typename Expr,                                                         \
0332         typename = std::enable_if_t<                                           \
0333             !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>>   \
0334     constexpr auto operator=(Expr && rhs) &&                                   \
0335     {                                                                          \
0336         using rhs_type =                                                       \
0337             ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
0338         using tuple_type = ::boost::hana::tuple<this_type, rhs_type>;          \
0339         return expr_template<::boost::yap::expr_kind::assign, tuple_type>{     \
0340             tuple_type{std::move(*this),                                       \
0341                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0342                            static_cast<Expr &&>(rhs))}};                       \
0343     }
0344 
0345 
0346 /** Defines operator overloads for \a operator[]() that each produce an
0347     expression instantiated from the \a expr_template expression template.
0348     One overload is defined for each of the qualifiers <code>const &</code>,
0349     <code>&</code>, and <code>&&</code>.  For the lvalue reference overloads,
0350     <code>*this</code> is captured by reference into the resulting expression.
0351     For the rvalue reference overload, <code>*this</code> is moved into the
0352     resulting expression.
0353 
0354     The \a rhs parameter to each of the defined overloads may be any type,
0355     including an expression, except that the overloads are constrained by
0356     std::enable_if<> not to conflict with the assignment and move assignement
0357     operators.  If \a rhs is a non-expression, it is wrapped in a terminal
0358     expression.
0359 
0360     Example:
0361     \snippet user_macros_snippets.cpp USER_SUBSCRIPT_OPERATOR
0362 
0363     \param expr_template The expression template to use to instantiate the
0364     result expression.  \a expr_template must be an \ref
0365     ExpressionTemplate.
0366 */
0367 #define BOOST_YAP_USER_SUBSCRIPT_OPERATOR(expr_template)                       \
0368     template<typename Expr>                                                    \
0369     constexpr auto operator[](Expr && rhs) const &                             \
0370     {                                                                          \
0371         using lhs_type = ::boost::yap::detail::                                \
0372             operand_type_t<expr_template, decltype(*this)>;                    \
0373         using rhs_type =                                                       \
0374             ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
0375         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0376         return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{  \
0377             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
0378                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0379                            static_cast<Expr &&>(rhs))}};                       \
0380     }                                                                          \
0381     template<typename Expr>                                                    \
0382     constexpr auto operator[](Expr && rhs) &                                   \
0383     {                                                                          \
0384         using lhs_type = ::boost::yap::detail::                                \
0385             operand_type_t<expr_template, decltype(*this)>;                    \
0386         using rhs_type =                                                       \
0387             ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
0388         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0389         return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{  \
0390             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
0391                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0392                            static_cast<Expr &&>(rhs))}};                       \
0393     }                                                                          \
0394     template<typename Expr>                                                    \
0395     constexpr auto operator[](Expr && rhs) &&                                  \
0396     {                                                                          \
0397         using lhs_type =                                                       \
0398             ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>;            \
0399         using rhs_type =                                                       \
0400             ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
0401         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0402         return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{  \
0403             tuple_type{std::move(*this),                                       \
0404                        ::boost::yap::detail::make_operand<rhs_type>{}(         \
0405                            static_cast<Expr &&>(rhs))}};                       \
0406     }
0407 
0408 
0409 /** Defines operator overloads for the call operator taking any number of
0410     parameters ("operator()") that each produce an expression instantiated
0411     from the \a expr_template expression template.  One overload is defined
0412     for each of the qualifiers <code>const &</code>, <code>&</code>, and
0413     <code>&&</code>.  For the lvalue reference overloads, <code>*this</code>
0414     is captured by reference into the resulting expression.  For the rvalue
0415     reference overload, <code>*this</code> is moved into the resulting
0416     expression.
0417 
0418     The \a u parameters to each of the defined overloads may be any type,
0419     including an expression.  Each non-expression is wrapped in a terminal
0420     expression.
0421 
0422     Example:
0423     \snippet user_macros_snippets.cpp USER_CALL_OPERATOR
0424 
0425     \param expr_template The expression template to use to instantiate the
0426     result expression.  \a expr_template must be an \ref
0427     ExpressionTemplate.
0428 */
0429 #define BOOST_YAP_USER_CALL_OPERATOR(expr_template)                            \
0430     template<typename... U>                                                    \
0431     constexpr auto operator()(U &&... u) const &                               \
0432     {                                                                          \
0433         using lhs_type = ::boost::yap::detail::                                \
0434             operand_type_t<expr_template, decltype(*this)>;                    \
0435         using tuple_type = ::boost::hana::tuple<                               \
0436             lhs_type,                                                          \
0437             ::boost::yap::detail::operand_type_t<expr_template, U>...>;        \
0438         return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
0439             tuple_type{                                                        \
0440                 ::boost::yap::detail::make_operand<lhs_type>{}(*this),         \
0441                 ::boost::yap::detail::make_operand<                            \
0442                     ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
0443                     static_cast<U &&>(u))...}};                                \
0444     }                                                                          \
0445     template<typename... U>                                                    \
0446     constexpr auto operator()(U &&... u) &                                     \
0447     {                                                                          \
0448         using lhs_type = ::boost::yap::detail::                                \
0449             operand_type_t<expr_template, decltype(*this)>;                    \
0450         using tuple_type = ::boost::hana::tuple<                               \
0451             lhs_type,                                                          \
0452             ::boost::yap::detail::operand_type_t<expr_template, U>...>;        \
0453         return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
0454             tuple_type{                                                        \
0455                 ::boost::yap::detail::make_operand<lhs_type>{}(*this),         \
0456                 ::boost::yap::detail::make_operand<                            \
0457                     ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
0458                     static_cast<U &&>(u))...}};                                \
0459     }                                                                          \
0460     template<typename... U>                                                    \
0461     constexpr auto operator()(U &&... u) &&                                    \
0462     {                                                                          \
0463         using this_type =                                                      \
0464             ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>;            \
0465         using tuple_type = ::boost::hana::tuple<                               \
0466             this_type,                                                         \
0467             ::boost::yap::detail::operand_type_t<expr_template, U>...>;        \
0468         return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
0469             tuple_type{                                                        \
0470                 std::move(*this),                                              \
0471                 ::boost::yap::detail::make_operand<                            \
0472                     ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
0473                     static_cast<U &&>(u))...}};                                \
0474     }
0475 
0476 
0477 #ifndef BOOST_YAP_DOXYGEN
0478 
0479 #define BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T(z, n, expr_template)            \
0480     ::boost::yap::detail::operand_type_t<expr_template, BOOST_PP_CAT(U, n)>
0481 #define BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND(z, n, expr_template)         \
0482     ::boost::yap::detail::make_operand<::boost::yap::detail::operand_type_t<   \
0483         expr_template,                                                         \
0484         BOOST_PP_CAT(U, n)>>{}(                                                \
0485         static_cast<BOOST_PP_CAT(U, n) &&>(BOOST_PP_CAT(u, n)))
0486 
0487 #endif
0488 
0489 /** Defines operator overloads for the call operator taking N parameters
0490     ("operator()(t0, t1, ... tn-1)") that each produce an expression
0491     instantiated from the \a expr_template expression template.  One overload
0492     is defined for each of the qualifiers <code>const &</code>,
0493     <code>&</code>, and <code>&&</code>.  For the lvalue reference overloads,
0494     <code>*this</code> is captured by reference into the resulting expression.
0495     For the rvalue reference overload, <code>*this</code> is moved into the
0496     resulting expression.
0497 
0498     The \a u parameters to each of the defined overloads may be any type,
0499     including an expression.  Each non-expression is wrapped in a terminal
0500     expression.
0501 
0502     Example:
0503     \snippet user_macros_snippets.cpp USER_CALL_OPERATOR
0504 
0505     \param expr_template The expression template to use to instantiate the
0506     result expression.  \a expr_template must be an \ref
0507     ExpressionTemplate.
0508 
0509     \param n The number of parameters accepted by the operator() overloads.  n
0510     must be <= BOOST_PP_LIMIT_REPEAT.
0511 */
0512 #define BOOST_YAP_USER_CALL_OPERATOR_N(expr_template, n)                       \
0513     template<BOOST_PP_ENUM_PARAMS(n, typename U)>                              \
0514     constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) const &  \
0515     {                                                                          \
0516         using lhs_type = ::boost::yap::detail::                                \
0517             operand_type_t<expr_template, decltype(*this)>;                    \
0518         using tuple_type = ::boost::hana::tuple<                               \
0519             lhs_type,                                                          \
0520             BOOST_PP_ENUM(                                                     \
0521                 n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>;    \
0522         return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
0523             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
0524                        BOOST_PP_ENUM(                                          \
0525                            n,                                                  \
0526                            BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND,          \
0527                            expr_template)}};                                   \
0528     }                                                                          \
0529     template<BOOST_PP_ENUM_PARAMS(n, typename U)>                              \
0530     constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) &        \
0531     {                                                                          \
0532         using lhs_type = ::boost::yap::detail::                                \
0533             operand_type_t<expr_template, decltype(*this)>;                    \
0534         using tuple_type = ::boost::hana::tuple<                               \
0535             lhs_type,                                                          \
0536             BOOST_PP_ENUM(                                                     \
0537                 n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>;    \
0538         return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
0539             tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
0540                        BOOST_PP_ENUM(                                          \
0541                            n,                                                  \
0542                            BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND,          \
0543                            expr_template)}};                                   \
0544     }                                                                          \
0545     template<BOOST_PP_ENUM_PARAMS(n, typename U)>                              \
0546     constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) &&       \
0547     {                                                                          \
0548         using this_type =                                                      \
0549             ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>;            \
0550         using tuple_type = ::boost::hana::tuple<                               \
0551             this_type,                                                         \
0552             BOOST_PP_ENUM(                                                     \
0553                 n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>;    \
0554         return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
0555             tuple_type{std::move(*this),                                       \
0556                        BOOST_PP_ENUM(                                          \
0557                            n,                                                  \
0558                            BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND,          \
0559                            expr_template)}};                                   \
0560     }
0561 
0562 
0563 /** Defines a 3-parameter function <code>if_else()</code> that acts as an
0564     analogue to the ternary operator (<code>?:</code>), since the ternary
0565     operator is not user-overloadable.  The return type of
0566     <code>if_else()</code> is an expression instantiated from the \a
0567     expr_template expression template.
0568 
0569     At least one parameter to <code>if_else()</code> must be an expression.
0570 
0571     For each parameter E passed to <code>if_else()</code>, if E is an rvalue,
0572     E is moved into the result, and otherwise E is captured by reference into
0573     the result.
0574 
0575     Example:
0576     \snippet user_macros_snippets.cpp USER_EXPR_IF_ELSE
0577 
0578     \param expr_template The expression template to use to instantiate the
0579     result expression.  \a expr_template must be an \ref
0580     ExpressionTemplate.
0581 */
0582 #define BOOST_YAP_USER_EXPR_IF_ELSE(expr_template)                             \
0583     template<typename Expr1, typename Expr2, typename Expr3>                   \
0584     constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3)     \
0585         ->::boost::yap::detail::                                               \
0586             ternary_op_result_t<expr_template, Expr1, Expr2, Expr3>            \
0587     {                                                                          \
0588         using result_types = ::boost::yap::detail::                            \
0589             ternary_op_result<expr_template, Expr1, Expr2, Expr3>;             \
0590         using cond_type = typename result_types::cond_type;                    \
0591         using then_type = typename result_types::then_type;                    \
0592         using else_type = typename result_types::else_type;                    \
0593         using tuple_type =                                                     \
0594             ::boost::hana::tuple<cond_type, then_type, else_type>;             \
0595         return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}(    \
0596                                static_cast<Expr1 &&>(expr1)),                  \
0597                            ::boost::yap::detail::make_operand<then_type>{}(    \
0598                                static_cast<Expr2 &&>(expr2)),                  \
0599                            ::boost::yap::detail::make_operand<else_type>{}(    \
0600                                static_cast<Expr3 &&>(expr3))}};                \
0601     }
0602 
0603 
0604 /** Defines a function <code>if_else()</code> that acts as an analogue to the
0605     ternary operator (<code>?:</code>), since the ternary operator is not
0606     user-overloadable.  The return type of <code>if_else()</code> is an
0607     expression instantiated from the \a expr_template expression template.
0608 
0609     Each parameter to <code>if_else()</code> may be any type that is \b not an
0610     expression.  At least on parameter must be a type <code>T</code> for which
0611     \code udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value
0612     \endcode is true.  Each parameter is wrapped in a terminal expression.
0613 
0614     Example:
0615     \snippet user_macros_snippets.cpp USER_UDT_ANY_IF_ELSE
0616 
0617     \param expr_template The expression template to use to instantiate the
0618     result expression.  \a expr_template must be an \ref
0619     ExpressionTemplate.
0620 
0621     \param udt_trait A trait template to use to constrain which types are
0622     accepted as template parameters to <code>if_else()</code>.
0623 */
0624 #define BOOST_YAP_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait)               \
0625     template<typename Expr1, typename Expr2, typename Expr3>                   \
0626     constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3)     \
0627         ->::boost::yap::detail::udt_any_ternary_op_result_t<                   \
0628             expr_template,                                                     \
0629             Expr1,                                                             \
0630             Expr2,                                                             \
0631             Expr3,                                                             \
0632             udt_trait>                                                         \
0633     {                                                                          \
0634         using result_types = ::boost::yap::detail::udt_any_ternary_op_result<  \
0635             expr_template,                                                     \
0636             Expr1,                                                             \
0637             Expr2,                                                             \
0638             Expr3,                                                             \
0639             udt_trait>;                                                        \
0640         using cond_type = typename result_types::cond_type;                    \
0641         using then_type = typename result_types::then_type;                    \
0642         using else_type = typename result_types::else_type;                    \
0643         using tuple_type =                                                     \
0644             ::boost::hana::tuple<cond_type, then_type, else_type>;             \
0645         return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}(    \
0646                                static_cast<Expr1 &&>(expr1)),                  \
0647                            ::boost::yap::detail::make_operand<then_type>{}(    \
0648                                static_cast<Expr2 &&>(expr2)),                  \
0649                            ::boost::yap::detail::make_operand<else_type>{}(    \
0650                                static_cast<Expr3 &&>(expr3))}};                \
0651     }
0652 
0653 
0654 /** Defines a free/non-member operator overload for unary operator \a op_name
0655     that produces an expression instantiated from the \a expr_template
0656     expression template.
0657 
0658     The parameter to the defined operator overload may be any type that is \b
0659     not an expression and for which \code
0660     udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
0661     true.  The parameter is wrapped in a terminal expression.
0662 
0663     Example:
0664     \snippet user_macros_snippets.cpp USER_UDT_UNARY_OPERATOR
0665 
0666     \param op_name The operator to be overloaded; this must be one of the \b
0667     unary enumerators in <code>expr_kind</code>, without the
0668     <code>expr_kind::</code> qualification.
0669 
0670     \param expr_template The expression template to use to instantiate the
0671     result expression.  \a expr_template must be an \ref
0672     ExpressionTemplate.
0673 
0674     \param udt_trait A trait template to use to constrain which types are
0675     accepted as template parameters to the defined operator overload.
0676 */
0677 #define BOOST_YAP_USER_UDT_UNARY_OPERATOR(op_name, expr_template, udt_trait)   \
0678     template<typename T>                                                       \
0679     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && x)           \
0680         ->::boost::yap::detail::udt_unary_op_result_t<                         \
0681             expr_template,                                                     \
0682             ::boost::yap::expr_kind::op_name,                                  \
0683             T,                                                                 \
0684             udt_trait>                                                         \
0685     {                                                                          \
0686         using result_types = ::boost::yap::detail::udt_unary_op_result<        \
0687             expr_template,                                                     \
0688             ::boost::yap::expr_kind::op_name,                                  \
0689             T,                                                                 \
0690             udt_trait>;                                                        \
0691         using x_type = typename result_types::x_type;                          \
0692         using tuple_type = ::boost::hana::tuple<x_type>;                       \
0693         return {tuple_type{x_type{static_cast<T &&>(x)}}};                     \
0694     }
0695 
0696 
0697 /** Defines a free/non-member operator overload for binary operator \a op_name
0698     that produces an expression instantiated from the \a expr_template
0699     expression template.
0700 
0701     The \a lhs parameter to the defined operator overload may be any type that
0702     is \b not an expression and for which \code
0703     t_udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
0704     true.  The parameter is wrapped in a terminal expression.
0705 
0706     The \a rhs parameter to the defined operator overload may be any type that
0707     is \b not an expression and for which \code
0708     u_udt_trait<std::remove_cv_t<std::remove_reference_t<U>>>::value \endcode is
0709     true.  The parameter is wrapped in a terminal expression.
0710 
0711     Example:
0712     \snippet user_macros_snippets.cpp USER_UDT_UDT_BINARY_OPERATOR
0713 
0714     \param op_name The operator to be overloaded; this must be one of the \b
0715     binary enumerators in <code>expr_kind</code>, without the
0716     <code>expr_kind::</code> qualification.
0717 
0718     \param expr_template The expression template to use to instantiate the
0719     result expression.  \a expr_template must be an \ref
0720     ExpressionTemplate.
0721 
0722     \param t_udt_trait A trait template to use to constrain which types are
0723     accepted as \a T template parameters to the defined operator overload.
0724 
0725     \param u_udt_trait A trait template to use to constrain which types are
0726     accepted as \a U template parameters to the defined operator overload.
0727 */
0728 #define BOOST_YAP_USER_UDT_UDT_BINARY_OPERATOR(                                \
0729     op_name, expr_template, t_udt_trait, u_udt_trait)                          \
0730     template<typename T, typename U>                                           \
0731     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \
0732         ->::boost::yap::detail::udt_udt_binary_op_result_t<                    \
0733             expr_template,                                                     \
0734             ::boost::yap::expr_kind::op_name,                                  \
0735             T,                                                                 \
0736             U,                                                                 \
0737             t_udt_trait,                                                       \
0738             u_udt_trait>                                                       \
0739     {                                                                          \
0740         using result_types = ::boost::yap::detail::udt_udt_binary_op_result<   \
0741             expr_template,                                                     \
0742             ::boost::yap::expr_kind::op_name,                                  \
0743             T,                                                                 \
0744             U,                                                                 \
0745             t_udt_trait,                                                       \
0746             u_udt_trait>;                                                      \
0747         using lhs_type = typename result_types::lhs_type;                      \
0748         using rhs_type = typename result_types::rhs_type;                      \
0749         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0750         return {tuple_type{                                                    \
0751             lhs_type{static_cast<T &&>(lhs)},                                  \
0752             rhs_type{static_cast<U &&>(rhs)},                                  \
0753         }};                                                                    \
0754     }
0755 
0756 
0757 /** Defines a free/non-member operator overload for binary operator \a op_name
0758     that produces an expression instantiated from the \a expr_template
0759     expression template.
0760 
0761     The \a lhs and \a rhs parameters to the defined operator overload may be any
0762    types that are \b not expressions.  Each parameter is wrapped in a terminal
0763    expression.
0764 
0765     At least one of the parameters to the defined operator overload must be a
0766     type \c T for which \code
0767     udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
0768     true.
0769 
0770     Example:
0771     \snippet user_macros_snippets.cpp USER_UDT_ANY_BINARY_OPERATOR
0772 
0773     \param op_name The operator to be overloaded; this must be one of the \b
0774     binary enumerators in <code>expr_kind</code>, without the
0775     <code>expr_kind::</code> qualification.
0776 
0777     \param expr_template The expression template to use to instantiate the
0778     result expression.  \a expr_template must be an \ref
0779     ExpressionTemplate.
0780 
0781     \param udt_trait A trait template to use to constrain which types are
0782     accepted as template parameters to the defined operator overload.
0783 */
0784 #define BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(                                \
0785     op_name, expr_template, udt_trait)                                         \
0786     template<typename T, typename U>                                           \
0787     constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \
0788         ->::boost::yap::detail::udt_any_binary_op_result_t<                    \
0789             expr_template,                                                     \
0790             ::boost::yap::expr_kind::op_name,                                  \
0791             T,                                                                 \
0792             U,                                                                 \
0793             udt_trait>                                                         \
0794     {                                                                          \
0795         using result_types = ::boost::yap::detail::udt_any_binary_op_result<   \
0796             expr_template,                                                     \
0797             ::boost::yap::expr_kind::op_name,                                  \
0798             T,                                                                 \
0799             U,                                                                 \
0800             udt_trait>;                                                        \
0801         using lhs_type = typename result_types::lhs_type;                      \
0802         using rhs_type = typename result_types::rhs_type;                      \
0803         using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
0804         return {tuple_type{lhs_type{static_cast<T &&>(lhs)},                   \
0805                            rhs_type{static_cast<U &&>(rhs)}}};                 \
0806     }
0807 
0808 
0809 /** Defines user defined literal template that creates literal placeholders
0810     instantiated from the \a expr_template expression template.  It is
0811     recommended that you put this in its own namespace.
0812 
0813     \param expr_template The expression template to use to instantiate the
0814     result expression.  \a expr_template must be an \ref
0815     ExpressionTemplate.
0816 */
0817 #define BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR(expr_template)             \
0818     template<char... c>                                                        \
0819     constexpr auto operator"" _p()                                             \
0820     {                                                                          \
0821         using i = ::boost::hana::llong<                                        \
0822             ::boost::hana::ic_detail::parse<sizeof...(c)>({c...})>;            \
0823         static_assert(1 <= i::value, "Placeholders must be >= 1.");            \
0824         return expr_template<                                                  \
0825             ::boost::yap::expr_kind::terminal,                                 \
0826             ::boost::hana::tuple<::boost::yap::placeholder<i::value>>>{};      \
0827     }
0828 
0829 #endif