Class that is able to perform dynamic dispatch on multiple functions with two parameters.
More...
Public Member Functions |
| DoubleDispatcher (bool symmetric=true, bool supportDerivedToBase=false) |
| Constructor.
|
template<class D1 , class D2 > |
void | Register (R(*globalFunction)(D1#, D2#)) |
| Registers a global function.
|
template<class D1 , class D2 , class C > |
void | Register (R(C::*memberFunction)(D1#, D2#), C &object) |
| Registers a member function.
|
template<class D1 , class D2 , typename Fn > |
void | Register (const Fn &functionObject) |
| Registers a function object.
|
R | Call (B arg1, B arg2) const |
| Dispatches the dynamic types of arg1 and arg2 and invokes the corresponding function.
|
template<class B, typename R = void>
class thor::DoubleDispatcher< B, R >
Class that is able to perform dynamic dispatch on multiple functions with two parameters.
Sometimes you encounter the situation where you need to implement polymorphic behavior to dispatch dynamically on more than one type. Like overloading functions with two parameters at compile time, this class allows you to perform a dispatch on two arguments at runtime. At invocation time, all you need is the static type of the base class, the DoubleDispatcher figures out which dynamic types match which function.
- Template Parameters:
-
B | Reference or pointer to polymorphic base class. This is the base class of every dispatched function's parameter type. When it is a pointer, the arguments of the dispatched functions shall be pointers too (the same applies to references). the dispatched functions shall have arguments of type pointer or reference to const, too. |
R | Return type of the dispatched functions. |
class Base { public: virtual ~Base() {} };
class Derived1 : public Base {};
class Derived2 : public Base {};
void Func(Derived1* lhs, Derived1* rhs);
void Func(Derived1* lhs, Derived2* rhs);
void Func(Derived2* lhs, Derived2* rhs);
thor::DoubleDispatcher<Base*> dispatcher;
dispatcher.Register<Derived1, Derived1>(&Func);
dispatcher.Register<Derived1, Derived2>(&Func);
dispatcher.Register<Derived2, Derived2>(&Func);
Base* ptr = new Derived1;
dispatcher.Call(ptr, ptr);
delete ptr;
template<class B, typename R = void>
Dispatches the dynamic types of arg1 and arg2 and invokes the corresponding function.
Note that the argument's dynamic type must match exactly with the registered type, unless you enabled derived-to-base conversions in the constructor and specified the class hierarchy. In the latter case, the function with the best match is chosen for overload resolution.
- Parameters:
-
arg1 | First function argument. |
arg2 | Second function argument. |
- Returns:
- The return value of the dispatched function, if any.
- Exceptions:
-
FunctionCallException | when no corresponding function is found, or if a call is ambiguous. Ambiguity emerges at derived-to-base conversions if multiple functions represent an equally good match for overload resolution. |
template<class B, typename R = void>
template<class D1 , class D2 >
Registers a global function.
- Template Parameters:
-
D1 | Type of the derived class for the first parameter. Must be explicitly specified. |
D2 | Type of the derived class for the second parameter. Must be explicitly specified. |
- Parameters:
-
globalFunction | Pointer to function to register. |
Note that # is a placeholder for either & or *. The types D1# and D2# have the same attributes as B (pointer, reference, const-qualification): For instance, B=const Base& implies D1#=const Derived1&.
Example (class hierarchy and dispatcher declaration missing):
void Func(Derived1&, Derived1&);
void Func(Derived1&, Derived2&);
void Func(Derived2&, Derived2&);
dispatcher.Register<Derived1, Derived1>(&Func);
dispatcher.Register<Derived1, Derived2>(&Func);
dispatcher.Register<Derived2, Derived2>(&Func);
- Precondition:
- A function taking two arguments of dynamic type D1 and D2 is not registered yet.
template<class B, typename R = void>
template<class D1 , class D2 , class C >
Registers a member function.
- Template Parameters:
-
D1 | Type of the derived class for the first parameter. Must be explicitly specified. |
D2 | Type of the derived class for the second parameter. Must be explicitly specified. |
C | Class that holds the member function. |
- Parameters:
-
memberFunction | Pointer to member function to register. |
object | Reference to object on which the member function is invoked. |
Note that # is a placeholder for either & or *. The types D1# and D2# have the same attributes as B (pointer, reference, const-qualification): For instance, B=const Base& implies D1#=const Derived1&.
Example (class hierarchy and dispatcher declaration missing):
struct MyClass
{
void MemFunc(Derived1&, Derived1&);
void MemFunc(Derived1&, Derived2&);
void MemFunc(Derived2&, Derived2&);
} obj;
dispatcher.Register<Derived1, Derived1>(&MyClass::MemFunc, obj);
dispatcher.Register<Derived1, Derived2>(&MyClass::MemFunc, obj);
dispatcher.Register<Derived2, Derived2>(&MyClass::MemFunc, obj);
- Precondition:
- A function taking two arguments of dynamic type D1 and D2 is not registered yet.
template<class B, typename R = void>
template<class D1 , class D2 , typename Fn >
Registers a function object.
- Template Parameters:
-
D1 | Type of the derived class for the first parameter. Must be explicitly specified. |
D2 | Type of the derived class for the second parameter. Must be explicitly specified. |
Fn | Type of the function object. Can be deduced from the argument. |
- Parameters:
-
functionObject | Functor to register. |
Incomplete example using a function object (you can also have separate functors for each function):
struct Functor
{
void operator() (Derived1&, Derived1&);
void operator() (Derived1&, Derived2&);
void operator() (Derived2&, Derived2&);
};
dispatcher.Register<Derived1, Derived1>(Functor());
dispatcher.Register<Derived1, Derived2>(Functor());
dispatcher.Register<Derived2, Derived2>(Functor());
- Precondition:
- A function taking two arguments of dynamic type D1 and D2 is not registered yet.