
On 9/30/07, Marco Costalba <mcostalba@gmail.com> wrote:
On 9/30/07, Dean Michael Berris <mikhailberis@gmail.com> wrote:
is not clear to me when and where this invokers are called given that dispatcher::operator[] returns a function object reference. Or perhaps I misread.
Can you refer to which page in the documentation you see that?
If you mean the above example is in: dispatcher-0.2/libs/dispatcher/doc/index.html
Ah, this documentation is I think a bit dated -- and is one of the earlier attempts at defining what the dispatcher is supposed to look like. Please refer to the generated documentation in dispatcher-0.2/libs/dispatcher/doc/html/index.html -- at least it's prettier, and is more hierarchically coherent (or so i think. ;) ).
The immediate "top of my head" implementation would be to do a linear inheritance of the different Functor objects that support different signatures to represent a multi-signature Functor wrappers.
--------- cut ---------------
void foo(double d) ; void bar(string s) ; void fizz(int i) ;
multi_index_dispatcher d; d[0] = foo; // valid, will register the void(double) d[0] = bar; // valid, will register the void(string) d[0] = fizz; // valid, will register the void(int)
Also Dispatcher::operator=() should be 'stacked' in some way though...but how?
Remember that operator=() can be implemented as part of the class -- and it can be overloaded much like the other operators. That means: Functor<void(int)> has: Functor<void(int)> & operator=(boost::function<void(int)> const & function) { this->_wrapped_function = function; return *this; }; Function<void(double)> has: Functor<void(double)> & operator=(boost::function<void(double)> const & function) { this->_wrapped_function = function; return *this; }; And since it's linear inheritance, the derived type (or at least the one in the end of the inheritance hierarchy) will inherit all these overloads to operator=() which will enable the compiler to choose at compile time which overload it's going to use depending on what's on the right hand side of the operator=().
d[0](1.0); // valid, will call the void(double) d[0](1); // valid, will call the void(int) d[0]("1"); // valid, will call the void(string)
This might also be achievable with an encapsulated Fusion map instead of linear inheritance, but I'm not entirely sure about being able to generate the appropriate type-safe operator() overloads in that manner.
Perhaps if the key of the map is the function signature could be possible first find a match with the supplied arguments and then call the operator(), should be safe in that case. A (big) downside is that you forget implicit conversions this way.
This is one problem with the Fusion map approach, but something I perceive as really a non-issue -- because after all, the goal of the library is to provide a type-safe way of implementing a dispatcher. However, I find that your requirement for implicit type conversion is something I particularly don't find very compelling since I'd rather have at compile time (or statically) know that I'm performing a conversion -- with static_cast<> or copy construction -- instead of the compiler doing it for me. I think allowing for implicit conversions is very dangerous and contrary to the notion of type-safety -- but don't let that stop you from implementing it and making it a design goal. It's just how I see it, which you can safely ignore. :)
Thank you for the interest, and I definitely hope the above explanation helps. :)
Helped a lot.
I'm glad it helped. :)
Thanks Marco
You're welcome. :) -- Dean Michael C. Berris Software Engineer, Friendster, Inc. [http://cplusplus-soup.blogspot.com/] [mikhailberis@gmail.com] [+63 928 7291459] [+1 408 4049523]