Index: boost/proto/proto_fwd.hpp =================================================================== --- boost/proto/proto_fwd.hpp (revision 74374) +++ boost/proto/proto_fwd.hpp (working copy) @@ -269,6 +269,9 @@ using namespace tagns_; + template + struct tag_of; + //////////////////////////////////////////////////////////////////////////////////////////////// struct _; @@ -359,7 +362,7 @@ template > struct if_; - template + template() > struct switch_; template @@ -462,9 +465,6 @@ struct is_sub_domain_of; template - struct tag_of; - - template struct arity_of; template @@ -741,7 +741,7 @@ template struct pass_through; - template + template struct _default; struct _expr; Index: boost/proto/matches.hpp =================================================================== --- boost/proto/matches.hpp (revision 74374) +++ boost/proto/matches.hpp (working copy) @@ -10,6 +10,7 @@ #ifndef BOOST_PROTO_MATCHES_HPP_EAN_11_03_2006 #define BOOST_PROTO_MATCHES_HPP_EAN_11_03_2006 + #include #include #include @@ -402,14 +403,26 @@ {}; // handle proto::switch_ - template - struct matches_, switch_ > - : matches_< - Expr - , proto::basic_expr - , typename Cases::template case_::proto_grammar - > + template< typename Expr, typename Tag, typename Args, long Arity, typename Cases, typename Transform> + struct matches_ < Expr, proto::basic_expr, switch_ > + : matches_< Expr, proto::basic_expr + , typename Cases::template case_::template impl::result_type + >::proto_grammar + > { + typedef when<_,Transform> applicant; + typedef typename applicant::template impl::result_type selected_type; + typedef typename Cases::template case_ which; + }; + + template< typename Expr, typename Tag, typename Args, long Arity, typename Cases > + struct matches_ < Expr, proto::basic_expr , switch_ > + : matches_< Expr, proto::basic_expr + , typename Cases::template + case_::proto_grammar + > + { typedef typename Cases::template case_ which; }; } @@ -449,6 +462,9 @@ /// not match \c T. /// \li An expression \c E matches switch_\ if /// \c E matches C::case_\. + /// \li An expression \c E matches switch_\ if + /// the result type of the transform \c T on \c E matches + /// C::case_\::type\>. /// /// A terminal expression expr\ \> matches /// a grammar expr\ \> if \c BT is \c AT or @@ -784,26 +800,31 @@ /// When applying switch_\ as a transform with an /// expression \c e of type \c E, state \c s and data \c d, it is /// equivalent to C::case_\()(e, s, d). - template - struct switch_ : transform > + template + struct switch_ : transform< switch_ > { typedef switch_ proto_grammar; + typedef when<_,Transform> applicant; /// \param e An expression /// \param s The current state /// \param d A data of arbitrary type /// \pre matches\::value is \c true. /// \return which()(e, s, d), where which is - /// Cases::case_ + /// Cases::case_< typename boost::result_of< Transform(Expr) >::type > template struct impl - : Cases::template case_::template impl + : Cases::template + case_ < typename applicant::template impl::result_type + >::template impl {}; template struct impl - : Cases::template case_::template impl + : Cases::template + case_ ::result_type + >::template impl {}; }; @@ -901,8 +922,8 @@ /// INTERNAL ONLY /// - template - struct is_callable > + template + struct is_callable > : mpl::true_ {}; Index: libs/proto/test/new_switch.cpp =================================================================== --- libs/proto/test/new_switch.cpp (revision 0) +++ libs/proto/test/new_switch.cpp (revision 0) @@ -0,0 +1,94 @@ +/////////////////////////////////////////////////////////////////////////////// +// new_switch.cpp +// +// Copyright 2011 Eric Niebler +// Copyright Pierre Esterie & Joel Falcou. +// 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 + +using namespace boost; +using namespace proto; + +struct MyCases +{ + template + struct case_ + : proto::not_ + {}; +}; + +template<> +struct MyCases::case_ +: proto::_ +{}; + +template<> +struct MyCases::case_ +: proto::_ +{}; + +struct ArityOf; + +struct ArityOfCases +{ + template + struct case_ + : proto::not_ {}; +}; + + +template<> +struct ArityOfCases::case_< boost::mpl::long_<1> > +: boost::proto::when +{}; + +template<> +struct ArityOfCases::case_< boost::mpl::long_<2> > +: boost::proto::when +{}; + +struct ArityOf +: boost::proto::switch_ < ArityOfCases + , proto::arity_of() + > +{}; + +void test_switch() +{ + // Tests for backward compatibility + assert_matches< proto::switch_ >( lit(1) >> 'a' ); + assert_matches< proto::switch_ >( lit(1) + 'a' ); + assert_matches_not< proto::switch_ >( lit(1) << 'a' ); + + //Test new matching on the Transform result type + ArityOf ar; + + assert_matches_not< ArityOf >( lit(1) ); + assert_matches< ArityOf >( lit(1) + 2 ); + assert_matches< ArityOf >( !lit(1)); + BOOST_CHECK_EQUAL( ar( !lit(1) ), false); + BOOST_CHECK_EQUAL( ar( lit(1) + 2 ), true); +} + +using namespace unit_test; +/////////////////////////////////////////////////////////////////////////////// +// init_unit_test_suite +// +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite *test = BOOST_TEST_SUITE("test proto::switch_<>"); + + test->add(BOOST_TEST_CASE(&test_switch)); + + return test; +} + Index: libs/proto/test/Jamfile.v2 =================================================================== --- libs/proto/test/Jamfile.v2 (revision 74374) +++ libs/proto/test/Jamfile.v2 (working copy) @@ -31,6 +31,7 @@ [ run make_expr.cpp ] [ run matches.cpp ] [ run flatten.cpp ] + [ run new_switch.cpp ] [ run toy_spirit.cpp ] [ run toy_spirit2.cpp ] [ run make.cpp ] Index: libs/proto/doc/reference/matches.xml =================================================================== --- libs/proto/doc/reference/matches.xml (revision 74374) +++ libs/proto/doc/reference/matches.xml (working copy) @@ -1,4 +1,4 @@ - +
Contains definition of the @@ -427,10 +427,13 @@ - proto::transform<switch_<Cases> > - For matching one of a set of alternate grammars, which are looked up based on an - expression's tag type. When used as a transform, + proto::transform<switch_<Cases, Transform> > + For matching one of a set of alternate grammars, which are looked up based on + the result type of the transform passed in second template parameter. + If no transform is passed, the default one is proto::tag_of() + so the default matching is based on the expression's tag type. When used as a transform, proto::switch_<> applies the transform associated with the sub-grammar that matches the expression. @@ -439,6 +442,13 @@ proto::switch_<C> if E matches C::case_<E::proto_tag>. + + + An expression type E matches + proto::switch_<C,T> if + the result type of the transform T + on E matches + C::case_<boost::result_of<T(E)> >. When applying proto::switch_<C> as a transform @@ -446,6 +456,13 @@ E, state s and data d, it is equivalent to C::case_<E::proto_tag>()(e, s, d). + + + When applying proto::switch_<C,T> as a transform + with an expression e of type + E, state s and + data d, it is equivalent to + C::case_<boost::result_of<T(E)> >()(e, s, d). @@ -455,11 +472,16 @@ - Cases::template case_<typename Expr::tag_type>::template impl<Expr, State, Data> + Cases::template case_< typename applicant::template impl<Expr, State, Data>::result_type + >::template impl<Expr, State, Data> + switch_ + + when<_, Transform> +