That's really cool! I love it :-D
Thank you!
I'll see if I can explain how it works, and maybe you could tell me where I'm wrong/not-quite-right?
The
Dispatcher
class is used to map pairs of shape types with the desired corresponding function, and use this map to call these functions when required. In Dispatcher class:
(*)
BaseFunction
structure and the derived
Function
structure template encapsulate a response function to a particular pair of
Shapes
. Constructor specified in the
Function
structure template takes a
Callback
type, which has just been defined as
typedef void (*Callback)(T1 &,T2 &);
or "a pointer to a function returning void and taking parameters T1&, and T2&, determined upon template specialisation".
(*) An STL
map
container is used with
pair
keys to map shape-type combinations to the desired function.
(*) A boolean 'symmetric' is used to indicate whether or not if (s1,s2) cannot be found in the map, we should search for (s2,s1) instead and call its function:
typedef map<Key, BaseFunction*> DispatchMap
. This is the purpose of the
Function
template inheriting from the
BaseFunction
structure, otherwise the typedef of
DispatchMap
would need to be a template too, to keep
Function
<> generic.
(*)
Add
function template. Takes a
Function
structure as a parameter. The
Add
function adds the
Function
structure to the private member
DispatchMap
, with a
pair
containing the
two shape types as the key (if the key is found within the map already, then the new key and value overwrite the old; this is not a multimap).
(*)
Call
function. Takes two
Shapes
and a
boolean
that allows the caller to specify whether the key (s2,s1) should be tried if (s1,s2) is not found. If the dispatcher has its symmetric boolean == false, then this flag is ignored and (s2,s1) is never tried. The
Call
function searches for the key (types of the two parameter shapes) in the private
DispatchMap
instance, if found,
the corresponding function is called.
-------------------------------------------------------------------------------------------
What I don't understand are the
get_type()
and
get_type_static()
methods. Why set
static int type=0;
and what is
&type
referring to?
Thanks again for your help! I love this solution :-D
Tom.
-------------------------------------------------------------------------------------------
For anyone else who reads this some time in the future - here are a few references I found handy while going through the code:
Void pointers (e.g.
void*
) ==>
http://theoryx5.uwinnipeg.ca/programming/node87.html
Function pointer declarations with a typedef (e.g.
typedef void (*Callback)(T1 &,T2 &);
) ==>
http://www.devx.com/tips/Tip/13829 - Function Pointer Declarations With a typedef
Also, in the following:
1 2 3 4 5 6 7 8 9
|
it=dispatch_map.find(type);
if (it==dispatch_map.end())
{
if (symmetric && check_symmetric)
return Call(s2,s1,false);
else return;
}
(*it->second)(s1,s2);
|
it
is an iterator for the STL
map
container. After
it = dispatch_map.find(type)
, if
it == dispatch_map.end()
, then this means that find() reached the end of the map without finding
type
as a key. In this case, if the functions are symmetric, we can try searching for (s2,s1) in the map instead of (s1,s2). Otherwise, return because there are no other options.
If this is not the case, the required function was found, and
it->second
points to it. Thus
(*it->second)
is like using the function name, and
(*it->second)(s1,s2);
is like calling the function.