Re: double dispatch, half compile-time
Ethan Eade <ee231@cam.ac.uk> writes:
I have a hierarchy that looks like this:
-----------
class Variant {
public:
virtual ~Variant(){}
};
template <class T> class Value<T> : public Variant {
private:
T value;
public:
};
------------
Let's say there are two function templates:
------------
template <class A>
void single_bound(const A& a, const Variant& b);
template <class A, class T>
void double_bound(const A& a, const Value<T>& v);
------------
Is there any possible implementation of single_bound such that the
appropriate double_bound would be called inside? That is, can Variant
and Value<T> be defined s.t. their definitions do not explicitly list
the possibilities for type A, but still both A and T can be known in the
same scope?
At some point, you have to define which combinations of A and T are
valid. Since you know A at compile time, you can get away with only
having to
specify which Ts are permitted (for all A), by using the following:
#include <typeinfo>
#include <iostream>
#include <string>
#include <memory>
struct DispatchBase;
class Variant {
public:
virtual ~Variant(){}
virtual void dispatch(DispatchBase& dispatcher) const=0;
};
template<class T> class Value;
template<typename T>
struct DoDispatch
{
virtual void dispatch2(Value<T> const& v)=0;
};
struct DispatchBase
{
template<typename T>
void dispatch(Value<T> const& v)
{
DoDispatch<T>* const dispatcher=dynamic_cast<DoDispatch<T>*>(this);
if(dispatcher)
{
dispatcher->dispatch2(v);
}
else
{
std::cout<<"No dispatcher for T="<<typeid(T).name()<<std::endl;
}
}
virtual ~DispatchBase()
{}
};
template <class T> class Value : public Variant {
public:
T value;
Value(T const& t):value(t){}
void dispatch(DispatchBase& dispatcher) const
{
dispatcher.dispatch(*this);
}
};
template <class A, class T>
void double_bound(const A& a, const Value<T>& v);
#define IMPLEMENT_DISPATCH(T) void dispatch2(Value<T> const&
v){double_bound(a,v);}
template<typename A>
struct Dispatcher:
DispatchBase,
DoDispatch<int>,
DoDispatch<std::string>
{
IMPLEMENT_DISPATCH(int)
IMPLEMENT_DISPATCH(std::string)
A const& a;
Dispatcher(A const& a_):a(a_){}
};
template <class A>
void single_bound(const A& a, const Variant& b)
{
Dispatcher<A> dispatcher(a);
b.dispatch(dispatcher);
}
class X{};
class Y{};
class Z{};
template <class A, class T>
void double_bound(const A& a, const Value<T>& v)
{
std::cout<<"double_bound called for A="<<typeid(A).name()
<<", T="<<typeid(T).name()
<<", value="<<v.value<<std::endl;
}
int main()
{
std::auto_ptr<Variant> v1(new Value<int>(3));
std::auto_ptr<Variant> v2(new Value<std::string>("hello"));
std::auto_ptr<Variant> v3(new Value<double>(1.2));
X x;
Y y;
single_bound(x,*v1);
single_bound(x,*v2);
single_bound(x,*v3);
single_bound(y,*v1);
single_bound(y,*v2);
single_bound(y,*v3);
}
Compiled with MSVC 7.1, this outputs:
double_bound called for A=class X, T=int, value=3
double_bound called for A=class X, T=class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >, value=hello
No dispatcher for T=double
double_bound called for A=class Y, T=int, value=3
double_bound called for A=class Y, T=class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >, value=hello
No dispatcher for T=double
I discussed this sort of thing in my "Message Handling without Dependencies"
article in the May 2006 issue of DDJ:
http://www.ddj.com/dept/cpp/184429055
Anthony
--
Anthony Williams
Just Software Solutions Ltd - http://www.justsoftwaresolutions.co.uk
Registered in England, Company Number 5478976.
Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]