Boost logo

Boost :

Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
From: Fabio Fracassi (f.fracassi_at_[hidden])
Date: 2012-07-30 02:30:50


On 7/30/12 2:27 AM, Steven Watanabe wrote:
> If you have an abstract base for your legacy interface,
> you can do this:
>
> template<class T = _self>
> struct legacy_concept : mpl::vector<...> {};
>
> namespace boost { namespace type_erasure {
>
> template<class T, class Base>
> struct concept_interface<legacy_concept<T>, Base, T>
> : Base, legacy_base {
> // implement legacy_base methods
> };
>
> }}
>
> Now any<legacy_concept<> > is derived from legacy_base.
>
> Of course, once you've written all this out, you don't
> gain much over just using:
>
> template<class T>
> struct legacy_adapter : legacy_base {
> // constructors and forwarding
> T impl_;
> };
>
> which is probably easier to understand.
> The only thing you gain is the ability
> to compose with other concepts.

Which is a quite significant win imo.

>
>> b.2. I cannot define a concept that has more than one function directly,
>> i.e. I have to define concepts for push_back and size and then compose
>> them (in this case 35 lines of code). This is of course mainly an issue
>> of syntactic sugar, but in Stevens concept definition boiler plate and
>> interface information (member name, arguments, composition lists) are
>> intermixed.
>>
>> I seem to recall that there was some discussion about having some macros
>> to simplify the boilerplate. I think something along the lines of
>>
>> BOOST_CREATE_CONCEPT(container_concept, typename T,
>> (void (push_back, T),
>> void (size))
>> )
>>
>> wouldn't be too bad.
>>
>
> I rather dislike complex macros like this.
>

I am non to fond of them either. In this case though it makes the code
much cleaner, consider a syntax like above or similar (haven't checked
whether this is even possible, my PP foo is not to good) to this:

BOOST_CREATE_CONCEPT(push_back, typename T,
      MEMBER push_back (void (T))
)

concisely gives you all the information (concept name, member func name
and signature) a user of this concept needs. In contrast to spelling it out

template<class C, class T> // < Part I of the signature
struct push_back { // < Concept name here
    static void apply(C& cont, const T& arg) { cont.push_back(arg); }
        // the rest of the signature is hidden somewhere in the apply
         // but never explicitly spelled out
};

namespace boost {
    namespace type_erasure {

       // lots of duplicated information and unrelated details to
       // (mis)understand and get wrong
       template<class C, class T, class Base>
       struct concept_interface< ::push_back<C, T>, Base, C> : Base {
          void push_back(typename rebind_any<Base, const T&>::type arg)
     {
             call(::push_back<C, T>(), *this, arg);
          }
       };
    }
}

Writing this is not to onerous, but (quickly) reading code that uses it ...

regards

Fabio


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