matches.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // matches.hpp
  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 <string>
  8. #include <iostream>
  9. #include <boost/config.hpp>
  10. #include <boost/detail/workaround.hpp>
  11. #include <boost/mpl/assert.hpp>
  12. #include <boost/mpl/placeholders.hpp>
  13. #include <boost/type_traits/is_same.hpp>
  14. #include <boost/proto/core.hpp>
  15. #include <boost/proto/debug.hpp>
  16. #include <boost/proto/transform/arg.hpp>
  17. #include <boost/test/unit_test.hpp>
  18. namespace mpl = boost::mpl;
  19. namespace proto = boost::proto;
  20. namespace fusion = boost::fusion;
  21. struct int_convertible
  22. {
  23. int_convertible() {}
  24. operator int() const { return 0; }
  25. };
  26. struct Input
  27. : proto::or_<
  28. proto::shift_right< proto::terminal< std::istream & >, proto::_ >
  29. , proto::shift_right< Input, proto::_ >
  30. >
  31. {};
  32. struct Output
  33. : proto::or_<
  34. proto::shift_left< proto::terminal< std::ostream & >, proto::_ >
  35. , proto::shift_left< Output, proto::_ >
  36. >
  37. {};
  38. proto::terminal< std::istream & >::type const cin_ = {std::cin};
  39. proto::terminal< std::ostream & >::type const cout_ = {std::cout};
  40. struct Anything
  41. : proto::or_<
  42. proto::terminal<proto::_>
  43. , proto::nary_expr<proto::_, proto::vararg<Anything> >
  44. >
  45. {};
  46. void a_function() {}
  47. struct MyCases
  48. {
  49. template<typename Tag>
  50. struct case_
  51. : proto::not_<proto::_>
  52. {};
  53. };
  54. template<>
  55. struct MyCases::case_<proto::tag::shift_right>
  56. : proto::_
  57. {};
  58. template<>
  59. struct MyCases::case_<proto::tag::plus>
  60. : proto::_
  61. {};
  62. enum binary_representation_enum
  63. {
  64. magnitude
  65. , two_complement
  66. };
  67. typedef
  68. mpl::integral_c<binary_representation_enum, magnitude>
  69. magnitude_c;
  70. typedef
  71. mpl::integral_c<binary_representation_enum, two_complement>
  72. two_complement_c;
  73. template<typename Type, typename Representation>
  74. struct number
  75. {};
  76. struct NumberGrammar
  77. : proto::or_ <
  78. proto::terminal<number<proto::_, two_complement_c> >
  79. , proto::terminal<number<proto::_, magnitude_c> >
  80. >
  81. {};
  82. struct my_terminal
  83. {};
  84. template<typename T>
  85. struct a_template
  86. {};
  87. template<typename Expr>
  88. struct my_expr;
  89. struct my_domain
  90. : proto::domain<proto::pod_generator<my_expr> >
  91. {};
  92. template<typename Expr>
  93. struct my_expr
  94. {
  95. BOOST_PROTO_BASIC_EXTENDS(Expr, my_expr, my_domain)
  96. };
  97. void test_matches()
  98. {
  99. proto::assert_matches< proto::_ >( proto::lit(1) );
  100. proto::assert_matches< proto::_ >( proto::as_child(1) );
  101. proto::assert_matches< proto::_ >( proto::as_expr(1) );
  102. proto::assert_matches< proto::terminal<int> >( proto::lit(1) );
  103. proto::assert_matches< proto::terminal<int> >( proto::as_child(1) );
  104. proto::assert_matches< proto::terminal<int> >( proto::as_expr(1) );
  105. proto::assert_matches_not< proto::terminal<int> >( proto::lit('a') );
  106. proto::assert_matches_not< proto::terminal<int> >( proto::as_child('a') );
  107. proto::assert_matches_not< proto::terminal<int> >( proto::as_expr('a') );
  108. proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::lit('a') );
  109. proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::as_child('a') );
  110. proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::as_expr('a') );
  111. proto::assert_matches_not< proto::terminal<int> >( proto::lit((int_convertible())) );
  112. proto::assert_matches_not< proto::terminal<int> >( proto::as_child((int_convertible())) );
  113. proto::assert_matches_not< proto::terminal<int> >( proto::as_expr((int_convertible())) );
  114. proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::lit((int_convertible())) );
  115. proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::as_child((int_convertible())) );
  116. proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::as_expr((int_convertible())) );
  117. proto::assert_matches< proto::if_<boost::is_same<proto::_value, int>() > >( proto::lit(1) );
  118. proto::assert_matches_not< proto::if_<boost::is_same<proto::_value, int>() > >( proto::lit('a') );
  119. proto::assert_matches<
  120. proto::and_<
  121. proto::terminal<proto::_>
  122. , proto::if_<boost::is_same<proto::_value, int>() >
  123. >
  124. >( proto::lit(1) );
  125. proto::assert_matches_not<
  126. proto::and_<
  127. proto::terminal<proto::_>
  128. , proto::if_<boost::is_same<proto::_value, int>() >
  129. >
  130. >( proto::lit('a') );
  131. proto::assert_matches< proto::terminal<char const *> >( proto::lit("hello") );
  132. proto::assert_matches< proto::terminal<char const *> >( proto::as_child("hello") );
  133. proto::assert_matches< proto::terminal<char const *> >( proto::as_expr("hello") );
  134. proto::assert_matches< proto::terminal<char const[6]> >( proto::lit("hello") );
  135. proto::assert_matches< proto::terminal<char const (&)[6]> >( proto::as_child("hello") );
  136. proto::assert_matches< proto::terminal<char const[6]> >( proto::as_expr("hello") );
  137. proto::assert_matches< proto::terminal<char [6]> >( proto::lit("hello") );
  138. proto::assert_matches< proto::terminal<char [6]> >( proto::as_child("hello") );
  139. proto::assert_matches< proto::terminal<char [6]> >( proto::as_expr("hello") );
  140. proto::assert_matches< proto::terminal<char const[proto::N]> >( proto::lit("hello") );
  141. proto::assert_matches< proto::terminal<char const (&)[proto::N]> >( proto::as_child("hello") );
  142. proto::assert_matches< proto::terminal<char const[proto::N]> >( proto::as_expr("hello") );
  143. proto::assert_matches< proto::terminal<char [proto::N]> >( proto::lit("hello") );
  144. proto::assert_matches< proto::terminal<char [proto::N]> >( proto::as_child("hello") );
  145. proto::assert_matches< proto::terminal<char [proto::N]> >( proto::as_expr("hello") );
  146. proto::assert_matches< proto::terminal<wchar_t const[proto::N]> >( proto::lit(L"hello") );
  147. proto::assert_matches< proto::terminal<wchar_t const (&)[proto::N]> >( proto::as_child(L"hello") );
  148. proto::assert_matches< proto::terminal<wchar_t const[proto::N]> >( proto::as_expr(L"hello") );
  149. proto::assert_matches< proto::terminal<wchar_t [proto::N]> >( proto::lit(L"hello") );
  150. proto::assert_matches< proto::terminal<wchar_t [proto::N]> >( proto::as_child(L"hello") );
  151. proto::assert_matches< proto::terminal<wchar_t [proto::N]> >( proto::as_expr(L"hello") );
  152. proto::assert_matches_not< proto::if_<boost::is_same<proto::_value, int>()> >( proto::lit("hello") );
  153. proto::assert_matches< proto::terminal<std::string> >( proto::lit(std::string("hello")) );
  154. proto::assert_matches< proto::terminal<std::string> >( proto::as_child(std::string("hello")) );
  155. proto::assert_matches< proto::terminal<std::string> >( proto::as_expr(std::string("hello")) );
  156. proto::assert_matches< proto::terminal<std::basic_string<proto::_> > >( proto::lit(std::string("hello")) );
  157. proto::assert_matches< proto::terminal<std::basic_string<proto::_> > >( proto::as_child(std::string("hello")) );
  158. proto::assert_matches< proto::terminal<std::basic_string<proto::_> > >( proto::as_expr(std::string("hello")) );
  159. proto::assert_matches_not< proto::terminal<std::basic_string<proto::_> > >( proto::lit(1) );
  160. proto::assert_matches_not< proto::terminal<std::basic_string<proto::_> > >( proto::as_child(1) );
  161. proto::assert_matches_not< proto::terminal<std::basic_string<proto::_> > >( proto::as_expr(1) );
  162. proto::assert_matches_not< proto::terminal<std::basic_string<proto::_,proto::_,proto::_> > >( proto::lit(1) );
  163. proto::assert_matches_not< proto::terminal<std::basic_string<proto::_,proto::_,proto::_> > >( proto::as_child(1) );
  164. proto::assert_matches_not< proto::terminal<std::basic_string<proto::_,proto::_,proto::_> > >( proto::as_expr(1) );
  165. #if BOOST_WORKAROUND(__HP_aCC, BOOST_TESTED_AT(61700))
  166. typedef std::string const const_string;
  167. #else
  168. typedef std::string const_string;
  169. #endif
  170. proto::assert_matches< proto::terminal<std::basic_string<proto::_> const & > >( proto::lit(const_string("hello")) );
  171. proto::assert_matches< proto::terminal<std::basic_string<proto::_> const & > >( proto::as_child(const_string("hello")) );
  172. proto::assert_matches_not< proto::terminal<std::basic_string<proto::_> const & > >( proto::as_expr(const_string("hello")) );
  173. proto::assert_matches< proto::terminal< void(&)() > >( proto::lit(a_function) );
  174. proto::assert_matches< proto::terminal< void(&)() > >( proto::as_child(a_function) );
  175. proto::assert_matches< proto::terminal< void(&)() > >( proto::as_expr(a_function) );
  176. proto::assert_matches_not< proto::terminal< void(*)() > >( proto::lit(a_function) );
  177. proto::assert_matches_not< proto::terminal< void(*)() > >( proto::as_child(a_function) );
  178. proto::assert_matches_not< proto::terminal< void(*)() > >( proto::as_expr(a_function) );
  179. proto::assert_matches< proto::terminal< proto::convertible_to<void(*)()> > >( proto::lit(a_function) );
  180. proto::assert_matches< proto::terminal< proto::convertible_to<void(*)()> > >( proto::as_child(a_function) );
  181. proto::assert_matches< proto::terminal< proto::convertible_to<void(*)()> > >( proto::as_expr(a_function) );
  182. proto::assert_matches< proto::terminal< void(*)() > >( proto::lit(&a_function) );
  183. proto::assert_matches< proto::terminal< void(*)() > >( proto::as_child(&a_function) );
  184. proto::assert_matches< proto::terminal< void(*)() > >( proto::as_expr(&a_function) );
  185. proto::assert_matches< proto::terminal< void(* const &)() > >( proto::lit(&a_function) );
  186. proto::assert_matches< proto::terminal< void(* const &)() > >( proto::as_child(&a_function) );
  187. proto::assert_matches_not< proto::terminal< void(* const &)() > >( proto::as_expr(&a_function) );
  188. proto::assert_matches<
  189. proto::or_<
  190. proto::if_<boost::is_same<proto::_value, char>() >
  191. , proto::if_<boost::is_same<proto::_value, int>() >
  192. >
  193. >( proto::lit(1) );
  194. proto::assert_matches_not<
  195. proto::or_<
  196. proto::if_<boost::is_same<proto::_value, char>() >
  197. , proto::if_<boost::is_same<proto::_value, int>() >
  198. >
  199. >( proto::lit(1u) );
  200. proto::assert_matches< Input >( cin_ >> 1 >> 2 >> 3 );
  201. proto::assert_matches_not< Output >( cin_ >> 1 >> 2 >> 3 );
  202. proto::assert_matches< Output >( cout_ << 1 << 2 << 3 );
  203. proto::assert_matches_not< Input >( cout_ << 1 << 2 << 3 );
  204. proto::assert_matches< proto::function< proto::terminal<int>, proto::vararg< proto::terminal<char> > > >( proto::lit(1)('a','b','c','d') );
  205. proto::assert_matches_not< proto::function< proto::terminal<int>, proto::vararg< proto::terminal<char> > > >( proto::lit(1)('a','b','c',"d") );
  206. proto::assert_matches< Anything >( cout_ << 1 << +proto::lit('a') << proto::lit(1)('a','b','c',"d") );
  207. proto::assert_matches< proto::switch_<MyCases> >( proto::lit(1) >> 'a' );
  208. proto::assert_matches< proto::switch_<MyCases> >( proto::lit(1) + 'a' );
  209. proto::assert_matches_not< proto::switch_<MyCases> >( proto::lit(1) << 'a' );
  210. number<int, two_complement_c> num;
  211. proto::assert_matches<NumberGrammar>(proto::as_expr(num));
  212. // check custom terminal types
  213. {
  214. proto::nullary_expr<my_terminal, int>::type i = {0};
  215. proto::assert_matches<proto::nullary_expr<my_terminal, proto::_> >( i );
  216. proto::assert_matches_not<proto::terminal<proto::_> >( i );
  217. proto::terminal<int>::type j = {0};
  218. proto::assert_matches<proto::terminal<proto::_> >( j );
  219. proto::assert_matches_not<proto::nullary_expr<my_terminal, proto::_> >( j );
  220. proto::assert_matches<proto::nullary_expr<proto::_, proto::_> >( i );
  221. }
  222. // check 0 and 1 arg forms or or_ and and_
  223. {
  224. proto::assert_matches< proto::and_<> >( proto::lit(1) );
  225. proto::assert_matches_not< proto::or_<> >( proto::lit(1) );
  226. proto::assert_matches< proto::and_<proto::terminal<int> > >( proto::lit(1) );
  227. proto::assert_matches< proto::or_<proto::terminal<int> > >( proto::lit(1) );
  228. }
  229. // Test lambda matches with arrays, a corner case that had
  230. // a bug that was reported by Antoine de Maricourt on boost@lists.boost.org
  231. {
  232. a_template<int[3]> a;
  233. proto::assert_matches< proto::terminal< a_template<proto::_> > >( proto::lit(a) );
  234. }
  235. // Test that the actual derived expression type makes it through to proto::if_
  236. {
  237. my_expr<proto::terminal<int>::type> e = {{1}};
  238. proto::assert_matches< proto::if_<boost::is_same<proto::domain_of<proto::_>, my_domain>()> >( e );
  239. }
  240. }
  241. using namespace boost::unit_test;
  242. ///////////////////////////////////////////////////////////////////////////////
  243. // init_unit_test_suite
  244. //
  245. test_suite* init_unit_test_suite( int argc, char* argv[] )
  246. {
  247. test_suite *test = BOOST_TEST_SUITE("test proto::matches<>");
  248. test->add(BOOST_TEST_CASE(&test_matches));
  249. return test;
  250. }