Request for interest in a library to ease double dispatching

Hi, I have been tinkering on a template library to ease the use of double dispatching. Now I know there are other techniques such as visitor patterns that might solve this problem in a more general way. However I believe that there are occasions when using double dispatch is a good way forward. I have some excerpts of example code at the end of this mail. Of course if I somehow have missed a boost library that already handles this I would be happy to know about it. So if there is even any interest for this I would be happy if someone would like to cooperate with me to make this library better and in the end so good so that it can be part of boost. I feel I do not have the time to spare to finalize this on my own, plus I feel I still have things to learn and would be happy to cooperate with someone more experienced in template programming. What I in that case need help with is: *How (or is it) possible to make the library more transparent to the number of types that should be in the double dispatch hierarchy. Right now, as I have shown in the code at the end of this mail, you have to put a post-fix number telling how many types to use. *How (if possible) can a class be double dispatchable with different return types. The way I solved it was with a union. But would it somehow be possible to do like this struct Val : public DoubleDispatchable<bool,A,B>, public DoubleDispatchable<int,A,B> *What else would be needed to start the journey to make this a library fit for boost (is it even good enough to ever make into boost?) If anyone is interested in a cooperation I am happy to provide my working draft of this library and to have a more private talk about how we could move forward. Best Regards Per Karlström For now a union is used to hold the return value to make this simmilar for all types of returns. union ReturnVal { float float_type_m; bool bool_type_m; ReturnVal(const bool& bool_type_):bool_type_m(bool_type_){} ReturnVal(const float& float_type_):float_type_m(float_type_){} ReturnVal():bool_type_m(false){} }; In essence a library user can define handler classes akin to this: struct less : public DoubleDispatchHandler_3<ReturnVal,A,B,C> { return_type handle_alpha_alpha(const alpha_type& arg1, const alpha_type& arg2) const {return arg1 < arg2} return_type handle_alpha_beta (const alpha_type& arg1, const beta_type& arg2) const {return true;} return_type handle_alpha_gamma (const alpha_type& arg1, const gamma_type& arg2) const {return true;} //And all other combinations }; Or with a default function struct equal : public DoubleDispatchHandler_3<ReturnVal,A,B,C> { return_type handle_default() const {return false;} return_type handle_alpha_alpha(const alpha_type& arg1, const alpha_type& arg2) const; return_type handle_beta_beta (const beta_type& arg1, const beta_type& arg2) const; return_type handle_gamma_gamma (const gamma_type& arg1, const gamma_type& arg2) const; }; Then the base class is derived from DoubleDispatchable class Val : public DoubleDispatchable_3<ReturnVal,A,B,C> { public: virtual ~Val(){} virtual std::ostream& print(std::ostream& ost) const=0; virtual bool operator<(const Val& other) const =0; virtual bool operator==(const Val& other) const =0; virtual float combine(const Val& other) const =0; }; While Child classes had to define the member function dispatch_<type> struct A : public Val { int val_m; private: //Handles the first double dispatch call return_type dispatch_alpha(const alpha_type& alpha, const handler_type& handler) const { return double_dispatch(alpha,*this,handler); } return_type dispatch_beta(const beta_type& beta, const handler_type& handler) const { return double_dispatch(beta,*this,handler); } return_type dispatch_gamma(const gamma_type& gamma, const handler_type& handler) const { return double_dispatch(gamma,*this,handler); } public: A(const int& val_=0):val_m(val_){} //Normal calls to the operators via a template function bool operator<(const Val& other) const { return double_dispatch(*this,other,less()).bool_type_m; } bool operator==(const Val& other) const { return double_dispatch(*this,other,equal()).bool_type_m; } float combine(const Val& other) const { return double_dispatch(*this,other,add()).float_type_m; } std::ostream& print(std::ostream& ost) const { ost<<"A("<<val_m<<")"; return ost; } }; class B{...}; class C{...};

On 12/03/12 08:13, Per Karlström wrote:
Hi,
I have been tinkering on a template library to ease the use of double dispatching. Now I know there are other techniques such as visitor patterns that might solve this problem in a more general way. However I believe that there are occasions when using double dispatch is a good way forward. I have some excerpts of example code at the end of this mail.
Of course if I somehow have missed a boost library that already handles this I would be happy to know about it.
So if there is even any interest for this I would be happy if someone would like to cooperate with me to make this library better and in the end so good so that it can be part of boost. I feel I do not have the time to spare to finalize this on my own, plus I feel I still have things to learn and would be happy to cooperate with someone more experienced in template programming.
What I in that case need help with is:
*How (or is it) possible to make the library more transparent to the number of types that should be in the double dispatch hierarchy. Right now, as I have shown in the code at the end of this mail, you have to put a post-fix number telling how many types to use.
*How (if possible) can a class be double dispatchable with different return types. The way I solved it was with a union. But would it somehow be possible to do like this
struct Val : public DoubleDispatchable<bool,A,B>, public DoubleDispatchable<int,A,B>
*What else would be needed to start the journey to make this a library fit for boost (is it even good enough to ever make into boost?)
If anyone is interested in a cooperation I am happy to provide my working draft of this library and to have a more private talk about how we could move forward.
Best Regards Per Karlström
For now a union is used to hold the return value to make this simmilar for all types of returns. union ReturnVal { float float_type_m; bool bool_type_m;
ReturnVal(const bool& bool_type_):bool_type_m(bool_type_){} ReturnVal(const float& float_type_):float_type_m(float_type_){} ReturnVal():bool_type_m(false){} };
In essence a library user can define handler classes akin to this:
struct less : public DoubleDispatchHandler_3<ReturnVal,A,B,C> { return_type handle_alpha_alpha(const alpha_type& arg1, const alpha_type& arg2) const {return arg1 < arg2} return_type handle_alpha_beta (const alpha_type& arg1, const beta_type& arg2) const {return true;}
return_type handle_alpha_gamma (const alpha_type& arg1, const gamma_type& arg2) const {return true;}
//And all other combinations };
Or with a default function
struct equal : public DoubleDispatchHandler_3<ReturnVal,A,B,C> { return_type handle_default() const {return false;} return_type handle_alpha_alpha(const alpha_type& arg1, const alpha_type& arg2) const; return_type handle_beta_beta (const beta_type& arg1, const beta_type& arg2) const; return_type handle_gamma_gamma (const gamma_type& arg1, const gamma_type& arg2) const; };
Then the base class is derived from DoubleDispatchable
class Val : public DoubleDispatchable_3<ReturnVal,A,B,C> { public: virtual ~Val(){} virtual std::ostream& print(std::ostream& ost) const=0; virtual bool operator<(const Val& other) const =0; virtual bool operator==(const Val& other) const =0; virtual float combine(const Val& other) const =0; };
While Child classes had to define the member function dispatch_<type> struct A : public Val { int val_m; private: //Handles the first double dispatch call return_type dispatch_alpha(const alpha_type& alpha, const handler_type& handler) const { return double_dispatch(alpha,*this,handler); } return_type dispatch_beta(const beta_type& beta, const handler_type& handler) const { return double_dispatch(beta,*this,handler); } return_type dispatch_gamma(const gamma_type& gamma, const handler_type& handler) const { return double_dispatch(gamma,*this,handler); } public: A(const int& val_=0):val_m(val_){}
//Normal calls to the operators via a template function bool operator<(const Val& other) const { return double_dispatch(*this,other,less()).bool_type_m; }
bool operator==(const Val& other) const { return double_dispatch(*this,other,equal()).bool_type_m; }
float combine(const Val& other) const { return double_dispatch(*this,other,add()).float_type_m; }
std::ostream& print(std::ostream& ost) const { ost<<"A("<<val_m<<")"; return ost; } };
class B{...}; class C{...};
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
There's multiple dispatch code here: http://svn.boost.org/svn/boost/sandbox/variadic_templates/libs/composite_sto... The predator_prey.cpp uses virtual functions for dispatching. The one_of_multiple_dispatch.test.cpp uses either virtual functions or switches to do the dispatching. Unfortunately, I found the timing was pretty slow on the one_of_multiple_dispatch vs. the variant visitor :( HTH. -regards, Larry

On 12/03/12 11:40, Larry Evans wrote:
On 12/03/12 08:13, Per Karlström wrote: [snip]
I have been tinkering on a template library to ease the use of double dispatching. Now I know there are other techniques such as visitor patterns that might solve this problem in a more general way. However I believe that there are occasions when using double dispatch is a good way forward. I have some excerpts of example code at the end of this mail.
Of course if I somehow have missed a boost library that already handles this I would be happy to know about it. [snip]
There's multiple dispatch code here:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/libs/composite_sto...
The predator_prey.cpp uses virtual functions for dispatching. The one_of_multiple_dispatch.test.cpp uses either virtual functions or switches to do the dispatching.
Unfortunately, I found the timing was pretty slow on the one_of_multiple_dispatch vs. the variant visitor :(
I meant the compile times were slow. I didn't bother with runtimes. Also, I provided a switch implementation because others (in this NG, IIRC) have said that was faster than virtual functions for dispatching. Anyway, the timing results are attached for a clang compiler. The table shows the ratio of the times w.r.t. an implementation called CLOPTR, which was posted in the earlier post on boost.user: From: Paul <peebor@gmail.com> Newsgroups: gmane.comp.lib.boost.user Subject: Re: large variant performance compared (50 elements) Date: Thu, 27 Jan 2011 20:19:08 +0100 -regards, Larry

So if there is even any interest for this I would be happy if someone would like to cooperate with me to make this library better and in the end so good so that it can be part of boost. I feel I do not have the time to spare to finalize this on my own, plus I feel I still have things to learn and would be happy to cooperate with someone more experienced in template programming.
I have used double dispatching several times and would be interested. Is your library publically available?

On 12/03/2012 08:21 PM, Karsten Ahnert wrote:
So if there is even any interest for this I would be happy if someone would like to cooperate with me to make this library better and in the end so good so that it can be part of boost. I feel I do not have the time to spare to finalize this on my own, plus I feel I still have things to learn and would be happy to cooperate with someone more experienced in template programming.
I have used double dispatching several times and would be interested. Is your library publically available?
If you (or anyone else) are interested I have an early version you can have a look at here, I release this code as is under the general boost license. http://www.da.isy.liu.se/~perk/double_dispatch_v0.1.tar.bz2

On 12/03/2012 08:21 PM, Karsten Ahnert wrote:
So if there is even any interest for this I would be happy if someone would like to cooperate with me to make this library better and in the end so good so that it can be part of boost. I feel I do not have the time to spare to finalize this on my own, plus I feel I still have things to learn and would be happy to cooperate with someone more experienced in template programming.
I have used double dispatching several times and would be interested. Is your library publically available?
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Since at least I found this library to be useful (for the limited problem domain that is solves). I thought that someone else could find it useful too. For this reason I made it publicly available at Sourceforge http://sourceforge.net/projects/cpp11doubledisp/ Any other posts or comments regarding this package should thus be directed there.
participants (3)
-
Karsten Ahnert
-
Larry Evans
-
Per Karlström