
In some situations you're limited by the fact that proto::switch_ matches on tag type. For instance, if you have a bunch of these things: namespace tag { struct exp {}; struct log {}; // lots more, say 50 of them } Expression<terminal<tag::exp>::type> const exp = {{}}; Expression<terminal<tag::log>::type> const log = {{}}; // 50 more And you try to write a transform with switch_ that handles theses, you're stymied by the fact that switch_ will only tell you the tag of what has matched. Here's an attempt at the switch: struct UnaryFunctionCases { template <typename Tag, int i=0> struct case_ : not_<_> { }; template <int i> struct case_<VEY, i> : when<proto::function<...>, DoSomethingClever(...)> { }; }; struct UnaryFunctionSwitch : proto::switch_<UnaryFunctionCases> { }; the VEY above is going to be proto::tag::function for all of these terminals if you're trying to transform an expression like exp(7); (If I remember correctly... I havent looked at this code in a while). You can add a policy to the stock switch_ that makes this easy to handle (sorry if my mailer borks some newlines here): namespace boost { namespace proto { template<typename Cases, template <class> class Policy = boost::proto::tag_of> struct switch_ : proto::transform<switch_<Cases, Policy> > { typedef switch_<Cases, Policy> proto_base_expr; template<typename Expr, typename State, typename Data> struct impl : Cases::template case_< typename Policy<Expr>::type >::template impl<Expr, State, Data> { }; template<typename Expr, typename State, typename Data> struct impl<Expr &, State, Data> : Cases::template case_< typename Policy<Expr>::type >::template impl<Expr &, State, Data> { }; }; namespace detail { template<typename Expr, typename Cases, template <class> class Policy> struct matches_<Expr, switch_<Cases, Policy> > : matches_< Expr , typename Cases::template case_< typename Policy<Expr>::type >::proto_base_expr > { }; } } } Which I believe behaves identically to the stock switch_, and you can handle the example scenario like this: namespace detail { // metafunction extracts the thing we want to match on template <typename Expr> struct fncall2fntag { typedef typename Expr::proto_child0 child0; typedef typename proto::result_of::value<child0>::type value; typedef typename boost::remove_reference<value>::type noref; typedef typename boost::remove_const<noref>::type noconst; typedef noconst type; }; } struct UnaryFunctionCases { template <typename Tag, int _=0> struct case_ : proto::not_<proto::_> { }; template <int _> struct case_<tag::exp,_> : proto::when< proto::function<proto::terminal<tag::exp>, Array>, UnaryFunctionDispatch(tag::exp(), ...) > { }; // etc }; struct UnaryFunctionSwitch : proto::switch_<UnaryFunctionCases, detail::fncall2fntag> { }; Thoughts? -t