flatten.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // proto_fusion_s.cpp
  3. //
  4. // Copyright 2008 Eric Niebler. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #include <boost/proto/core.hpp>
  8. #include <boost/proto/fusion.hpp>
  9. #include <boost/fusion/include/for_each.hpp>
  10. #include <boost/test/unit_test.hpp>
  11. #include <boost/utility/addressof.hpp>
  12. #include <sstream>
  13. std::ostream &operator <<(std::ostream &sout, boost::proto::tag::shift_right)
  14. {
  15. return sout << ">>";
  16. }
  17. std::ostream &operator <<(std::ostream &sout, boost::proto::tag::bitwise_or)
  18. {
  19. return sout << "|";
  20. }
  21. template<typename Args>
  22. std::ostream &operator <<(std::ostream &sout, boost::proto::expr<boost::proto::tag::terminal, Args, 0> const *op)
  23. {
  24. return sout << boost::proto::value(*op);
  25. }
  26. template<typename Args>
  27. std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<boost::proto::tag::terminal, Args, 0> const *op)
  28. {
  29. return sout << boost::proto::value(*op);
  30. }
  31. template<typename Tag, typename Args>
  32. std::ostream &operator <<(std::ostream &sout, boost::proto::expr<Tag, Args, 1> const *op)
  33. {
  34. return sout << Tag() << boost::addressof(boost::proto::child(*op).proto_base());
  35. }
  36. template<typename Tag, typename Args>
  37. std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<Tag, Args, 1> const *op)
  38. {
  39. return sout << Tag() << boost::addressof(boost::proto::child(*op).proto_base());
  40. }
  41. template<typename Tag, typename Args>
  42. std::ostream &operator <<(std::ostream &sout, boost::proto::expr<Tag, Args, 2> const *op)
  43. {
  44. return sout << boost::addressof(boost::proto::left(*op).proto_base()) << Tag() << boost::addressof(boost::proto::right(*op).proto_base());
  45. }
  46. template<typename Tag, typename Args>
  47. std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<Tag, Args, 2> const *op)
  48. {
  49. return sout << boost::addressof(boost::proto::left(*op).proto_base()) << Tag() << boost::addressof(boost::proto::right(*op).proto_base());
  50. }
  51. ///////////////////////////////////////////////////////////////////////////////
  52. // to_string
  53. //
  54. struct to_string
  55. {
  56. to_string(std::ostream &sout)
  57. : sout_(sout)
  58. {}
  59. template<typename Op>
  60. void operator ()(Op const &op) const
  61. {
  62. this->sout_ << '(' << boost::addressof(op.proto_base()) << ')';
  63. }
  64. private:
  65. std::ostream &sout_;
  66. };
  67. void test1()
  68. {
  69. using boost::proto::flatten;
  70. boost::proto::terminal<char>::type a_ = {'a'};
  71. boost::proto::terminal<char>::type b_ = {'b'};
  72. boost::proto::terminal<char>::type c_ = {'c'};
  73. boost::proto::terminal<char>::type d_ = {'d'};
  74. boost::proto::terminal<char>::type e_ = {'e'};
  75. boost::proto::terminal<char>::type f_ = {'f'};
  76. boost::proto::terminal<char>::type g_ = {'g'};
  77. boost::proto::terminal<char>::type h_ = {'h'};
  78. boost::proto::terminal<char>::type i_ = {'i'};
  79. std::stringstream sout;
  80. // Test for 1-way branching "tree"
  81. sout.str("");
  82. boost::fusion::for_each(flatten(!!!!(a_ >> b_)), to_string(sout));
  83. BOOST_CHECK_EQUAL("(a>>b)", sout.str());
  84. // Tests for 2-way branching trees
  85. sout.str("");
  86. boost::fusion::for_each(flatten(a_ >> b_ >> c_), to_string(sout));
  87. BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
  88. sout.str("");
  89. boost::fusion::for_each(flatten(a_ | b_ | c_), to_string(sout));
  90. BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
  91. sout.str("");
  92. boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_), to_string(sout));
  93. BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str());
  94. sout.str("");
  95. boost::fusion::for_each(flatten(a_ | b_ >> c_ | d_), to_string(sout));
  96. BOOST_CHECK_EQUAL("(a)(b>>c)(d)", sout.str());
  97. sout.str("");
  98. boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_), to_string(sout));
  99. BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f>>g)", sout.str());
  100. sout.str("");
  101. boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_), to_string(sout));
  102. BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f|g>>h)", sout.str());
  103. // Test for n-way branching tree
  104. sout.str("");
  105. boost::fusion::for_each(flatten(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_)), to_string(sout));
  106. BOOST_CHECK_EQUAL("(a)(b)(c>>d)(e|f)(g>>h)(i)", sout.str());
  107. }
  108. ////////////////////////////////////////////////////////////////////////
  109. // Test that EXTENDS expression wrappers are also valid fusion sequences
  110. template<typename Expr>
  111. struct My;
  112. struct MyDomain
  113. : boost::proto::domain<boost::proto::pod_generator<My> >
  114. {};
  115. template<typename Expr>
  116. struct My
  117. {
  118. BOOST_PROTO_EXTENDS(Expr, My<Expr>, MyDomain)
  119. };
  120. void test2()
  121. {
  122. using boost::proto::flatten;
  123. My<boost::proto::terminal<char>::type> a_ = {{'a'}};
  124. My<boost::proto::terminal<char>::type> b_ = {{'b'}};
  125. My<boost::proto::terminal<char>::type> c_ = {{'c'}};
  126. My<boost::proto::terminal<char>::type> d_ = {{'d'}};
  127. My<boost::proto::terminal<char>::type> e_ = {{'e'}};
  128. My<boost::proto::terminal<char>::type> f_ = {{'f'}};
  129. My<boost::proto::terminal<char>::type> g_ = {{'g'}};
  130. My<boost::proto::terminal<char>::type> h_ = {{'h'}};
  131. My<boost::proto::terminal<char>::type> i_ = {{'i'}};
  132. std::stringstream sout;
  133. // Test for 1-way branching "tree"
  134. sout.str("");
  135. boost::fusion::for_each(flatten(!!!!(a_ >> b_)), to_string(sout));
  136. BOOST_CHECK_EQUAL("(a>>b)", sout.str());
  137. // Tests for 2-way branching trees
  138. sout.str("");
  139. boost::fusion::for_each(flatten(a_ >> b_ >> c_), to_string(sout));
  140. BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
  141. sout.str("");
  142. boost::fusion::for_each(flatten(a_ | b_ | c_), to_string(sout));
  143. BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
  144. sout.str("");
  145. boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_), to_string(sout));
  146. BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str());
  147. sout.str("");
  148. boost::fusion::for_each(flatten(a_ | b_ >> c_ | d_), to_string(sout));
  149. BOOST_CHECK_EQUAL("(a)(b>>c)(d)", sout.str());
  150. sout.str("");
  151. boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_), to_string(sout));
  152. BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f>>g)", sout.str());
  153. sout.str("");
  154. boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_), to_string(sout));
  155. BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f|g>>h)", sout.str());
  156. // Test for n-way branching tree
  157. sout.str("");
  158. boost::fusion::for_each(flatten(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_)), to_string(sout));
  159. BOOST_CHECK_EQUAL("(a)(b)(c>>d)(e|f)(g>>h)(i)", sout.str());
  160. }
  161. using namespace boost::unit_test;
  162. ///////////////////////////////////////////////////////////////////////////////
  163. // init_unit_test_suite
  164. //
  165. test_suite* init_unit_test_suite( int argc, char* argv[] )
  166. {
  167. test_suite *test = BOOST_TEST_SUITE("test proto and segmented fusion integration");
  168. test->add(BOOST_TEST_CASE(&test1));
  169. test->add(BOOST_TEST_CASE(&test2));
  170. return test;
  171. }