#define BOOST_PROTO17_CONVERSION_OPERATOR_TEMPLATE #include "expression.hpp" #include #include template using term = boost::proto17::terminal; namespace bp17 = boost::proto17; namespace user_2 { struct number { double value; friend number operator+ (number lhs, number rhs) { return number{lhs.value + rhs.value}; } friend number operator* (number lhs, number rhs) { return number{lhs.value * rhs.value}; } }; number naxpy (number a, number x, number y) { return number{a.value * x.value + y.value + 10.0}; } #if 0 // TODO: Document this verbose form. auto eval_expression_as ( bp17::expression< bp17::expr_kind::plus, bp17::expression< bp17::expr_kind::multiplies, term, term >, term > const & expr, boost::hana::basic_type) { using namespace boost::hana::literals; return naxpy( expr.elements[0_c].elements[0_c].elements[0_c], expr.elements[0_c].elements[1_c].elements[0_c], expr.elements[1_c].elements[0_c] ); } #endif decltype(auto) eval_expression_as ( decltype(term{{0.0}} * number{} + number{}) const & expr, boost::hana::basic_type, boost::hana::tuple<>) { return naxpy( expr.left().left().value(), expr.left().right().value(), expr.right().value() ); } decltype(auto) transform_expression ( decltype(term{{0.0}} * number{} + number{}) const & expr, boost::hana::tuple<> ) { return naxpy( evaluate(expr.left().left()), evaluate(expr.left().right()), evaluate(expr.right()) ); } } TEST(user_expression_transform, test_user_expression_transform) { term k{{2.0}}; term a{{1.0}}; term x{{42.0}}; term y{{3.0}}; { bp17::expression< bp17::expr_kind::plus, bp17::expression< bp17::expr_kind::multiplies, bp17::expression< bp17::expr_kind::multiplies, term, term >, term >, term > expr = k * a * x + y; user_2::number result = expr; EXPECT_EQ(result.value, 87); } { bp17::expression< bp17::expr_kind::plus, bp17::expression< bp17::expr_kind::multiplies, term, term >, term > expr = a * x + y; user_2::number result = expr; EXPECT_EQ(result.value, 55); } { bp17::expression< bp17::expr_kind::multiplies, term, bp17::expression< bp17::expr_kind::plus, bp17::expression< bp17::expr_kind::multiplies, term, term >, term > > expr = k * (a * x + y); user_2::number result = expr; EXPECT_EQ(result.value, 110); } { auto expr = (a * x + y) * (a * x + y) + (a * x + y); user_2::number result = expr; // Note: +10 not done at the top level naxpy opportunity. EXPECT_EQ(result.value, 55 * 55 + 55); } // TODO: This was an error (user:: vs. user_2::). Document for users that // they should catch an expression in an auto var to diagnose these sorts // of things. #if 0 bp17::expression< bp17::expr_kind::multiplies, term, term > expr = a * x; #endif }