Boost logo

Boost :

From: Joel de Guzman (joel_at_[hidden])
Date: 2003-11-06 19:18:32


Brian McNamara <lorgon_at_[hidden]> wrote:

> So, based on my understanding, it seems to me that the simplest fix is
> to change from my original idea of
[...]
> to this:
>
> template <class T>
> class match {
> optional<T> data;
> ...
> void value( T y ) {
> if( data )
> *data = y;
> else
> data = y;
> }
> };
>
> Basically value() says: if it isn't initialized yet, initialize it,
> otherwise just update its value. I am pretty sure this will now work
> with all of your test cases.
>
> This feels a little kludgy to me, but I think it is reflective of how
> the parsers are currently using the interface. Apparently non-reference
> parameters don't have to be originally initialized, but reference
> parameters do. We need the "special case" (the if-then-else) to deal
> with the possibility of non-reference types starting out in the
> "invalid" state.

Yes, I do something similar now. I'm not quite happy with it, but it's
not really a big deal. I guess this is the very reason why this thread
started. I was the one who suggested optional references a month ago.
While the iron is hot, perhaps it's a good time to make the semantics
better. I would really like this:

    template <typename U>
    void value(U const& y)
    {
        data = y;
    }

to apply generically to both optional<T> and optional<T&> following C++'s
value/reference semantics which seems the right thing to do, in my opinion,
still. IMO, you can always use a pointer if you want it to be rebind-able:

    optional<T*> o;
    o = p;

> An alternative solution, which may or may not be useful, would be to,
> somewhere in this logic:
>
>> d) eps' semantic action stores 123 into r's closure member val.
>> e) r is about to return with an invalid attribute
>> f) the closure 'decorator's post-parse function is called.
>> g) closure member val (with a value of 123) is places in the match<int>
>> h) r returns the match<int> with a value of 123
>
> wherever value() is being called, change it to a call to a different
> method named "initialize". Then value() could do
>
> *data = y;
>
> whereas initialize() could do
>
> data = y;
>
> The idea is that closures (or, at least, "something" on the parser
> interface end of things--see below) would re-initialize the data,
> rather than updating its value.

Well, that's not an option because it's a bit too late in the ballgame to
change Spirit's match interface now.

> It's unclear to me in this code
>
> r = epsilon_p[ r.val = 123 ];
>
> how r decided to return a match<int>; I presume it deduced it from
> "123", and it always deduces non-reference types when assigning to the
> "val" member?

No, int is the type of r's closure member val. It is an explicit (rather than
deduced) type.

> It seems to me that you could also have a way to bind
> references here; I dunno what the syntax should be, but you ought to be
> able to make it so that, for instance,
>
> r = epsilon_p[ r.refval = x ]; // x is some global variable

refval cannot be late bound. It will have to be passed as an inherited
attribute upon invocation of r:

    int x, y;

    r = epsilon_p[ r.refval = 333 ]; // sets x or y to 333 depending
                                        // on who called r (s or t)
    s = r(ref(x));
    t = r(ref(y));

> I don't know if that made much sense, and even if it did, I don't know
> if this capability would actually be useful in practice. But I just
> wanted to share the idea that, since "under the hood" there are two
> kinds of meanings for "assignment of reference types" (reset the
> reference, or update the value),

Makes sense. Well, I'm not really interested with the first meaning.
Yet, as you showed, there can be workarounds, if you want to have
the second meaning. However, the reverse can also be true. In any case,
I do not have a strong opinion anymore since I can adjust any other way.

> you could export both of these out to
> users. My guess is that, in practice, this is probably not very useful.
> In that case, I think I would just stick with the original solution I
> suggested above (where value() is implemented with an if-then-else
> statement).

or, change optional's behavior ;-)

Cheers,

-- 
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk