|
Boost : |
Subject: Re: [boost] Formal Review Request: TypeErasure
From: Hite, Christopher (Christopher.Hite_at_[hidden])
Date: 2012-06-18 11:39:35
Dave Abrahams wrote:
> > I completely agree with using functors for simple interfaces.
> By "functors" do you mean runtime-polymorphic function objects?
Not sure they're polymorphic (as in fusion polymorphic - taking different parameters). Is there a shorter term "[const?] callable (with a particular signature) and copyable."?
http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/ReadHandler.html
"Deferred Callable Object"
http://www.boost.org/doc/libs/1_49_0/libs/fusion/doc/html/fusion/functional/concepts/def_callable.html
> > 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);
> > ...
> > };
> If it's not movable/copyable it has already failed the test. The idea is to construct a world of values, and this is not one.
What "test"? You mean for any. Well you could use any<...,_self&> with it. I'm going to assume your "idea" is meant generally for all/most C++.
Let's just say you've got to write a little monster like the one above. It's got threads, io_service, mutexes, signal2, containers, sockets, etc inside it that don't like being moved/copied and don't need to be. What would you do Dave?
Would you prefer to put all of monster's guts in a shared_ptr-ed pimple so monster can be copied?
This is an honest question. I may be a couple steps behind on best practices of C++. I'd probably give the user of monster an object he can't move/copy. Is that generally bad? Do you think all objects be copy/movable?
Here's a point asio::sockets moveable but not copyable to maintain 1:1 relationship with external resources.
http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/basic_stream_socket/basic_stream_socket.html
If a user tries to copy a socket, he probably doesn't really want the fd copied.
> > 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?
> Didn't we say this was about new code? If you've got legacy stuff like this you do what you have to do.
This scenario could happen to you in the future. How would you write monster? At a later point how would you achieve polymorphism of two impls of monster?
> > 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.
> I don't understand what point you're trying to make.
I'm trying to figure out if you prefer extremely functionally oriented code. Why expose member functions at all? We could just give the user a collection of free type-deleted functors.
For any copyable object I could take all the member functions, bind them with the object, type-delete and return them in a tuple or a fusion::map with name tags.
The user can then take any subset of those functions to be an interface.
I think Haskall programmers think like this:
http://www.haskell.org/haskellwiki/OOP_vs_type_classes#Packing_data_.26_functions_together:_use_.28records_of.29_closures
Seeing as how C++11 has gotten functional with lambda expressions and perfect function forwarding, maybe I need to go check out Haskell.
Chris
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk