(Public response to Maurizio's private follow-up. Hope Maurizio doesn't mind.) Maurizio Vitale wrote:
"Eric" == Eric Niebler
writes: Eric> Maurizio Vitale wrote: >> Hi Eric, while you were on vacation I posted the following on the >> boost.users Eric> <snip>
Eric> Sorry for the delay; I missed your original message. I've Eric> followed up on the boost-users list. In short: I don't Eric> understand enough of what you're trying to do to help. Please Eric> clarify and I'll help as best I can.
Let me try to rephrase what I was trying to ask and see if I'm more successful.
The gist of the question is what happens when you have to add an operator= to a proto extended expression. You normally wouldn't because in general it doesn't make much sense to do things like:
a+b = c-d;
(although it could make sense in a DSL for linear algebra) In my case something like:
(a,b,c) = expression;
would require to do (inside my_expr::operator=): a = f (expression); b = g (expression); c = h (expression);
where f,g,h depend on the semantics. In my case they would carve a certain number of bits from expression. In a DSL dealing with tuples they would select the appropriate component from expression.
OK sure, that makes sense.
The problem I'm having is that expressions built by proto seem to be const, forcing operator= to be const (or at least that's what happens in my example).
It's true, Proto's objects have a top-level const qualification. They are, after all, rvalues (temporaries) so they should not be modified. HOWEVER, the const-ness only applies at the top-level. The const-ness of child nodes is preserved. In particular, non-const lvalue terminals are held by reference and remain non-const. Consider: typedef proto::terminal<int>::type I; I i = {42}; I & refi = proto::left(i+i); The temporary object created by i+i is const, but each i is held by non-const reference, which is what is returned by proto::left.
If that's true, then my followup question was whether it is ok to perform the assignment the way I was doing it, casting away const.
In short, it shouldn't be necessary. You're using proto::flatten and fusion::fold. Somewhere in there the constness is getting messed up. You should file a bug. Proto's fold_tree transform gets the constness correct. See the attached code which is equivalent to yours, but doesn't require any ugly const_cast's.
The other question I had was on what was the reason for explicitely disable assignment operators in grammars. This is something you do in many of your examples
I do? Which examples? I don't see it.
, but doesn't seem to make a difference in my code (e.g. having an operator= in my expression seems to stop proto from building a larger tree including the '=' anyhow, without needing to disable it explicitly)
I'm afraid you've lost me again.
The last question, which was the first, it is not very important. What I'm really interesting in is how to use proto when you need to assign to a proto expression, rather than a proto terminal.
And I hope at least that much has been cleared up.
HTH,
--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
#include <iostream>
#include
{};
template<typename Expr>
struct my_expr;
struct my_domain : proto::domain