Boost logo

Boost :

Subject: Re: [boost] [fusion] [intro] ADAPT_STRUCT extensions
From: Christopher Schmidt (mr.chr.schmidt_at_[hidden])
Date: 2010-07-31 09:02:26


Joel de Guzman schrieb:
> On 7/30/2010 6:35 AM, Stefan Strasser wrote:
>> Zitat von Hartmut Kaiser <hartmut.kaiser_at_[hidden]>:
>>
>>>> 1)
>>>>
>>>> ADAPT_STRUCT can adapt public data members only.
>>>>
>>>> with the modifications I uploaded here:
>>>> http://svn.boost.org/svn/boost/sandbox/intro/boost/fusion/adapted/struct/
>>>>
>>>>
>>>> all data members can be adapted. for example:
>>>>
>>>> class A{
>>>> private:
>>>> friend class fusion::access;
>>>> int a;
>>>> };
>>>>
>>>> BOOST_FUSION_ADAPT_STRUCT(A,(int,a) )
>>>>
>>>> 2)
>>>>
>>>> adaption of a class including its base class members. for example:
>>>>
>>>> struct A{ int a; };
>>>> struct B{ int b; };
>>>> struct C : A,B{ int c; }
>>>>
>>>> BOOST_FUSION_ADAPT_STRUCT(A,(int,a) )
>>>> BOOST_FUSION_ADAPT_STRUCT(B,(int,b) )
>>>> BOOST_FUSION_ADAPT_DERIVED(
>>>> C, (A)(B),
>>>> (int,c)
>>>> )
>>>>
>>>> an instance of C is now a fusion sequence of size 3.
>>>> http://svn.boost.org/svn/boost/sandbox/intro/boost/fusion/adapted/struct/a
>>>>
>>>> dapt_derived.hpp
>>>>
>>>> private inheritance is supported as above, virtual inheritance is not.
>>>> I'm not sure if virtual inheritance can be supported.
>>>
>>> Have you seen the new BOOST_FUSION_ADAPT_CLASS() family of utilities
>>> which
>>> allow using (member-) functions instead of direct access to the data
>>> members
>>> of a class/struct?
>>
>> no I had not, I was using 1.41. where can I see those? can't seem to
>> find them in 1.43 or
>> the trunk.

The BOOST_FUSION_ADAPT_xxxCLASSxxx-macros are not documented yet. For
more information, refer to the code and the testcases:

https://svn.boost.org/trac/boost/browser/trunk/boost/fusion/adapted/class
https://svn.boost.org/trac/boost/browser/trunk/libs/fusion/test/sequence
https://svn.boost.org/trac/boost/browser/trunk/libs/fusion/test/sequence/adapt_class.cpp

>>
>> do these solve one of the two issues above?
>> in case you brought it up because then you could have public accessor
>> functions to private
>> members, I'd still propose to add a way to adapt private members as
>> shown above.
>> I'd like to use this for what is apparently known as the "scrap your
>> boilerplate" pattern
>> in the functional programming world (see the previous [intro]
>> discussion), which requires
>> adapting each member in every class used in such an algorithm. there
>> obviously shouldn't
>> be public accessors for all members.
>
> I like it! I think this patch provides solutions not yet available.
> You should coordinate with Christopher Schmidt, he did the new
> adapt class macros and figure out how to make it all fit and have
> a consistent interface.

I patched the code in the trunk to enable the adaption of private
attributes. The adaptee just needs to friend "struct
boost::fusion::extension::access". See changeset 64490
(https://svn.boost.org/trac/boost/changeset/64490) for details.

Regarding the second feature request: I am not in favor of adding yet
another set of BOOST_FUSION_ADAPT_xxx-macros. Altogether we got 6
documented and 4 undocumented macros to adapt structs, 10 undocumented
macros to adapt classes and another 4 macros to define structs.
Any new adaption family will multiply the macro count, disfigure the
common code base of the macros even more, bloat the documentation and
most likely will not raise the learning curve for developers.
I think, rather than introducing a new set of macros to adapt class
hierarchies, this specific usecase may be covered in a convenient way
using a composition of more primitive means.
In particular the segmented sequences might come in handy. Any class
hierarchy may be represented by a n-ary segmented fusion wrapper sequence.

struct A{int x;};
struct B{int y;};
struct C : A,B{int z;};
BOOST_FUSION_ADAPT_STRUCT(A, (int,x))
BOOST_FUSION_ADAPT_STRUCT(B, (int,y))
BOOST_FUSION_ADAPT_STRUCT(C, (int,z))

struct adapted_C : fusion::tree<C&, A&, B&>
{
        adapted_C(C& c) : fusion::tree<A&, B&, C&>(c,c,c){}
};

int main()
{
        C c;c.x=0;c.y=1;c.z=2;

        adapted_C adapted_c(c);
        std::cout << fusion::flatten(adapted_c) << std::endl;
}

To get native fusion support without a named wrapper, the tree-view may
be constructed inplace whenever an intrinsic sequence operation is
performed. Defining such functionality may be hidden behind a new macro.

struct A{int x;};
struct B{int y;};
struct C : A,B{int z;};
BOOST_FUSION_ADAPT_STRUCT(A, (int,x))
BOOST_FUSION_ADAPT_STRUCT(B, (int,y))
BOOST_FUSION_ADAPT_STRUCT_NAMED_NS(C, BOOST_PP_EMPTY(), C_adpt, (int,z))

typedef fusion::tree<C_adpt, A&, B&> tree_type;
BOOST_FUSION_ADAPT_INPLACE(
        //type to adapt
        C,
         //type to construct *inplace* whenever an intrinsic
        //sequence operation is performed
        tree_type,
        //initialization expression, with obj being C&, the instance of
        //C
        fusion::repeat<3>(fusion::single_view<C&>(obj)))
)

int main()
{
        C c;c.x=0;c.y=1;c.z=2;
        std::cout << fusion::flatten(c) << std::endl;
}

BOOST_FUSION_ADAPT_INPLACE is simple to implement - and it is just one
new, independent macro. If compiled using a recent optimizing compiler,
there will not be any runtime overhead at all.
Unfortunately the segmented sequences are undocumented and pretty much
broken at the moment. I will definitely work on them once I have time again.

I think, whenever compile-time is not mandatory, new facilities should
be aligned to the functional fundamental of Fusion that is: providing
independent, primitive means that can be used to compose new, more
expressive means.

Does that make sense?

-Christopher


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