|
Boost : |
Subject: Re: [boost] [fusion] Trouble using BOOST_FUSION_ADAPT_ADT with boost::fusion::operator<
From: Nathan Ridge (zeratul976_at_[hidden])
Date: 2012-05-15 22:44:49
> >>>>> I'm attempting to adapt a third-party struct into a fusion sequence
> >>>>> using BOOST_FUSION_ADAPT_ADT to get access to a nice operator<.
> >>>>> Unfortunately compilation fails and I'm not sure if it's a bug or me
> >>>>> using the library incorrectly. As best I can read the error message, it
> >>>>> looks like the code is attempting to compare adt_attribute_proxy structs
> >>>>> instead of the values represented by these. Below is some code that
> >>>>> demonstrates the problem. Can anybody help me out?
> >>>>>
> >>>>
> >>>> You've bumped into a limitation of proxies. Fusion adapted ADTs do
> >>>> not have access to the actual L-values of the class members, but only
> >>>> through get and set. As such, it actually exposes proxy elements
> >>>> (adt_attribute_proxy) instead of the actual elements. The only thing
> >>>> you can do with these proxies is either to get the values or set the
> >>>> values:
> >>>
> >>> Can't Fusion provide overloads for relational operators that compare
> >>> adt_attribute_proxy objects by comparing their values?
> >>
> >> Yes, that is a reasonable solution. I'd welcome a patch if anyone
> >> wants to add such operators. I'm a bit worried about the behavior
> >> of such operators, however. It needs to deduce the return types of
> >> the actual (non-proxy) overloads. It can be done, but is rather
> >> tricky without C++11.
> >
> > A slightly different idea: rather than provide relational operators
> > for adt_attribute_proxy itself, add support for it to the relational
> > opperators of Fusion sequences.
> >
> [...]
> >
> > Now the relational operators will work for ADT sequences themselves.
> > The user will still have to call get() explicitly when comparing
> > individual elements of the ADT sequences, but that should be rare.
> >
> > What do you think of this approach? It does not seem to require
> > deducing the type of anything.
> >
> > If you're interested I can try this out and submit a patch.
>
> Clever! I like it. We can probably put the customization points
> (e.g. call_on_values <but better names please>) in the lower level
> "support" module in "extension" namespace. Then the "adapted"
> module can simply specialize the CPs for adt_attribute_proxy.
>
> Yeah, nice idea!
I implemented a slight variation of this that's a bit more general.
I added a new function extension::as_readonly() in the support module,
which unwraps wrappers like adt_attribute_proxy to get at the underlying
value. The main template is just the identity function, but the
adapted/adt module overloads it for adt_attribute_proxy to return
proxy.get().
I then changed the implementations of the relational operators to wrap
accesses to the sequence elements in as_readonly() before comparing.
There may be other parts of the library where it's useful to wrap
readonly accesses of sequence elements in as_readonly() - this
mechanism can be re-used in those parts.
Users can also overload/specialize as_readonly() for their own wrapper
classes if they find it convenient.
Patch attached. Tests pass with patch.
(If you have a better idea for the name of this function that
'as_readonly', I am happy to change it.)
Regards,
Nate
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk