[proto] switch_ with a policy

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

troy d. straszheim wrote:
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 <snip>
First, I agree that switch_ could be made more general, but I am not overjoyed with the extra policy you suggest. Not sure why yet, just a vague Ick. I'll think about it. There is a deeper problem, which is that the matching primitives form a closed set. There is no way to define your own matching primitives (like switch_) and have proto::matches<> use it. There should be. To solve your immediate problem, I suggest you define exp and log to be actual function templates instead of proto terminals, as follows (untested): template<class T> typename proto::result_of::make_expr< exp_tag, T const &
::type exp(T const &t) { return proto::make_expr<exp_tag>(proto::ref(t)); }
Now you can use the stock proto::switch_ because all your functions will create expressions with unique tag types. There have also been some recent performance benchmarks that show this approach (function templates vs. proto terminals) to be much faster at compile-time. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler a écrit :
There have also been some recent performance benchmarks that show this approach (function templates vs. proto terminals) to be much faster at compile-time. Speaking of which, did you pass proto to Stefen Watanabe's template instance counter ? I'll be glad to do some investigation to make proto faster and wanted to know if this simple test was done.
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

Joel Falcou wrote:
Eric Niebler a écrit :
There have also been some recent performance benchmarks that show this approach (function templates vs. proto terminals) to be much faster at compile-time.
Speaking of which, did you pass proto to Stefen Watanabe's template instance counter ? I'll be glad to do some investigation to make proto faster and wanted to know if this simple test was done.
I has not been done. Be my guest! I'm sure there's a lot of low-hanging fruit there ... this tool wasn't available when I was developing proto. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler a écrit :
I has not been done. Be my guest! I'm sure there's a lot of low-hanging fruit there ... this tool wasn't available when I was developing proto. I'll give a shot. main problem is to identify compilable scenarii that makes sense. I think I'll start small with the proto example folder and move to my large code.
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35
participants (3)
-
Eric Niebler
-
Joel Falcou
-
troy d. straszheim