Boost logo

Boost :

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


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