1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
/*==============================================================================
Copyright (c) 2005-2010 Joel de Guzman
Copyright (c) 2010 Thomas Heller
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#include <boost/phoenix/phoenix.hpp>
#include <boost/proto/proto.hpp>
#include <boost/proto/debug.hpp>
namespace phoenix = boost::phoenix;
namespace proto = boost::proto;
using phoenix::evaluator;
#ifdef _MSC_VER
// redifining evaluator, this is because MSVC chokes on function types like:
// F(G(...))
#define evaluator(A0, A1) proto::call<phoenix::evaluator(A0, A1)>
#endif
struct invert_actions
{
template <typename Rule>
struct when
: proto::nary_expr<
proto::_
, proto::vararg<
proto::when<proto::_, evaluator(proto::_, phoenix::_context)>
>
>
{};
};
template <>
struct invert_actions::when<phoenix::rule::plus>
: proto::call<
phoenix::functional::make_minus(
evaluator(proto::_left, phoenix::_context)
, evaluator(proto::_right, phoenix::_context)
)
>
{};
template <>
struct invert_actions::when<phoenix::rule::minus>
: proto::call<
phoenix::functional::make_plus(
evaluator(proto::_left, phoenix::_context)
, evaluator(proto::_right, phoenix::_context)
)
>
{};
template <>
struct invert_actions::when<phoenix::rule::multiplies>
: proto::call<
phoenix::functional::make_divides(
evaluator(proto::_left, phoenix::_context)
, evaluator(proto::_right, phoenix::_context)
)
>
{};
template <>
struct invert_actions::when<phoenix::rule::divides>
: proto::call<
phoenix::functional::make_multiplies(
evaluator(proto::_left, phoenix::_context)
, evaluator(proto::_right, phoenix::_context)
)
>
{};
#ifdef _MSC_VER
#undef evaluator
#endif
template <typename Expr>
void print_expr(Expr const & expr)
{
std::cout << "before inversion:\n";
proto::display_expr(expr);
std::cout << "after inversion:\n";
proto::display_expr(
phoenix::eval(
expr
, phoenix::context(
phoenix::nothing
, invert_actions()
)
)
);
std::cout << "\n";
}
template <typename Expr>
typename
boost::phoenix::result_of::eval<
Expr const&
, phoenix::result_of::make_context<
phoenix::result_of::make_env<>::type
, invert_actions
>::type
>::type
invert(Expr const & expr)
{
return
phoenix::eval(
expr
, phoenix::make_context(
phoenix::make_env()
, invert_actions()
)
);
}
int main()
{
using phoenix::placeholders::_1;
using phoenix::placeholders::_2;
using phoenix::placeholders::_3;
using phoenix::placeholders::_4;
print_expr(_1);
print_expr(_1 + _2);
print_expr(_1 + _2 - _3);
print_expr(_1 * _2);
print_expr(_1 * _2 / _3);
print_expr(_1 * _2 + _3);
print_expr(_1 * _2 - _3);
print_expr(if_(_1 * _4)[_2 - _3]);
print_expr(_1 * invert(_2 - _3));
}
|