[ create a new paste ] login | about

Link: http://codepad.org/MO2NUgI2    [ raw code | fork ]

C++, pasted on Apr 3:
#include <iostream>
#include <boost/proto/core.hpp>
#include <boost/proto/transform.hpp>
#include <boost/proto/debug.hpp>
#include <boost/fusion/include/for_each.hpp>
namespace proto = boost::proto;
using proto::_;

template<typename Expr>
struct calculator_expression;

struct calculator_domain
  : proto::domain<proto::generator<calculator_expression> >
{
};

struct tag_subexpression
{
    template<typename Expr>
    void operator()(Expr const& e) const
    {
        e.is_top_level = 0;
    }
};

struct value;

template<typename Expr>
struct calculator_expression
  : proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
{
    template<typename Xpr>
    explicit calculator_expression(
         Xpr const &expr = Xpr(),
        typename boost::disable_if<
            boost::mpl::and_<
                proto::is_expr<Xpr>,
                boost::mpl::not_<
                    boost::is_same<typename proto::tag_of<Xpr>::type, proto::tag::terminal>
                >
            >
        >::type* = 0
    )
      : calculator_expression::proto_extends(expr), is_top_level(0)
    {
    }
    
    template<typename Xpr>
    explicit calculator_expression(
        Xpr const &expr = Xpr(),
        typename boost::enable_if<
            boost::mpl::and_<
                proto::is_expr<Xpr>,
                boost::mpl::not_<
                    boost::is_same<typename proto::tag_of<Xpr>::type, proto::tag::terminal>
                >
            >
        >::type* = 0
    )
      : calculator_expression::proto_extends(expr), is_top_level(1)
    {
        boost::fusion::for_each(expr, tag_subexpression());
    }

    BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression)
    
    operator value() const;
    
    ~calculator_expression()
    {
        if(is_top_level)
            evaluate(*this);
    }
    
    mutable bool is_top_level;
};

struct value
  : calculator_expression<proto::terminal<int>::type>
{
    typedef calculator_expression<proto::terminal<int>::type> base_type;
    
    value(int e)
      : base_type(proto::make_expr<proto::tag::terminal>(e))
    {
    }

    template<typename Expr>
    typename proto::result_of::make_expr<
        proto::tag::assign,
        base_type&,
        Expr const&
    >::type
    operator=(Expr const& e)
    {
        return static_cast<base_type&>(*this) = e;
    }
};

template<typename Expr>
value evaluate(Expr const& e)
{
    return proto::_default<>()(e);
}

template<typename Expr>
calculator_expression<Expr>::operator value() const
{
    value v(evaluate(*this));
    is_top_level = 0;
    return v;
}

void bar(const value& v);

int foo()
{
    value a = 1;
    value b = 2;
    
    bar(b = b += a * 2);
}


Create a new paste based on this one


Comments: