Re: Design question: alternative to inheritance.
ram@zedat.fu-berlin.de (Stefan Ram) writes:
The visitor pattern mentioned is a means to emulate bimethods
in languages without multimethods.
To explain the visitor pattern, I have made up a simplified
version: The dynamic-static adaptor.
There might be a type hierarchy as follows:
struct X { ... };
struct A : public X { ... };
struct B : public X { ... };
One might be given two function definitions with /static/
dispatch:
struct S
{
static void static_process( A const * a )
{ ::std::cout << "S::static_process( A )\n"; }
static void static_process( B const * b )
{ ::std::cout << "S::static_process( B )\n"; }};
But one might want to call ?static_process? via /dynamic/ dispatch:
int main()
{ A a;
B b;
{ X * x = &a; x->static_process(); }
{ X * x = &b; x->static_process(); }}
S::static_process( A )
S::static_process( B )
(The final two lines are the output wanted.)
This won't work directly as shown above, because of the
dynamic-static mismatch.
But one can write a dynamic-static adaptor to
convert the dynamic calls to static calls:
struct X { virtual void process() = 0; };
struct A : public X { void process(){ S::static_process( this ); }};
struct B : public X { void process(){ S::static_process( this ); }};
The key to this is that the type of ?this? is known statically
at the two places above. Therefore, it can be used for static
dispatch. Still, calls to X#process() are dispatched
dynamically. So, a /dynamically/ dispatched call is converted to
a /statically/ dispatched call. The complete source code:
#include <iostream>
#include <ostream>
struct A;
struct B;
struct S
{ static void static_process( A const * a )
{ ::std::cout << "S::static_process( A )\n"; }
static void static_process( B const * b )
{ ::std::cout << "S::static_process( B )\n"; }};
struct X { virtual void process() = 0; };
struct A : public X { void process(){ S::static_process( this ); }};
struct B : public X { void process(){ S::static_process( this ); }};
int main()
{ A a;
B b;
{ X * x = &a; x->process(); }
{ X * x = &b; x->process(); }}
S::static_process( A )
S::static_process( B )
(The final two lines are the output.)
By a combination of two dynamic-static adaptors, one gets the
visitor pattern. This might be elaborated in another post.