|
Boost : |
Subject: [boost] Request for interest in a library to ease double dispatching
From: Per Karlström (per_at_[hidden])
Date: 2012-12-03 09:13:58
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{...};
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk