diff --git a/expression.hpp b/expression.hpp index 578abf0..b4844e9 100644 --- a/expression.hpp +++ b/expression.hpp @@ -6,24 +6,43 @@ #include "detail/default_eval.hpp" #include -//#include -//#include namespace boost::proto17 { - // TODO: Customization point. - // TODO: static assert/SFINAE std::is_callable<> - // TODO: static assert/SFINAE no placeholders - template - R evaluate_expression_as (expression const & expr) - { return static_cast(detail::default_eval_expr(expr, hana::tuple<>())); } + namespace adl_detail { - // TODO: static assert/SFINAE std::is_callable<> + template + constexpr auto evaluate_expression_as (E const & expr, hana::basic_type, T && ...t) + { return static_cast(detail::default_eval_expr(expr, hana::make_tuple(static_cast(t)...))); } + + struct evaluate_expression_as_fn + { + template + constexpr auto operator() (E const & expr, hana::basic_type rtype, T && ...t) const + { return evaluate_expression_as(expr, rtype, static_cast(t)...); } + }; + + } + + using adl_detail::evaluate_expression_as_fn; + + inline namespace function_objects { + + inline constexpr evaluate_expression_as_fn evaluate_expression_as{}; + + } + + // TODO: static assert/SFINAE sizeof...(T) >= highest-indexed placeholder + 1 template auto evaluate (Expr const & expr, T && ...t) { return detail::default_eval_expr(expr, hana::make_tuple(static_cast(t)...)); } + // TODO: static assert/SFINAE sizeof...(T) >= highest-indexed placeholder + 1 + template + auto evaluate_as (Expr const & expr, T && ...t) + { return evaluate_expression_as(expr, hana::basic_type{}, static_cast(t)...); } + template struct expression { @@ -54,7 +73,7 @@ namespace boost::proto17 { template operator R () - { return evaluate_expression_as(*this); } + { return evaluate_expression_as(*this, hana::basic_type{}); } template auto operator+ (U && rhs) const & diff --git a/sketch.cpp b/sketch.cpp index 13f077f..f8b2dfc 100644 --- a/sketch.cpp +++ b/sketch.cpp @@ -964,6 +964,8 @@ void print () void default_eval () { + std::cout << "\ndefault_eva()\n"; + term unity{1.0}; int i_ = 42; term i{std::move(i_)}; @@ -998,19 +1000,21 @@ void default_eval () } { - double result = evaluate(unity, boost::hana::make_tuple(5, 6, 7)); + double result = evaluate(unity, 5, 6, 7); std::cout << "evaluate(unity)=" << result << "\n"; // 1 } { - double result = evaluate(expr, boost::hana::make_tuple()); + double result = evaluate(expr); std::cout << "evaluate(expr)=" << result << "\n"; // -41 } { - double result = evaluate(unevaluated_expr, boost::hana::make_tuple(std::string("15"))); + double result = evaluate(unevaluated_expr, std::string("15")); std::cout << "evaluate(unevaluated_expr)=" << result << "\n"; // -40 } + + std::cout << "\n"; } namespace test { @@ -1023,13 +1027,31 @@ namespace test { }; // User-defined binary-plus! With weird semantics! - inline auto eval_plus (number a, number b) + template + inline auto eval_plus (A a, B b) { return number{a.value - b.value}; } + template + constexpr auto evaluate_expression_as ( + E const & expr, + boost::hana::basic_type, + T && ...t) + { + std::cout << "User eval! "; + return static_cast( + bp17::detail::default_eval_expr( + expr, + boost::hana::make_tuple(static_cast(t)...) + ) + ); + } + } void user_operator_eval () { + std::cout << "\nuser_operator_eval()\n"; + term unity{{1.0}}; double d_ = 42.0; term i{{d_}}; @@ -1064,23 +1086,97 @@ void user_operator_eval () } { - double result = (double)evaluate(unity, boost::hana::make_tuple(5, 6, 7)); + double result = (double)evaluate(unity, 5, 6, 7); std::cout << "evaluate(unity)=" << result << "\n"; // 1 } { - double result = (double)evaluate(expr, boost::hana::make_tuple()); + double result = (double)evaluate(expr); std::cout << "evaluate(expr)=" << result << "\n"; // -41 } { - double result = (double)evaluate(unevaluated_expr, boost::hana::make_tuple(std::string("15"))); + double result = (double)evaluate(unevaluated_expr, std::string("15")); std::cout << "evaluate(unevaluated_expr)=" << result << "\n"; // 42 } + + std::cout << "\n"; +} + +void user_evaluate_expression_as () +{ + term unity{{1.0}}; + double d_ = 42.0; + term i{{d_}}; + bp17::expression< + bp17::expr_kind::plus, + term, + term + > expr = unity + std::move(i); + bp17::expression< + bp17::expr_kind::plus, + term, + bp17::expression< + bp17::expr_kind::plus, + term, + term + > + > unevaluated_expr = unity + std::move(expr); + + std::cout << "\nuser_evaluate_expression_as()\n"; + + { + test::number result = unity; + std::cout << "unity=" << result.value << "\n"; // 1 + } + + { + test::number result = expr; + std::cout << "expr=" << result.value << "\n"; // -41 + } + + { + test::number result = unevaluated_expr; + std::cout << "unevaluated_expr=" << result.value << "\n"; // 42 + } + + { + test::number result = evaluate(unity, 5, 6, 7); + std::cout << "evaluate(unity)=" << result.value << "\n"; // 1 + } + + { + double result = (double)evaluate(expr); + std::cout << "evaluate(expr)=" << result << "\n"; // -41 + } + + { + double result = (double)evaluate(unevaluated_expr, std::string("15")); + std::cout << "evaluate(unevaluated_expr)=" << result << "\n"; // 42 + } + + { + test::number result = bp17::evaluate_as(unity, 5, 6, 7); + std::cout << "evaluate(unity)=" << result.value << "\n"; // 1 + } + + { + test::number result = bp17::evaluate_as(expr); + std::cout << "evaluate(expr)=" << result.value << "\n"; // -41 + } + + { + test::number result = bp17::evaluate_as(unevaluated_expr, std::string("15")); + std::cout << "evaluate(unevaluated_expr)=" << result.value << "\n"; // 42 + } + + std::cout << "\n"; } void placeholder_eval () { + std::cout << "\nplaceholder_eval()\n"; + using namespace boost::proto17::literals; bp17::placeholder<2> p2 = 2_p; @@ -1115,6 +1211,8 @@ void placeholder_eval () double result = evaluate(unevaluated_expr, std::string("15"), 2, 3); std::cout << "evaluate(unevaluated_expr)=" << result << "\n"; // 48 } + + std::cout << "\n"; } int main () @@ -1130,6 +1228,7 @@ int main () print(); default_eval(); + user_evaluate_expression_as(); user_operator_eval(); placeholder_eval();