From 15e70fefe10be6144422681ded4754978bfdef8a Mon Sep 17 00:00:00 2001 From: Zach Laine Date: Tue, 15 Nov 2016 19:12:07 -0600 Subject: [PATCH] Pass individual args through evaluate*(), instead of making a tuple of them. --- detail/default_eval.hpp | 76 +++++++++++++------ expression.hpp | 18 ++--- expression_fwd.hpp | 4 +- test/user_eval_expression_as.cpp | 6 +- test/user_expression_transform.cpp | 6 +- test/user_expression_transform_2.cpp | 3 +- test/user_operator_and_eval_expression_as.cpp | 22 +++--- 7 files changed, 80 insertions(+), 55 deletions(-) diff --git a/detail/default_eval.hpp b/detail/default_eval.hpp index 3cd2a2e..c3744b3 100644 --- a/detail/default_eval.hpp +++ b/detail/default_eval.hpp @@ -16,33 +16,57 @@ namespace boost::proto17 { struct nonexistent_transform {}; inline nonexistent_transform transform_expression (...) { return {}; } - template - decltype(auto) default_eval_expr (expression const & expr, Tuple && args) // TODO: Take args directly, instead of in a tuple. + template + struct kind_of; + + template + struct kind_of> + { static expr_kind const value = Kind; }; + + template + auto eval_placeholder (I, T && arg) { - using void_type = hana::basic_type; + static_assert(I::value == 0); + return static_cast(arg); + } + + template + auto eval_placeholder (I, T && arg, Ts &&... args) + { + if constexpr (I::value == 0) { + return arg; + } else { + return eval_placeholder(hana::llong{}, static_cast(args)...); + } + } + + template + decltype(auto) default_eval_expr (Expr const & expr, T &&... args) + { + constexpr expr_kind kind = kind_of::value; using namespace hana::literals; if constexpr ( !std::is_same_v< - decltype(transform_expression(expr, static_cast(args))), + 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 transform_expression(expr, static_cast(args)...); + } else if constexpr (kind == expr_kind::terminal) { + static_assert(decltype(hana::size(expr.elements))::value == 1UL); return expr.elements[0_c]; - } else if constexpr (Kind == expr_kind::placeholder) { - static_assert(sizeof...(T) == 1); - return args[expr.elements[0_c]]; + } else if constexpr (kind == expr_kind::placeholder) { + static_assert(decltype(hana::size(expr.elements))::value == 1UL); + return eval_placeholder(expr.elements[0_c], static_cast(args)...); } #define BOOST_PROTO17_UNARY_OPERATOR_CASE(op_name) \ - else if constexpr (Kind == expr_kind:: op_name) { \ + else if constexpr (kind == expr_kind:: op_name) { \ return \ eval_ ## op_name( \ - default_eval_expr(expr.elements[0_c], static_cast(args)) \ + default_eval_expr(expr.elements[0_c], static_cast(args)...) \ ); \ } @@ -60,11 +84,11 @@ namespace boost::proto17 { #undef BOOST_PROTO17_UNARY_OPERATOR_CASE #define BOOST_PROTO17_BINARY_OPERATOR_CASE(op_name) \ - else if constexpr (Kind == expr_kind:: op_name) { \ + else if constexpr (kind == expr_kind:: op_name) { \ return \ eval_ ## op_name( \ - default_eval_expr(expr.elements[0_c], static_cast(args)), \ - default_eval_expr(expr.elements[1_c], static_cast(args)) \ + default_eval_expr(expr.elements[0_c], static_cast(args)...), \ + default_eval_expr(expr.elements[1_c], static_cast(args)...) \ ); \ } @@ -87,11 +111,11 @@ namespace boost::proto17 { BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_or) // | BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_xor) // ^ - else if constexpr (Kind == expr_kind::comma) { + else if constexpr (kind == expr_kind::comma) { return eval_comma( - default_eval_expr(expr.elements[0_c], static_cast(args)), - default_eval_expr(expr.elements[1_c], static_cast(args)) + default_eval_expr(expr.elements[0_c], static_cast(args)...), + default_eval_expr(expr.elements[1_c], static_cast(args)...) ); } @@ -111,15 +135,19 @@ namespace boost::proto17 { #undef BOOST_PROTO17_BINARY_OPERATOR_CASE - else if constexpr (Kind == expr_kind::call) { + else if constexpr (kind == expr_kind::call) { + auto expand_args = [&](auto && element) { + return default_eval_expr( + static_cast(element), + static_cast(args)... + ); + }; + return hana::unpack( expr.elements, - [&args] (auto && ... element) { + [&] (auto && ... elements) { return eval_call( - default_eval_expr( - static_cast(element), - static_cast(args) - )... + expand_args(static_cast(elements))... ); }); } else { diff --git a/expression.hpp b/expression.hpp index 8d3fb4a..1e2eecf 100644 --- a/expression.hpp +++ b/expression.hpp @@ -13,15 +13,15 @@ namespace boost::proto17 { namespace adl_detail { - template - 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, T &&... args) + { return static_cast(detail::default_eval_expr(expr, static_cast(args)...)); } struct eval_expression_as_fn { - template - constexpr decltype(auto) operator() (E const & expr, hana::basic_type rtype, Tuple && args) const - { return eval_expression_as(expr, rtype, static_cast(args)); } + template + constexpr decltype(auto) operator() (E const & expr, hana::basic_type rtype, T &&... args) const + { return eval_expression_as(expr, rtype, static_cast(args)...); } }; } @@ -37,12 +37,12 @@ namespace boost::proto17 { // TODO: static assert/SFINAE sizeof...(T) >= highest-indexed placeholder + 1 template decltype(auto) evaluate (Expr const & expr, T && ...t) - { return detail::default_eval_expr(expr, hana::make_tuple(static_cast(t)...)); } + { return detail::default_eval_expr(expr, static_cast(t)...); } // TODO: static assert/SFINAE sizeof...(T) >= highest-indexed placeholder + 1 template decltype(auto) evaluate_as (Expr const & expr, T && ...t) - { return eval_expression_as(expr, hana::basic_type{}, hana::make_tuple(static_cast(t)...)); } + { return eval_expression_as(expr, hana::basic_type{}, static_cast(t)...); } template struct expression @@ -75,7 +75,7 @@ namespace boost::proto17 { #ifdef BOOST_PROTO17_CONVERSION_OPERATOR_TEMPLATE template operator R () - { return eval_expression_as(*this, hana::basic_type{}, hana::tuple<>{}); } + { return eval_expression_as(*this, hana::basic_type{}); } #endif decltype(auto) value () const diff --git a/expression_fwd.hpp b/expression_fwd.hpp index 0b89cc3..8324f0f 100644 --- a/expression_fwd.hpp +++ b/expression_fwd.hpp @@ -82,8 +82,8 @@ namespace boost::proto17 { namespace detail { - template - decltype(auto) default_eval_expr (expression const & expr, Tuple && args); + template + decltype(auto) default_eval_expr (Expr const & expr, T &&... args); } diff --git a/test/user_eval_expression_as.cpp b/test/user_eval_expression_as.cpp index acec2fe..2c1cd6f 100644 --- a/test/user_eval_expression_as.cpp +++ b/test/user_eval_expression_as.cpp @@ -22,14 +22,14 @@ namespace user { double value; }; - template + template constexpr auto eval_expression_as ( E const & expr, boost::hana::basic_type, - Tuple && args) + T &&... args) { return static_cast( - bp17::detail::default_eval_expr(expr, static_cast(args)) + bp17::detail::default_eval_expr(expr, static_cast(args)...) ); } diff --git a/test/user_expression_transform.cpp b/test/user_expression_transform.cpp index e559397..f33ac09 100644 --- a/test/user_expression_transform.cpp +++ b/test/user_expression_transform.cpp @@ -52,8 +52,7 @@ namespace user { decltype(auto) eval_expression_as ( decltype(term{{0.0}} * number{} + number{}) const & expr, - boost::hana::basic_type, - boost::hana::tuple<>) + boost::hana::basic_type) { return naxpy( expr.left().left().value(), @@ -63,8 +62,7 @@ namespace user { } decltype(auto) transform_expression ( - decltype(term{{0.0}} * number{} + number{}) const & expr, - boost::hana::tuple<> + decltype(term{{0.0}} * number{} + number{}) const & expr ) { return naxpy( evaluate(expr.left().left()), diff --git a/test/user_expression_transform_2.cpp b/test/user_expression_transform_2.cpp index 4917478..f0d8102 100644 --- a/test/user_expression_transform_2.cpp +++ b/test/user_expression_transform_2.cpp @@ -38,8 +38,7 @@ namespace user { Expr2 >, Expr3 - > const & expr, - boost::hana::tuple<> + > const & expr ) { return naxpy( evaluate(expr.left().left()), diff --git a/test/user_operator_and_eval_expression_as.cpp b/test/user_operator_and_eval_expression_as.cpp index 81e0fb4..298e605 100644 --- a/test/user_operator_and_eval_expression_as.cpp +++ b/test/user_operator_and_eval_expression_as.cpp @@ -24,15 +24,15 @@ namespace user { inline auto eval_plus (A a, B b) { return number{a.value - b.value}; } - template + template constexpr auto eval_expression_as ( E const & expr, boost::hana::basic_type, - Tuple && args) + T &&... args) { - return static_cast( - bp17::detail::default_eval_expr(expr, static_cast(args)) - ); + user::number const x = + bp17::detail::default_eval_expr(expr, static_cast(args)...); + return user::number{x.value + 5.0}; } } @@ -59,17 +59,17 @@ TEST(user_eval_expression_as, test_user_eval_expression_as) { user::number result = unity; - EXPECT_EQ(result.value, 1); + EXPECT_EQ(result.value, 6); } { user::number result = expr; - EXPECT_EQ(result.value, -41); + EXPECT_EQ(result.value, -36); } { user::number result = unevaluated_expr; - EXPECT_EQ(result.value, 42); + EXPECT_EQ(result.value, 47); } { @@ -89,16 +89,16 @@ TEST(user_eval_expression_as, test_user_eval_expression_as) { user::number result = bp17::evaluate_as(unity, 5, 6, 7); - EXPECT_EQ(result.value, 1); + EXPECT_EQ(result.value, 6); } { user::number result = bp17::evaluate_as(expr); - EXPECT_EQ(result.value, -41); + EXPECT_EQ(result.value, -36); } { user::number result = bp17::evaluate_as(unevaluated_expr, std::string("15")); - EXPECT_EQ(result.value, 42); + EXPECT_EQ(result.value, 47); } }