# include # include # include # include # include # define PRECISION_MAKE_tag(name) \ struct name \ { \ friend std::ostream& operator<< (std::ostream& s, name const&) \ { \ return s<< #name; \ } \ }; # define PRECISION_MAKE_terminal(name) \ proto::terminal< tag::name >::type const name = {{}} namespace proto = boost::proto; namespace tag{ PRECISION_MAKE_tag(a); PRECISION_MAKE_tag(b); PRECISION_MAKE_tag(c); } namespace mpl = boost::mpl; namespace fusion = boost::fusion; using proto::_; #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) #define _left call #define _right call #define _make_plus(x,y) call #define _make_multiplies(x,y) call #endif struct DistributiveLaw : proto::or_< proto::when< proto::multiplies< _, proto::plus< _, _ > > , proto::_make_plus( proto::_make_multiplies( proto::_left , proto::_left( proto::_right ) ) , proto::_make_multiplies( proto::_left , proto::_right( proto::_right ) ) ) > > {}; PRECISION_MAKE_terminal(a); PRECISION_MAKE_terminal(b); PRECISION_MAKE_terminal(c); # undef PRECISION_MAKE_tag # undef PRECISION_MAKE_terminal int main() { proto::display_expr(a*(b+c)); proto::display_expr(DistributiveLaw()( a*(b+c) )); return boost::exit_success; }