/////////////////////////////////////////////////////////////////////////////// // matches.hpp // // 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 #include #include #include #include #include namespace mpl = boost::mpl; namespace proto = boost::proto; namespace fusion = boost::fusion; struct int_convertible { int_convertible() {} operator int() const { return 0; } }; struct Input : proto::or_< proto::shift_right< proto::terminal< std::istream & >, proto::_ > , proto::shift_right< Input, proto::_ > > {}; struct Output : proto::or_< proto::shift_left< proto::terminal< std::ostream & >, proto::_ > , proto::shift_left< Output, proto::_ > > {}; proto::terminal< std::istream & >::type const cin_ = {std::cin}; proto::terminal< std::ostream & >::type const cout_ = {std::cout}; struct Anything : proto::or_< proto::terminal , proto::nary_expr > > {}; void a_function() {} struct MyCases { template struct case_ : proto::not_ {}; }; template<> struct MyCases::case_ : proto::_ {}; template<> struct MyCases::case_ : proto::_ {}; enum binary_representation_enum { magnitude , two_complement }; typedef mpl::integral_c magnitude_c; typedef mpl::integral_c two_complement_c; template struct number {}; struct NumberGrammar : proto::or_ < proto::terminal > , proto::terminal > > {}; struct my_terminal {}; template struct a_template {}; template struct my_expr; struct my_domain : proto::domain > {}; template struct my_expr { BOOST_PROTO_BASIC_EXTENDS(Expr, my_expr, my_domain) }; void test_matches() { proto::assert_matches< proto::_ >( proto::lit(1) ); proto::assert_matches< proto::_ >( proto::as_child(1) ); proto::assert_matches< proto::_ >( proto::as_expr(1) ); proto::assert_matches< proto::terminal >( proto::lit(1) ); proto::assert_matches< proto::terminal >( proto::as_child(1) ); proto::assert_matches< proto::terminal >( proto::as_expr(1) ); proto::assert_matches_not< proto::terminal >( proto::lit('a') ); proto::assert_matches_not< proto::terminal >( proto::as_child('a') ); proto::assert_matches_not< proto::terminal >( proto::as_expr('a') ); proto::assert_matches< proto::terminal > >( proto::lit('a') ); proto::assert_matches< proto::terminal > >( proto::as_child('a') ); proto::assert_matches< proto::terminal > >( proto::as_expr('a') ); proto::assert_matches_not< proto::terminal >( proto::lit((int_convertible())) ); proto::assert_matches_not< proto::terminal >( proto::as_child((int_convertible())) ); proto::assert_matches_not< proto::terminal >( proto::as_expr((int_convertible())) ); proto::assert_matches< proto::terminal > >( proto::lit((int_convertible())) ); proto::assert_matches< proto::terminal > >( proto::as_child((int_convertible())) ); proto::assert_matches< proto::terminal > >( proto::as_expr((int_convertible())) ); proto::assert_matches< proto::if_() > >( proto::lit(1) ); proto::assert_matches_not< proto::if_() > >( proto::lit('a') ); proto::assert_matches< proto::and_< proto::terminal , proto::if_() > > >( proto::lit(1) ); proto::assert_matches_not< proto::and_< proto::terminal , proto::if_() > > >( proto::lit('a') ); proto::assert_matches< proto::terminal >( proto::lit("hello") ); proto::assert_matches< proto::terminal >( proto::as_child("hello") ); proto::assert_matches< proto::terminal >( proto::as_expr("hello") ); proto::assert_matches< proto::terminal >( proto::lit("hello") ); proto::assert_matches< proto::terminal >( proto::as_child("hello") ); proto::assert_matches< proto::terminal >( proto::as_expr("hello") ); proto::assert_matches< proto::terminal >( proto::lit("hello") ); proto::assert_matches< proto::terminal >( proto::as_child("hello") ); proto::assert_matches< proto::terminal >( proto::as_expr("hello") ); proto::assert_matches< proto::terminal >( proto::lit("hello") ); proto::assert_matches< proto::terminal >( proto::as_child("hello") ); proto::assert_matches< proto::terminal >( proto::as_expr("hello") ); proto::assert_matches< proto::terminal >( proto::lit("hello") ); proto::assert_matches< proto::terminal >( proto::as_child("hello") ); proto::assert_matches< proto::terminal >( proto::as_expr("hello") ); proto::assert_matches< proto::terminal >( proto::lit(L"hello") ); proto::assert_matches< proto::terminal >( proto::as_child(L"hello") ); proto::assert_matches< proto::terminal >( proto::as_expr(L"hello") ); proto::assert_matches< proto::terminal >( proto::lit(L"hello") ); proto::assert_matches< proto::terminal >( proto::as_child(L"hello") ); proto::assert_matches< proto::terminal >( proto::as_expr(L"hello") ); proto::assert_matches_not< proto::if_()> >( proto::lit("hello") ); proto::assert_matches< proto::terminal >( proto::lit(std::string("hello")) ); proto::assert_matches< proto::terminal >( proto::as_child(std::string("hello")) ); proto::assert_matches< proto::terminal >( proto::as_expr(std::string("hello")) ); proto::assert_matches< proto::terminal > >( proto::lit(std::string("hello")) ); proto::assert_matches< proto::terminal > >( proto::as_child(std::string("hello")) ); proto::assert_matches< proto::terminal > >( proto::as_expr(std::string("hello")) ); proto::assert_matches_not< proto::terminal > >( proto::lit(1) ); proto::assert_matches_not< proto::terminal > >( proto::as_child(1) ); proto::assert_matches_not< proto::terminal > >( proto::as_expr(1) ); proto::assert_matches_not< proto::terminal > >( proto::lit(1) ); proto::assert_matches_not< proto::terminal > >( proto::as_child(1) ); proto::assert_matches_not< proto::terminal > >( proto::as_expr(1) ); #if BOOST_WORKAROUND(__HP_aCC, BOOST_TESTED_AT(61700)) typedef std::string const const_string; #else typedef std::string const_string; #endif proto::assert_matches< proto::terminal const & > >( proto::lit(const_string("hello")) ); proto::assert_matches< proto::terminal const & > >( proto::as_child(const_string("hello")) ); proto::assert_matches_not< proto::terminal const & > >( proto::as_expr(const_string("hello")) ); proto::assert_matches< proto::terminal< void(&)() > >( proto::lit(a_function) ); proto::assert_matches< proto::terminal< void(&)() > >( proto::as_child(a_function) ); proto::assert_matches< proto::terminal< void(&)() > >( proto::as_expr(a_function) ); proto::assert_matches_not< proto::terminal< void(*)() > >( proto::lit(a_function) ); proto::assert_matches_not< proto::terminal< void(*)() > >( proto::as_child(a_function) ); proto::assert_matches_not< proto::terminal< void(*)() > >( proto::as_expr(a_function) ); proto::assert_matches< proto::terminal< proto::convertible_to > >( proto::lit(a_function) ); proto::assert_matches< proto::terminal< proto::convertible_to > >( proto::as_child(a_function) ); proto::assert_matches< proto::terminal< proto::convertible_to > >( proto::as_expr(a_function) ); proto::assert_matches< proto::terminal< void(*)() > >( proto::lit(&a_function) ); proto::assert_matches< proto::terminal< void(*)() > >( proto::as_child(&a_function) ); proto::assert_matches< proto::terminal< void(*)() > >( proto::as_expr(&a_function) ); proto::assert_matches< proto::terminal< void(* const &)() > >( proto::lit(&a_function) ); proto::assert_matches< proto::terminal< void(* const &)() > >( proto::as_child(&a_function) ); proto::assert_matches_not< proto::terminal< void(* const &)() > >( proto::as_expr(&a_function) ); proto::assert_matches< proto::or_< proto::if_() > , proto::if_() > > >( proto::lit(1) ); proto::assert_matches_not< proto::or_< proto::if_() > , proto::if_() > > >( proto::lit(1u) ); proto::assert_matches< Input >( cin_ >> 1 >> 2 >> 3 ); proto::assert_matches_not< Output >( cin_ >> 1 >> 2 >> 3 ); proto::assert_matches< Output >( cout_ << 1 << 2 << 3 ); proto::assert_matches_not< Input >( cout_ << 1 << 2 << 3 ); proto::assert_matches< proto::function< proto::terminal, proto::vararg< proto::terminal > > >( proto::lit(1)('a','b','c','d') ); proto::assert_matches_not< proto::function< proto::terminal, proto::vararg< proto::terminal > > >( proto::lit(1)('a','b','c',"d") ); proto::assert_matches< Anything >( cout_ << 1 << +proto::lit('a') << proto::lit(1)('a','b','c',"d") ); proto::assert_matches< proto::switch_ >( proto::lit(1) >> 'a' ); proto::assert_matches< proto::switch_ >( proto::lit(1) + 'a' ); proto::assert_matches_not< proto::switch_ >( proto::lit(1) << 'a' ); number num; proto::assert_matches(proto::as_expr(num)); // check custom terminal types { proto::nullary_expr::type i = {0}; proto::assert_matches >( i ); proto::assert_matches_not >( i ); proto::terminal::type j = {0}; proto::assert_matches >( j ); proto::assert_matches_not >( j ); proto::assert_matches >( i ); } // check 0 and 1 arg forms or or_ and and_ { proto::assert_matches< proto::and_<> >( proto::lit(1) ); proto::assert_matches_not< proto::or_<> >( proto::lit(1) ); proto::assert_matches< proto::and_ > >( proto::lit(1) ); proto::assert_matches< proto::or_ > >( proto::lit(1) ); } // Test lambda matches with arrays, a corner case that had // a bug that was reported by Antoine de Maricourt on boost@lists.boost.org { a_template a; proto::assert_matches< proto::terminal< a_template > >( proto::lit(a) ); } // Test that the actual derived expression type makes it through to proto::if_ { my_expr::type> e = {{1}}; proto::assert_matches< proto::if_, my_domain>()> >( e ); } } 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::matches<>"); test->add(BOOST_TEST_CASE(&test_matches)); return test; }