#include <events.h>
Public Member Functions | |
template<typename TargT> | |
void | Register (TargT *targp, TRet(TargT::*mfp)(TA1, TA2, TA3, TA4, TA5, TA6)) |
Register a simple object and method to be called. | |
void | Register (BaseT const &src) |
Copy the state of an identical callback object. | |
TRet | operator() (TA1 a1, TA2 a2, TA3 a3, TA4 a4, TA5 a5, TA6 a6) |
Invoke the callback method. | |
bool | Registered (void) const |
Test whether an object and method are registered to be called. | |
void | Unregister (void) |
Clear the currently registered object and method. | |
template<typename TargT> | |
void | Bind (TargT *objp, TRet(TargT::*mfp)(void)) |
Register a method with a nonconforming signature to the callback object. |
This class allows a callback to be defined to match any desired function signature up to six arguments, and allows any arbitrary member function up to six arguments to be registered. Stored parameters and provided parameter remapping is supported.
The expected arguments are configured by template parameters:
TRet | Return type of the callback method | |
TA1 | Type of the first argument, or Nil if no arguments | |
TA2 | Type of the second argument, or Nil if less than two arguments | |
TA3 | Type of the third argument, or Nil if less than three arguments |
The object to be called and method may be set using the Register() or Bind() methods. The callback may be cleared with the Unregister() function. The presence of a callback may be tested with the Registered() function.
In most situations, Callback is used to define an abstract interface. The provider will define the template parameters and invoke the callback. The client will define a method to be called, register the method, and receive the call.
An untypical usage:
class Target { void Alert(int priority, const char *text) { printf("PRIORITY %d ALERT: %s\n", priority, text); } void GroceryList(int priority, const char *text) { printf("Groceries: %s (Priority %d)\n", text, priority); } }; Callback<void, int, const char *> format_func; Target t; format_func.Register(t, &t::Alert); format_func(1, "Russian Nukes Launched"); format_func.Register(t, &t::GroceryList); format_func(1, "Milk and Eggs");
The output of this example would be:
PRIORITY 1 ALERT: Russian Nukes Launched Groceries: Milk and Eggs (Priority 1)
void Register | ( | TargT * | targp, | |
TRet(TargT::*)(TA1, TA2, TA3, TA4, TA5, TA6) | mfp | |||
) | [inline] |
Register a simple object and method to be called.
targp | The object to receive the method call | |
mfp | Pointer to the method of the object to be invoked |
For example, if the callback has signature:
Callback<void, int, int, bool, const char *>
The method to be registered must have signature:
void Method(int, int, bool, const char *).
Nonconforming methods may also be registered as the target using Bind(). However, Register() results in lower overhead callback invocations, and its use is advised when possible.
TRet operator() | ( | TA1 | a1, | |
TA2 | a2, | |||
TA3 | a3, | |||
TA4 | a4, | |||
TA5 | a5, | |||
TA6 | a6 | |||
) | [inline] |
Invoke the callback method.
void Bind | ( | TargT * | objp, | |
TRet(TargT::*)(void) | mfp | |||
) | [inline, inherited] |
Register a method with a nonconforming signature to the callback object.
In the spirit of boost::bind, this module provides a generic argument remapping mechanism for target methods. This makes it possible to bind methods to callbacks where the method's signature does not match that of the callback, as long as a useful argument mapping can be created. This mechanism allows values to be stored at the time the method is bound to the callback, and passed to the target function each time the callback is invoked.
objp | Target object to receive the callback | |
mfp | Target method to receive the callback. The signature of the method need not conform to the signature of the callback, but it must have the same return type. |
objp->mfp
, and must match the signature of mfp
. Arguments will be saved in the callback object and passed to the method when the callback is invoked. Special keywords Arg1
, Arg2
, ... Arg6
can be used to identify parameters passed to the callback by its caller, as potential arguments to the nonconforming method.As an untypical example, suppose we want to log messages to stdout, and prefix them with either "error" or "warning" depending on which of two objects the message is submitted to.
class Target { void LogValue(const char *source, const char *value) { printf("%s: %d\n", source, value); } }; Target tgt; Callback<void, const char *> error; Callback<void, const char *> warning; error.Bind(&tgt, &Target::LogValue, "Error", Arg1); warning.Bind(&tgt, &Target::LogValue, "Error", Arg1); error("This is an error\n"); warning("This is a warning\n");
The output would be:
Error: This is an error Warning: This is a warning
This method has one specific advantage over boost::bind. It does not allocate memory under any circumstances. It will not unpredictably fail or throw an exception at runtime. On the down side, it is quite primitive compared to boost::bind. It does not support pointers to nonmember functions. Also, its stored parameters reside inside the Callback object itself. The amount of space reserved for stored parameters is larger than that set by boost::function, and Callback objects take up more space. Additionally, if a binding request is made that would exceed the space reserved for stored parameters, a compile time error will be generated.