Boost logo

Boost :

Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2012-07-29 20:27:00


AMDG

On 07/29/2012 12:28 PM, Fabio Fracassi wrote:
>
> b. creating custom concepts/concept interfaces.
>
> Consider this paragraph as dreaming out loud. I like the way Steven
> solved the problem of defining concepts but I still like it to be
> easier, because I believe that how easy it is to define concepts is the
> key to widespread adoption.
> Ideally it should not be more complex to define a concept than to define
> a (virtual) interface. My ideal solution would be able to do this:
>
> struct int_container_concept {
> //...
> void push_back(int) = 0;
> size_t size() = 0; // b.2
> //...
> };
>
> void legacy_func(int_container_concept& c); // b.1
>
> BOOST_CREATE_CONCEPT(int_container_concept);
>
> void test()
> std::vector<int> v = /*filles somehow*/;
> any<int_container_concept> con = v;
>
> legacy_func(con);
> }
>
> I know that it is impossible to implement the BOOST_CREATE_CONCEPT macro
> in the above example without language support. So until we get compile
> time reflection in c++ we need to live with the additional boilerplate
> in some way.
> In the "Design" section Steven explains that to scrap the boilerplate he
> departed from defining the user facing interface using abstract classes.
> My concern with this departure is that it is quite different, and not
> directly compatible.
> There are two things type erasures concepts cannot do:
>
> b.1. I cannot use a concept without using any<>. (i.e. the legacy_func
> marked above would need to take an any<int_container_concept>& instead)
> This might be a deal-breaker for some users of the library.
>

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.

> 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.

In Christ,
Steven Watanabe


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