diff options
Diffstat (limited to 'src/boost/libs/phoenix/example/invert.cpp')
-rw-r--r-- | src/boost/libs/phoenix/example/invert.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/boost/libs/phoenix/example/invert.cpp b/src/boost/libs/phoenix/example/invert.cpp new file mode 100644 index 00000000..3c5e64f0 --- /dev/null +++ b/src/boost/libs/phoenix/example/invert.cpp @@ -0,0 +1,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)); +} + |