From d1c3734945d9a0baac372491de326eccd704bba9 Mon Sep 17 00:00:00 2001 From: Zach Laine Date: Sat, 12 Nov 2016 12:05:01 -0600 Subject: [PATCH] Remove use of eval_expression_as on subexpressions; add transform_expression. --- detail/default_eval.hpp | 27 +++++++++++++++++++-------- expression.hpp | 4 ---- test/user_expression_transform.cpp | 28 ++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/detail/default_eval.hpp b/detail/default_eval.hpp index 497f14b..ae5e229 100644 --- a/detail/default_eval.hpp +++ b/detail/default_eval.hpp @@ -13,13 +13,24 @@ namespace boost::proto17 { namespace detail { + struct nonexistent_transform {}; + inline nonexistent_transform transform_expression (...) { return {}; } + template - decltype(auto) default_eval_expr (expression const & expr, Tuple && args) + decltype(auto) default_eval_expr (expression const & expr, Tuple && args) // TODO: Take args directly, instead of in a tuple. { using void_type = hana::basic_type; using namespace hana::literals; - if constexpr (Kind == expr_kind::terminal) { + + if constexpr ( + !std::is_same_v< + decltype(transform_expression(expr, static_cast(args))), + nonexistent_transform + > + ) { + return transform_expression(expr, static_cast(args)); + } else if constexpr (Kind == expr_kind::terminal) { static_assert(sizeof...(T) == 1); return expr.elements[0_c]; } else if constexpr (Kind == expr_kind::placeholder) { @@ -31,7 +42,7 @@ namespace boost::proto17 { else if constexpr (Kind == expr_kind:: op_name) { \ return \ eval_ ## op_name( \ - eval_expression_as(expr.elements[0_c], void_type{}, static_cast(args)) \ + default_eval_expr(expr.elements[0_c], static_cast(args)) \ ); \ } @@ -52,8 +63,8 @@ namespace boost::proto17 { else if constexpr (Kind == expr_kind:: op_name) { \ return \ eval_ ## op_name( \ - eval_expression_as(expr.elements[0_c], void_type{}, static_cast(args)), \ - eval_expression_as(expr.elements[1_c], void_type{}, static_cast(args)) \ + default_eval_expr(expr.elements[0_c], static_cast(args)), \ + default_eval_expr(expr.elements[1_c], static_cast(args)) \ ); \ } @@ -79,8 +90,8 @@ namespace boost::proto17 { else if constexpr (Kind == expr_kind::comma) { return eval_comma( - eval_expression_as(expr.elements[0_c], void_type{}, static_cast(args)), - eval_expression_as(expr.elements[1_c], void_type{}, static_cast(args)) + default_eval_expr(expr.elements[0_c], static_cast(args)), + default_eval_expr(expr.elements[1_c], static_cast(args)) ); } @@ -103,7 +114,7 @@ namespace boost::proto17 { else if constexpr (Kind == expr_kind::call) { return hana::unpack( hana::transform(expr.elements, [&args] (auto && element) { - return eval_expression_as(element, void_type{}, static_cast(args)); + return default_eval_expr(element, static_cast(args)); }), eval_call ); diff --git a/expression.hpp b/expression.hpp index edc6b85..8d3fb4a 100644 --- a/expression.hpp +++ b/expression.hpp @@ -17,10 +17,6 @@ namespace boost::proto17 { constexpr decltype(auto) eval_expression_as (E const & expr, hana::basic_type, Tuple && args) { return static_cast(detail::default_eval_expr(expr, static_cast(args))); } - template - constexpr decltype(auto) eval_expression_as (E const & expr, hana::basic_type, Tuple && args) - { return detail::default_eval_expr(expr, static_cast(args)); } - struct eval_expression_as_fn { template diff --git a/test/user_expression_transform.cpp b/test/user_expression_transform.cpp index 56e747e..8a63636 100644 --- a/test/user_expression_transform.cpp +++ b/test/user_expression_transform.cpp @@ -26,7 +26,7 @@ namespace user_2 { }; number naxpy (number a, number x, number y) - { return number{a.value * x.value + y.value + 100.0}; } + { return number{a.value * x.value + y.value + 10.0}; } #if 0 // TODO: Document this verbose form. auto eval_expression_as ( @@ -50,7 +50,7 @@ namespace user_2 { } #endif - auto eval_expression_as ( + decltype(auto) eval_expression_as ( decltype(term{{0.0}} * number{} + number{}) const & expr, boost::hana::basic_type, boost::hana::tuple<>) @@ -62,6 +62,17 @@ namespace user_2 { ); } + 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) @@ -103,7 +114,7 @@ TEST(user_expression_transform, test_user_expression_transform) > expr = a * x + y; user_2::number result = expr; - EXPECT_EQ(result.value, 145); + EXPECT_EQ(result.value, 55); } { @@ -122,7 +133,16 @@ TEST(user_expression_transform, test_user_expression_transform) > expr = k * (a * x + y); user_2::number result = expr; - EXPECT_EQ(result.value, 290); + 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