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

source code of boost/libs/proto/test/matches.cpp