[Proto] Recreating an expression

Thanks Eric for your fast answer! Unfortunately, this doesn't solve my problem. To make a very very long discussion long, here a small example showing the problem from another side: I have an expression wrapper called mp_terminal and I define terminals, but not in the documented way (which I suspect is the problem) but instead deriving from them (for convenience purposes), for example: struct True : mp_terminal<typename proto::terminal<guard_tag>::type> {...} These terminals are used with a simple grammar: struct BuildGuards : proto::or_< proto::when< proto::logical_or<BuildGuards,BuildGuards >, GuardOR<BuildGuards(proto::_left),BuildGuards(proto::_right)>() >, proto::when< proto::logical_and<BuildGuards,BuildGuards >, GuardAND<BuildGuards(proto::_left),BuildGuards(proto::_right)>() >, proto::when< proto::logical_not<BuildGuards >, GuardNOT<BuildGuards(proto::_value)>() >, proto::when < proto::terminal<guard_tag>, proto::_()
{}; Then, expressions like: True()|| False() give the expected result (struct GuardOR<struct True,struct False>). Even True()&& (Dummy1() || !(False() || True())) give the expected result: struct GuardAND<struct True,struct GuardOR<struct Dummy1,struct GuardNOT<struct GuardOR<struct False,struct True> > > > But a "!" alone (meaning followed by just a terminal, not the other parts of the BuildGuards grammar) breaks all (as do all unary operators I tried), like !False() or True()|| !False(). !False() => struct GuardNOT<struct mp_terminal<struct boost::proto::exprns_::expr<struct boost::proto::tag::terminal,struct boost::proto::argsns_::term<struct guard_tag>,0> > > Notice that !(False() || True()) works! Now, if I do not derive from mp_terminal but instead proceed as documented, all works as expected: proto::terminal<True>::type True_; ... !False_ => correct result. Sadly, this documented usage is unpractical in my use case. So, supposing that I managed this easy grammar, I imagine that the usage I do of terminals (deriving from them) is not allowed. Then, why do most use cases work like a charm? Only unary operators seem to fail. Attached are 2 test files. V1 doesn't work in all cases while V2 does. I use 1.38. Thanks a lot! Christophe _________________________________________________________________ Windows Live™: Keep your life in sync. Check it out! http://windowslive.com/explore?ocid=TXT_TAGLM_WL_t1_allup_explore_012009

christophe henry wrote:
Thanks Eric for your fast answer! Unfortunately, this doesn't solve my problem. To make a very very long discussion long, here a small example showing the problem from another side: I have an expression wrapper called mp_terminal and I define terminals, but not in the documented way (which I suspect is the problem)
Indeed.
but instead deriving from them (for convenience purposes), for example: struct True : mp_terminal<typename proto::terminal<guard_tag>::type> {...}
<snip>
Then, why do most use cases work like a charm? Only unary operators seem to fail.
It's because (a) True is a Proto type, but hasn't been made so by directly using proto::extends, and (b) Proto's unary operators are being a little too nit-picky about (a). I have fixed (b) on trunk (changelist 54610). In the mean time, you can change your definition of True and False to use this formulation: struct True : proto::extends< mp_terminal<typename proto::terminal<guard_tag>::type> , True , sm_domain > or the simpler and more direct struct True : proto::extends< typename proto::terminal<guard_tag>::type , True , sm_domain > HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Here's a little extra feedback that I forgot include in my first reply. christophe henry wrote:
These terminals are used with a simple grammar: struct BuildGuards : proto::or_< proto::when< proto::logical_or<BuildGuards,BuildGuards >,
GuardOR<BuildGuards(proto::_left),BuildGuards(proto::_right)>() >, proto::when< proto::logical_and<BuildGuards,BuildGuards >,
GuardAND<BuildGuards(proto::_left),BuildGuards(proto::_right)>() >, proto::when< proto::logical_not<BuildGuards >, GuardNOT<BuildGuards(proto::_value)>()
Use proto::_child instead of proto::_value here. proto::_value returns the value of a terminal node. proto::_child returns the child of a unary expression tree node. It's really just luck that this is working for you.
>, proto::when < proto::terminal<guard_tag>, proto::_()
I would use proto::_ here instead of proto::_(). They mean the same thing, but proto::_ is more idiomatic. See the following section for an explanation of why proto::_ and proto::_() are equivalent when used as transforms: http://www.boost.org/doc/libs/1_39_0/doc/html/proto/users_guide.html#boost_p... -- Eric Niebler BoostPro Computing http://www.boostpro.com
participants (2)
-
christophe henry
-
Eric Niebler