Subject: [boost] [TypeErasure] Composing Concepts & some notes
From: Fabio Fracassi (f.fracassi_at_[hidden])
Date: 2012-07-19 18:35:46


Hi Steven,

I am going through the documentation and simultaneously try out some
things that weren't immediately obvious to me. When I came to the
paragraph about composing concepts the last sentence "We can even
specialize concept_interface for it." tripped me up. My thought was "but
do I have to? and how do composed concepts interact with manually
composed any's?" so I gave it a try:

I used your push_back concept and defined a size concept like this:

template<class C>
struct size {
    static size_t apply(C& cont) { return cont.size(); }
};

namespace boost {
    namespace type_erasure {
       template<class C, class Base>
       struct concept_interface< ::size<C>, Base, C> : Base {
          size_t size() { return call(::size<C>(), *this); }
       };
    }
}

which works fine:
    std::vector<int> vec;

    typedef any<push_back<_self, int>, _self&> any_push_back;
    any_push_back pb(vec);
       pb.push_back(10);
       pb.push_back(2);

    typedef any<size<_self>, _self&> any_size;
    any_size s(vec);
    std::cout << "Size = " << s.size() << std::endl;

Now I wanted to try composition first manually:
    typedef
    any< mpl::vector<
             push_back<_self, int>,
             size<_self>
>,
         _self&
>
    any_manual_vecconcept;

    any_manual_vecconcept alvec(vec);

    alvec.push_back(13);
    alvec.push_back(11);
    std::cout << "Size = " << alvec.size() << std::endl;
and then via "named composition":

template<class T, class C>
struct vecconcept :
    mpl::vector<
       push_back<T, C>,
       size<T>
>
{};

    typedef any<vecconcept<_self, int>, _self&> any_vecconcept;
    any_vecconcept acvec(vec);
       acvec.push_back(15);
       acvec.push_back(17);
    std::cout << "Size = " << acvec.size() << std::endl;

great everything works as expected, and no, I did not have to define a
concept_interface for the composite interface. Now the first question is
why would I want to?

now the main reason for the exercise was how do these interact with each
other and while I am at it how do they interact with the concepts they
are composed of? Well I can freely interact as I hoped:

    any_vecconcept acvec2(alvec);
    any_manual_vecconcept alvec2(acvec);

    any_push_back pb3(alvec);
    any_push_back pb4(acvec);

    any_size s2(alvec);
    any_size s3(acvec);

This is great! I might have missed it in the documentation, but I think
this is really an important feature that deserves special mention.

Now I gather that there is no way to do the opposite, something along
the lines of
any_vecconcept acvec3 = dynamic_any_cast<any_vecconcept>(s3);
Well over the next days I will dive a bit deeper into the internals to
see if implementing such a feature would be feasible. (because I need it
before I could replace my current solution with type erasure)

Steven, let me finish by saying thank you for the great work.

regards

Fabio