[proto] switch_ with a policy

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[proto] switch_ with a policy

troy d. straszheim
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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [proto] switch_ with a policy

Eric Niebler
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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [proto] switch_ with a policy

Joel Falcou-2
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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [proto] switch_ with a policy

Eric Niebler
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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [proto] switch_ with a policy

Joel Falcou-2
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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost