
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{...};