Boost logo

Boost :

Subject: Re: [boost] Request for interest in a library to ease double dispatching
From: Larry Evans (cppljevans_at_[hidden])
Date: 2012-12-03 12:40:59


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_storage/sandbox/pack/

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


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