#ifndef BOOST_PROTO17_EXPRESSION_HPP_INCLUDED #define BOOST_PROTO17_EXPRESSION_HPP_INCLUDED #include "expression_fwd.hpp" #include "detail/expression.hpp" #include "detail/default_eval.hpp" #include namespace boost::proto17 { namespace adl_detail { 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 { using this_type = expression; using tuple_type = hana::tuple; static const expr_kind kind = Kind; expression (T && ... t) : elements (static_cast(t)...) {} expression (hana::tuple const & rhs) : elements (rhs) {} expression (hana::tuple && rhs) : elements (std::move(rhs)) {} expression & operator= (hana::tuple const & rhs) { elements = rhs.elements; } expression & operator= (hana::tuple && rhs) { elements = std::move(rhs.elements); } tuple_type elements; template operator R () { return evaluate_expression_as(*this, hana::basic_type{}); } template auto operator+ (U && rhs) const & { using rhs_type = typename detail::rhs_type::type; return expression{ hana::tuple{*this, rhs_type{static_cast(rhs)}} }; } template auto operator+ (U && rhs) && { using rhs_type = typename detail::rhs_type::type; return expression{ hana::tuple{std::move(*this), rhs_type{static_cast(rhs)}} }; } template auto operator- (U && rhs) const & { using rhs_type = typename detail::rhs_type::type; return expression{ hana::tuple{*this, rhs_type{static_cast(rhs)}} }; } template auto operator- (U && rhs) && { using rhs_type = typename detail::rhs_type::type; return expression{ hana::tuple{std::move(*this), rhs_type{static_cast(rhs)}} }; } }; } #endif