diff --git a/detail/expression.hpp b/detail/expression.hpp index 1d1e85d..4718057 100644 --- a/detail/expression.hpp +++ b/detail/expression.hpp @@ -181,6 +181,11 @@ namespace boost::proto17 { // free_binary_op_result + // TODO: Must is_expr<> below be an ExprTemplate instantiation? + // Without that, we potentially have one kind of expression template + // making another one when a non-expr value appears of the lhs of one + // of its binary ops. + template < template class ExprTemplate, expr_kind OpKind, @@ -242,6 +247,56 @@ namespace boost::proto17 { >::type; + // udt_binary_op_result + + template class UdtTrait> + struct is_udt_arg + { static bool const value = !is_expr::value && UdtTrait>::value; }; + + template < + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template class UUdtTrait, + bool Valid = is_udt_arg::value && is_udt_arg::value + > + struct udt_binary_op_result; + + template < + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template class UUdtTrait + > + struct udt_binary_op_result + { + using lhs_type = operand_type_t; + using rhs_type = operand_type_t; + using type = ExprTemplate>; + }; + + template < + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template class UUdtTrait + > + using udt_binary_op_result_t = typename udt_binary_op_result< + ExprTemplate, + OpKind, + T, + U, + TUdtTrait, + UUdtTrait + >::type; + + // expr_arity enum class expr_arity { diff --git a/user_macros.hpp b/user_macros.hpp index 8376045..a93b06f 100644 --- a/user_macros.hpp +++ b/user_macros.hpp @@ -213,4 +213,36 @@ } \ } \ + +#define BOOST_PROTO17_USER_UDT_BINARY_OPERATOR(op_name, expr_template, t_udt_trait, u_udt_trait) \ + template \ + auto operator BOOST_PROTO17_INDIRECT_CALL(op_name)() (T && lhs, U && rhs) \ + -> ::boost::proto17::detail::udt_binary_op_result_t< \ + expr_template, \ + ::boost::proto17::expr_kind::op_name, \ + T, \ + U, \ + t_udt_trait, \ + u_udt_trait \ + > \ + { \ + using result_types = ::boost::proto17::detail::udt_binary_op_result< \ + expr_template, \ + ::boost::proto17::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)}, \ + } \ + }; \ + } \ + #endif