XLE
v0.02.0
|
A collection of functions with varying signatures More...
#include <FunctionUtils.h>
Classes | |
class | DuplicateFunction |
class | NoFunction |
class | SignatureMismatch |
class | StoredFunction |
Public Types | |
typedef uint64_t | Id |
Public Member Functions | |
template<typename Result , typename... Args> | |
Result | Call (Id id, Args...args) const |
template<typename Result , typename... Args> | |
Result | CallDefault (Id id, const Result &defaultResult, Args...args) const |
template<typename Result , typename... Args> | |
bool | TryCall (Result &res, Id id, Args...args) const |
template<typename FnSig > | |
std::function< FnSig > & | Get (Id id) const |
template<typename FnSig > | |
bool | Has (Id id) const |
template<typename Fn > | |
void | Add (Id guid, std::function< Fn > &&fn) |
template<typename ReturnType , typename... Args> | |
void | Add (Id id, ReturnType(*p)(Args...)) |
template<typename L > | |
void | Add (Id id, L &&l) |
template<typename ReturnType , typename... Args, typename ClassType > | |
void | Add (Id id, ReturnType(ClassType::*p)(Args...)) |
bool | Remove (Id id) |
VariantFunctions (const VariantFunctions &)=delete | |
VariantFunctions & | operator= (const VariantFunctions &)=delete |
Protected Member Functions | |
void | ExpandBuffer (size_t newCapacity) |
Protected Attributes | |
std::vector< uint8_t > | _buffer |
std::vector< std::pair< Id, StoredFunction > > | _fns |
A collection of functions with varying signatures
VariantFunctions can be used to store function objects with arbitrary signatures. These functions can then be called by using a hash key id.
It is similar to ParameterBox. But where ParameterBox is used to store primitive data values, VariantFunctions is used to store functions and procedures.
VariantFunctions can be used with any of function-like object. That includes function pointers, std::bind expressions, lambda functions, std::function<> objects and other functor objects. In the case of lamdba expressions and functor objects, extra data associated in the object will be stored (and freed when the VariantFunctions object is destroyed).
Callers will specify the id of the function they want to call, plus the signature (ie, return type and argument types). Callers must get the signature exactly right. An incorrect signature will result in an exception (that is, the system is type safe, in a very strict way).
But callers won't know what type of function object they are calling (function pointer, std::function<>, lambda function, etc). All types of functions work in the same way.
Consider the following example:
This will call the lamdba function, and pass "2" as the parameter.
Stored functions can also store captured data. Consider:
In the above example, a std::weak_ptr is capured by the lambda. Its lifetime will be managed correctly; the std::weak_ptr will be stored in the VariantFunctions, until the VariantFunctions object is destroyed. Any type of object can be captured like this (including std::shared_ptr<>).
This means that it is possible to store arbitrarily complex data within a VariantFunctions instance (simply by adding "get" accessor functions Bind expressions also work. Consider:
Here, a class registers a pointer to its member function "OnMouseClick", using std::bind to bind a class instance pointer.