Boost logo

Boost :

Subject: Re: [boost] Formal Review Request: TypeErasure
From: Hite, Christopher (Christopher.Hite_at_[hidden])
Date: 2012-06-15 10:36:50


Luke:
> A real example from an application I have worked on is that two object types inherit (eventually) from the same base type and each has an interface for a concept they have in common. Getting some attribute of the object. However, that interface isn't a method of the (common) base class and is declared differently for each of the two types. Epic fail. With TypeErasure you can declare an interface that accepts any object of either type and knows how to map the concept they have in common to the disparate interfaces of the various types without needing to fix the broken inheritance hierarchy, which is often not feasible due to the mass of legacy code that may depend upon it. While such a situation might seem contrived, I would say it is pretty typical of legacy C++.

The classic OOP pattern is delegation, which you definitely have to do if they're different (though any<> might translate int to double).
http://en.wikipedia.org/wiki/Delegation_pattern#C.2B.2B_example_.28complex.29

Any<> might solve the problem where you need a random subset of functions in two classes that you want to use for some interface. OOP says "shouldn't that concept have a name?"

Marying up two complex libraries is never easy.


Dave Abrahams wrote:
> Sure. For new code, it's reasonable to consider a value-based paradigm in lieu of legacy inheritance paradigms.
Dave I think generally if you personally were going to start a new project you'd try hard to avoid fat interfaces anyway. Can you picture yourself asking a user to implement an interface with a dozen methods on a object?

I completely agree with using functors for simple interfaces. There need to be good utilities to type-delete them.

Consider this big monster object with this interface. It's not movable/copyable (maybe it has its own threads). I think you'd find something like this acceptable.

        struct monster : noncopyable{
                typedef signal<void ()>::slot_type slot;

                connection subscribeA(slot);
                connection subscribeB(slot);
                connection subscribeC(slot);
                ...
        };

Now let's say for some reason we need run time polymorphism two impls of monster. I would propose making subscribe* virtual. Would you really do something different?

Would you do something like this?

        typedef function< connection (slot)> S;
        typedef tuple<S,S,S> deleted_monster;

        template<T>
        deleted_monster make_ deleted_monster (T&); // uses names ABC



I think the use case for value based interface for a fat interface doesn't come up much.

Chris


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