1 ///////////////////////////////////////////////////////////////////////////////
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)
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>
20 namespace mpl
= boost::mpl
;
21 namespace proto
= boost::proto
;
22 namespace fusion
= boost::fusion
;
24 struct int_convertible
27 operator int() const { return 0; }
32 proto::shift_right
< proto::terminal
< std::istream
& >, proto::_
>
33 , proto::shift_right
< Input
, proto::_
>
39 proto::shift_left
< proto::terminal
< std::ostream
& >, proto::_
>
40 , proto::shift_left
< Output
, proto::_
>
44 proto::terminal
< std::istream
& >::type
const cin_
= {std::cin
};
45 proto::terminal
< std::ostream
& >::type
const cout_
= {std::cout
};
49 proto::terminal
<proto::_
>
50 , proto::nary_expr
<proto::_
, proto::vararg
<Anything
> >
58 template<typename Tag
>
60 : proto::not_
<proto::_
>
65 struct MyCases::case_
<proto::tag::shift_right
>
70 struct MyCases::case_
<proto::tag::plus
>
74 enum binary_representation_enum
81 mpl::integral_c
<binary_representation_enum
, magnitude
>
85 mpl::integral_c
<binary_representation_enum
, two_complement
>
88 template<typename Type
, typename Representation
>
94 proto::terminal
<number
<proto::_
, two_complement_c
> >
95 , proto::terminal
<number
<proto::_
, magnitude_c
> >
106 template<typename Expr
>
110 : proto::domain
<proto::pod_generator
<my_expr
> >
113 template<typename Expr
>
116 BOOST_PROTO_BASIC_EXTENDS(Expr
, my_expr
, my_domain
)
121 proto::assert_matches
< proto::_
>( proto::lit(1) );
122 proto::assert_matches
< proto::_
>( proto::as_child(1) );
123 proto::assert_matches
< proto::_
>( proto::as_expr(1) );
125 proto::assert_matches
< proto::terminal
<int> >( proto::lit(1) );
126 proto::assert_matches
< proto::terminal
<int> >( proto::as_child(1) );
127 proto::assert_matches
< proto::terminal
<int> >( proto::as_expr(1) );
129 proto::assert_matches_not
< proto::terminal
<int> >( proto::lit('a') );
130 proto::assert_matches_not
< proto::terminal
<int> >( proto::as_child('a') );
131 proto::assert_matches_not
< proto::terminal
<int> >( proto::as_expr('a') );
133 proto::assert_matches
< proto::terminal
<proto::convertible_to
<int> > >( proto::lit('a') );
134 proto::assert_matches
< proto::terminal
<proto::convertible_to
<int> > >( proto::as_child('a') );
135 proto::assert_matches
< proto::terminal
<proto::convertible_to
<int> > >( proto::as_expr('a') );
137 proto::assert_matches_not
< proto::terminal
<int> >( proto::lit((int_convertible())) );
138 proto::assert_matches_not
< proto::terminal
<int> >( proto::as_child((int_convertible())) );
139 proto::assert_matches_not
< proto::terminal
<int> >( proto::as_expr((int_convertible())) );
141 proto::assert_matches
< proto::terminal
<proto::convertible_to
<int> > >( proto::lit((int_convertible())) );
142 proto::assert_matches
< proto::terminal
<proto::convertible_to
<int> > >( proto::as_child((int_convertible())) );
143 proto::assert_matches
< proto::terminal
<proto::convertible_to
<int> > >( proto::as_expr((int_convertible())) );
145 proto::assert_matches
< proto::if_
<boost::is_same
<proto::_value
, int>() > >( proto::lit(1) );
146 proto::assert_matches_not
< proto::if_
<boost::is_same
<proto::_value
, int>() > >( proto::lit('a') );
148 proto::assert_matches
<
150 proto::terminal
<proto::_
>
151 , proto::if_
<boost::is_same
<proto::_value
, int>() >
155 proto::assert_matches_not
<
157 proto::terminal
<proto::_
>
158 , proto::if_
<boost::is_same
<proto::_value
, int>() >
160 >( proto::lit('a') );
162 proto::assert_matches
< proto::terminal
<char const *> >( proto::lit("hello") );
163 proto::assert_matches
< proto::terminal
<char const *> >( proto::as_child("hello") );
164 proto::assert_matches
< proto::terminal
<char const *> >( proto::as_expr("hello") );
166 proto::assert_matches
< proto::terminal
<char const[6]> >( proto::lit("hello") );
167 proto::assert_matches
< proto::terminal
<char const (&)[6]> >( proto::as_child("hello") );
168 proto::assert_matches
< proto::terminal
<char const[6]> >( proto::as_expr("hello") );
170 proto::assert_matches
< proto::terminal
<char [6]> >( proto::lit("hello") );
171 proto::assert_matches
< proto::terminal
<char [6]> >( proto::as_child("hello") );
172 proto::assert_matches
< proto::terminal
<char [6]> >( proto::as_expr("hello") );
174 proto::assert_matches
< proto::terminal
<char const[proto::N
]> >( proto::lit("hello") );
175 proto::assert_matches
< proto::terminal
<char const (&)[proto::N
]> >( proto::as_child("hello") );
176 proto::assert_matches
< proto::terminal
<char const[proto::N
]> >( proto::as_expr("hello") );
178 proto::assert_matches
< proto::terminal
<char [proto::N
]> >( proto::lit("hello") );
179 proto::assert_matches
< proto::terminal
<char [proto::N
]> >( proto::as_child("hello") );
180 proto::assert_matches
< proto::terminal
<char [proto::N
]> >( proto::as_expr("hello") );
182 proto::assert_matches
< proto::terminal
<wchar_t const[proto::N
]> >( proto::lit(L
"hello") );
183 proto::assert_matches
< proto::terminal
<wchar_t const (&)[proto::N
]> >( proto::as_child(L
"hello") );
184 proto::assert_matches
< proto::terminal
<wchar_t const[proto::N
]> >( proto::as_expr(L
"hello") );
186 proto::assert_matches
< proto::terminal
<wchar_t [proto::N
]> >( proto::lit(L
"hello") );
187 proto::assert_matches
< proto::terminal
<wchar_t [proto::N
]> >( proto::as_child(L
"hello") );
188 proto::assert_matches
< proto::terminal
<wchar_t [proto::N
]> >( proto::as_expr(L
"hello") );
190 proto::assert_matches_not
< proto::if_
<boost::is_same
<proto::_value
, int>()> >( proto::lit("hello") );
192 proto::assert_matches
< proto::terminal
<std::string
> >( proto::lit(std::string("hello")) );
193 proto::assert_matches
< proto::terminal
<std::string
> >( proto::as_child(std::string("hello")) );
194 proto::assert_matches
< proto::terminal
<std::string
> >( proto::as_expr(std::string("hello")) );
196 proto::assert_matches
< proto::terminal
<std::basic_string
<proto::_
> > >( proto::lit(std::string("hello")) );
197 proto::assert_matches
< proto::terminal
<std::basic_string
<proto::_
> > >( proto::as_child(std::string("hello")) );
198 proto::assert_matches
< proto::terminal
<std::basic_string
<proto::_
> > >( proto::as_expr(std::string("hello")) );
200 proto::assert_matches_not
< proto::terminal
<std::basic_string
<proto::_
> > >( proto::lit(1) );
201 proto::assert_matches_not
< proto::terminal
<std::basic_string
<proto::_
> > >( proto::as_child(1) );
202 proto::assert_matches_not
< proto::terminal
<std::basic_string
<proto::_
> > >( proto::as_expr(1) );
204 proto::assert_matches_not
< proto::terminal
<std::basic_string
<proto::_
,proto::_
,proto::_
> > >( proto::lit(1) );
205 proto::assert_matches_not
< proto::terminal
<std::basic_string
<proto::_
,proto::_
,proto::_
> > >( proto::as_child(1) );
206 proto::assert_matches_not
< proto::terminal
<std::basic_string
<proto::_
,proto::_
,proto::_
> > >( proto::as_expr(1) );
208 #if BOOST_WORKAROUND(__HP_aCC, BOOST_TESTED_AT(61700))
209 typedef std::string
const const_string
;
211 typedef std::string const_string
;
214 proto::assert_matches
< proto::terminal
<std::basic_string
<proto::_
> const & > >( proto::lit(const_string("hello")) );
215 proto::assert_matches
< proto::terminal
<std::basic_string
<proto::_
> const & > >( proto::as_child(const_string("hello")) );
216 proto::assert_matches_not
< proto::terminal
<std::basic_string
<proto::_
> const & > >( proto::as_expr(const_string("hello")) );
218 proto::assert_matches
< proto::terminal
< void(&)() > >( proto::lit(a_function
) );
219 proto::assert_matches
< proto::terminal
< void(&)() > >( proto::as_child(a_function
) );
220 proto::assert_matches
< proto::terminal
< void(&)() > >( proto::as_expr(a_function
) );
222 proto::assert_matches_not
< proto::terminal
< void(*)() > >( proto::lit(a_function
) );
223 proto::assert_matches_not
< proto::terminal
< void(*)() > >( proto::as_child(a_function
) );
224 proto::assert_matches_not
< proto::terminal
< void(*)() > >( proto::as_expr(a_function
) );
226 proto::assert_matches
< proto::terminal
< proto::convertible_to
<void(*)()> > >( proto::lit(a_function
) );
227 proto::assert_matches
< proto::terminal
< proto::convertible_to
<void(*)()> > >( proto::as_child(a_function
) );
228 proto::assert_matches
< proto::terminal
< proto::convertible_to
<void(*)()> > >( proto::as_expr(a_function
) );
230 proto::assert_matches
< proto::terminal
< void(*)() > >( proto::lit(&a_function
) );
231 proto::assert_matches
< proto::terminal
< void(*)() > >( proto::as_child(&a_function
) );
232 proto::assert_matches
< proto::terminal
< void(*)() > >( proto::as_expr(&a_function
) );
234 proto::assert_matches
< proto::terminal
< void(* const &)() > >( proto::lit(&a_function
) );
235 proto::assert_matches
< proto::terminal
< void(* const &)() > >( proto::as_child(&a_function
) );
236 proto::assert_matches_not
< proto::terminal
< void(* const &)() > >( proto::as_expr(&a_function
) );
238 proto::assert_matches
<
240 proto::if_
<boost::is_same
<proto::_value
, char>() >
241 , proto::if_
<boost::is_same
<proto::_value
, int>() >
245 proto::assert_matches_not
<
247 proto::if_
<boost::is_same
<proto::_value
, char>() >
248 , proto::if_
<boost::is_same
<proto::_value
, int>() >
252 proto::assert_matches
< Input
>( cin_
>> 1 >> 2 >> 3 );
253 proto::assert_matches_not
< Output
>( cin_
>> 1 >> 2 >> 3 );
255 proto::assert_matches
< Output
>( cout_
<< 1 << 2 << 3 );
256 proto::assert_matches_not
< Input
>( cout_
<< 1 << 2 << 3 );
258 proto::assert_matches
< proto::function
< proto::terminal
<int>, proto::vararg
< proto::terminal
<char> > > >( proto::lit(1)('a','b','c','d') );
259 proto::assert_matches_not
< proto::function
< proto::terminal
<int>, proto::vararg
< proto::terminal
<char> > > >( proto::lit(1)('a','b','c',"d") );
261 proto::assert_matches
< Anything
>( cout_
<< 1 << +proto::lit('a') << proto::lit(1)('a','b','c',"d") );
263 proto::assert_matches
< proto::switch_
<MyCases
> >( proto::lit(1) >> 'a' );
264 proto::assert_matches
< proto::switch_
<MyCases
> >( proto::lit(1) + 'a' );
265 proto::assert_matches_not
< proto::switch_
<MyCases
> >( proto::lit(1) << 'a' );
267 number
<int, two_complement_c
> num
;
268 proto::assert_matches
<NumberGrammar
>(proto::as_expr(num
));
270 // check custom terminal types
272 proto::nullary_expr
<my_terminal
, int>::type i
= {0};
274 proto::assert_matches
<proto::nullary_expr
<my_terminal
, proto::_
> >( i
);
275 proto::assert_matches_not
<proto::terminal
<proto::_
> >( i
);
277 proto::terminal
<int>::type j
= {0};
278 proto::assert_matches
<proto::terminal
<proto::_
> >( j
);
279 proto::assert_matches_not
<proto::nullary_expr
<my_terminal
, proto::_
> >( j
);
281 proto::assert_matches
<proto::nullary_expr
<proto::_
, proto::_
> >( i
);
284 // check 0 and 1 arg forms or or_ and and_
286 proto::assert_matches
< proto::and_
<> >( proto::lit(1) );
287 proto::assert_matches_not
< proto::or_
<> >( proto::lit(1) );
289 proto::assert_matches
< proto::and_
<proto::terminal
<int> > >( proto::lit(1) );
290 proto::assert_matches
< proto::or_
<proto::terminal
<int> > >( proto::lit(1) );
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
296 a_template
<int[3]> a
;
297 proto::assert_matches
< proto::terminal
< a_template
<proto::_
> > >( proto::lit(a
) );
300 // Test that the actual derived expression type makes it through to proto::if_
302 my_expr
<proto::terminal
<int>::type
> e
= {{1}};
303 proto::assert_matches
< proto::if_
<boost::is_same
<proto::domain_of
<proto::_
>, my_domain
>()> >( e
);
307 using namespace boost::unit_test
;
308 ///////////////////////////////////////////////////////////////////////////////
309 // init_unit_test_suite
311 test_suite
* init_unit_test_suite( int argc
, char* argv
[] )
313 test_suite
*test
= BOOST_TEST_SUITE("test proto::matches<>");
315 test
->add(BOOST_TEST_CASE(&test_matches
));