/////////////////////////////////////////////////////////////////////////////// // proto_fusion_s.cpp // // Copyright 2008 Eric Niebler. 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 #include #include #include #include #include std::ostream &operator <<(std::ostream &sout, boost::proto::tag::shift_right) { return sout << ">>"; } std::ostream &operator <<(std::ostream &sout, boost::proto::tag::bitwise_or) { return sout << "|"; } template std::ostream &operator <<(std::ostream &sout, boost::proto::expr const *op) { return sout << boost::proto::value(*op); } template std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr const *op) { return sout << boost::proto::value(*op); } template std::ostream &operator <<(std::ostream &sout, boost::proto::expr const *op) { return sout << Tag() << boost::addressof(boost::proto::child(*op).proto_base()); } template std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr const *op) { return sout << Tag() << boost::addressof(boost::proto::child(*op).proto_base()); } template std::ostream &operator <<(std::ostream &sout, boost::proto::expr const *op) { return sout << boost::addressof(boost::proto::left(*op).proto_base()) << Tag() << boost::addressof(boost::proto::right(*op).proto_base()); } template std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr const *op) { return sout << boost::addressof(boost::proto::left(*op).proto_base()) << Tag() << boost::addressof(boost::proto::right(*op).proto_base()); } /////////////////////////////////////////////////////////////////////////////// // to_string // struct to_string { to_string(std::ostream &sout) : sout_(sout) {} template void operator ()(Op const &op) const { this->sout_ << '(' << boost::addressof(op.proto_base()) << ')'; } private: std::ostream &sout_; }; void test1() { using boost::proto::flatten; boost::proto::terminal::type a_ = {'a'}; boost::proto::terminal::type b_ = {'b'}; boost::proto::terminal::type c_ = {'c'}; boost::proto::terminal::type d_ = {'d'}; boost::proto::terminal::type e_ = {'e'}; boost::proto::terminal::type f_ = {'f'}; boost::proto::terminal::type g_ = {'g'}; boost::proto::terminal::type h_ = {'h'}; boost::proto::terminal::type i_ = {'i'}; std::stringstream sout; // Test for 1-way branching "tree" sout.str(""); boost::fusion::for_each(flatten(!!!!(a_ >> b_)), to_string(sout)); BOOST_CHECK_EQUAL("(a>>b)", sout.str()); // Tests for 2-way branching trees sout.str(""); boost::fusion::for_each(flatten(a_ >> b_ >> c_), to_string(sout)); BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ | b_ | c_), to_string(sout)); BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_), to_string(sout)); BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ | b_ >> c_ | d_), to_string(sout)); BOOST_CHECK_EQUAL("(a)(b>>c)(d)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_), to_string(sout)); BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f>>g)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_), to_string(sout)); BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f|g>>h)", sout.str()); // Test for n-way branching tree sout.str(""); boost::fusion::for_each(flatten(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_)), to_string(sout)); BOOST_CHECK_EQUAL("(a)(b)(c>>d)(e|f)(g>>h)(i)", sout.str()); } //////////////////////////////////////////////////////////////////////// // Test that EXTENDS expression wrappers are also valid fusion sequences template struct My; struct MyDomain : boost::proto::domain > {}; template struct My { BOOST_PROTO_EXTENDS(Expr, My, MyDomain) }; void test2() { using boost::proto::flatten; My::type> a_ = {{'a'}}; My::type> b_ = {{'b'}}; My::type> c_ = {{'c'}}; My::type> d_ = {{'d'}}; My::type> e_ = {{'e'}}; My::type> f_ = {{'f'}}; My::type> g_ = {{'g'}}; My::type> h_ = {{'h'}}; My::type> i_ = {{'i'}}; std::stringstream sout; // Test for 1-way branching "tree" sout.str(""); boost::fusion::for_each(flatten(!!!!(a_ >> b_)), to_string(sout)); BOOST_CHECK_EQUAL("(a>>b)", sout.str()); // Tests for 2-way branching trees sout.str(""); boost::fusion::for_each(flatten(a_ >> b_ >> c_), to_string(sout)); BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ | b_ | c_), to_string(sout)); BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_), to_string(sout)); BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ | b_ >> c_ | d_), to_string(sout)); BOOST_CHECK_EQUAL("(a)(b>>c)(d)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_), to_string(sout)); BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f>>g)", sout.str()); sout.str(""); boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_), to_string(sout)); BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f|g>>h)", sout.str()); // Test for n-way branching tree sout.str(""); boost::fusion::for_each(flatten(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_)), to_string(sout)); BOOST_CHECK_EQUAL("(a)(b)(c>>d)(e|f)(g>>h)(i)", sout.str()); } using namespace boost::unit_test; /////////////////////////////////////////////////////////////////////////////// // init_unit_test_suite // test_suite* init_unit_test_suite( int argc, char* argv[] ) { test_suite *test = BOOST_TEST_SUITE("test proto and segmented fusion integration"); test->add(BOOST_TEST_CASE(&test1)); test->add(BOOST_TEST_CASE(&test2)); return test; }