#define BOOST_PROTO17_CONVERSION_OPERATOR_TEMPLATE #include "expression.hpp" #include #include template using term = boost::proto17::terminal; namespace bp17 = boost::proto17; namespace user { struct number { explicit operator double () const { return value; } double value; }; inline auto max (int a, int b) { return a < b ? b : a; }; struct tag_type {}; inline number tag_function (double a, double b) { return number{a + b}; } // User-defined operator() implementation. template inline auto eval_call (F && f, T && ...t) { if constexpr (sizeof...(T) == 2u && std::is_same_v, tag_type>) { return tag_function((double)t...); } else { assert(!"Unhandled case in eval_call()"); return; } } } TEST(call_expr, test_call_expr) { using namespace boost::proto17::literals; { bp17::expression< bp17::expr_kind::call, bp17::placeholder<0>, bp17::placeholder<1>, bp17::placeholder<2> > expr = 0_p(1_p, 2_p); { auto min = [] (int a, int b) { return a < b ? a : b; }; int result = evaluate(expr, min, 3, 7); EXPECT_EQ(result, 3); } { int result = evaluate(expr, &user::max, 3, 7); EXPECT_EQ(result, 7); } { int result = evaluate(expr, user::max, 3, 7); EXPECT_EQ(result, 7); } } { auto min_lambda = [] (int a, int b) { return a < b ? a : b; }; { auto min = bp17::make_terminal(min_lambda); auto expr = min(0_p, 1_p); { int result = evaluate(expr, 3, 7); EXPECT_EQ(result, 3); } } { term min = {{min_lambda}}; auto expr = min(0_p, 1_p); { int result = evaluate(expr, 3, 7); EXPECT_EQ(result, 3); } } } { struct min_function_object_t { auto operator() (int a, int b) const { return a < b ? a : b; } } min_function_object; { term min = bp17::make_terminal(min_function_object); auto expr = min(0_p, 1_p); { using namespace boost::hana::literals; int result = evaluate(expr, 3, 7); EXPECT_EQ(result, 3); } } { term min = {{min_function_object}}; auto expr = min(0_p, 1_p); { int result = evaluate(expr, 3, 7); EXPECT_EQ(result, 3); } } { auto min = bp17::make_terminal(min_function_object_t{}); auto expr = min(0_p, 1_p); { int result = evaluate(expr, 3, 7); EXPECT_EQ(result, 3); } } { term min = {{min_function_object_t{}}}; auto expr = min(0_p, 1_p); { int result = evaluate(expr, 3, 7); EXPECT_EQ(result, 3); } } } { auto min_lambda = [] (int a, int b) { return a < b ? a : b; }; { auto min = bp17::make_terminal(min_lambda); auto expr = min(0, 1); { int result = evaluate(expr); EXPECT_EQ(result, 0); } } { term min = {{min_lambda}}; bp17::expression< bp17::expr_kind::call, term, term, term > expr = min(0, 1); { int result = evaluate(expr); EXPECT_EQ(result, 0); } } } { { auto plus = bp17::make_terminal(user::tag_type{}); auto expr = plus(user::number{13}, 1); { user::number result = expr; EXPECT_EQ(result.value, 14); } } { term plus = {{user::tag_type{}}}; bp17::expression< bp17::expr_kind::call, term, term, term > expr = plus(0, 1); { user::number result = expr; EXPECT_EQ(result.value, 1); } } } }