2
0
mirror of https://github.com/boostorg/yap.git synced 2026-02-23 16:22:09 +00:00

Initial version of evaluate_expression_as() as a customization point (hopefully to be improved).

This commit is contained in:
Zach Laine
2016-11-04 18:25:43 -05:00
parent 63922a7cfd
commit 2e9eeb9c1e
2 changed files with 135 additions and 17 deletions

View File

@@ -6,24 +6,43 @@
#include "detail/default_eval.hpp"
#include <boost/hana/tuple.hpp>
//#include <boost/hana/type.hpp>
//#include <boost/hana/size.hpp>
namespace boost::proto17 {
// TODO: Customization point.
// TODO: static assert/SFINAE std::is_callable<>
// TODO: static assert/SFINAE no placeholders
template <typename R, expr_kind Kind, typename ...T>
R evaluate_expression_as (expression<Kind, T...> const & expr)
{ return static_cast<R>(detail::default_eval_expr(expr, hana::tuple<>())); }
namespace adl_detail {
// TODO: static assert/SFINAE std::is_callable<>
template <typename R, typename E, typename ...T>
constexpr auto evaluate_expression_as (E const & expr, hana::basic_type<R>, T && ...t)
{ return static_cast<R>(detail::default_eval_expr(expr, hana::make_tuple(static_cast<T &&>(t)...))); }
struct evaluate_expression_as_fn
{
template <typename R, typename E, typename ...T>
constexpr auto operator() (E const & expr, hana::basic_type<R> rtype, T && ...t) const
{ return evaluate_expression_as(expr, rtype, static_cast<T &&>(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 <typename Expr, typename ...T>
auto evaluate (Expr const & expr, T && ...t)
{ return detail::default_eval_expr(expr, hana::make_tuple(static_cast<T &&>(t)...)); }
// TODO: static assert/SFINAE sizeof...(T) >= highest-indexed placeholder + 1
template <typename R, typename Expr, typename ...T>
auto evaluate_as (Expr const & expr, T && ...t)
{ return evaluate_expression_as(expr, hana::basic_type<R>{}, static_cast<T &&>(t)...); }
template <expr_kind Kind, typename ...T>
struct expression
{
@@ -54,7 +73,7 @@ namespace boost::proto17 {
template <typename R>
operator R ()
{ return evaluate_expression_as<R>(*this); }
{ return evaluate_expression_as(*this, hana::basic_type<R>{}); }
template <typename U>
auto operator+ (U && rhs) const &

View File

@@ -964,6 +964,8 @@ void print ()
void default_eval ()
{
std::cout << "\ndefault_eva()\n";
term<double> unity{1.0};
int i_ = 42;
term<int &&> 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 <typename A, typename B>
inline auto eval_plus (A a, B b)
{ return number{a.value - b.value}; }
template <typename E, typename ...T>
constexpr auto evaluate_expression_as (
E const & expr,
boost::hana::basic_type<test::number>,
T && ...t)
{
std::cout << "User eval! ";
return static_cast<test::number>(
bp17::detail::default_eval_expr(
expr,
boost::hana::make_tuple(static_cast<T &&>(t)...)
)
);
}
}
void user_operator_eval ()
{
std::cout << "\nuser_operator_eval()\n";
term<test::number> unity{{1.0}};
double d_ = 42.0;
term<test::number> 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<test::number> unity{{1.0}};
double d_ = 42.0;
term<test::number> i{{d_}};
bp17::expression<
bp17::expr_kind::plus,
term<test::number>,
term<test::number>
> expr = unity + std::move(i);
bp17::expression<
bp17::expr_kind::plus,
term<test::number>,
bp17::expression<
bp17::expr_kind::plus,
term<test::number>,
term<test::number>
>
> 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<test::number>(unity, 5, 6, 7);
std::cout << "evaluate(unity)=" << result.value << "\n"; // 1
}
{
test::number result = bp17::evaluate_as<test::number>(expr);
std::cout << "evaluate(expr)=" << result.value << "\n"; // -41
}
{
test::number result = bp17::evaluate_as<test::number>(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();