XLE  v0.02.0
Classes | Public Types | Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
Utility::VariantFunctions Class Reference

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
 
VariantFunctionsoperator= (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
 

Detailed Description

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:

@code {.cpp}
VariantFunctions fns;
fns.Add(Hash64("Inc"), [](int i) { return i+1; });
....
auto result = fns.Call<int>(Hash64("Inc"), 2);
\endcode

This will call the lamdba function, and pass "2" as the parameter.

Stored functions can also store captured data. Consider:

@code {.cpp}
void Publish(std::shared_ptr<Foo> foo)
{
std::weak_ptr<Foo> weakPtrToFoo = foo;
s_variantFunctions.Add(Hash64("GetFoo"),
[weakPtrToFoo]() { return weakPtrToFoo.lock(); });
}
\endcode

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:

@code {.cpp}
void Foo::AddEvents(VariantFunctions& fn)
{
using namespace std::placeholders;
fn.Add(Hash64("OnMouseClick"),
std::bind(&Foo::OnMouseClick, shared_from_this(), _1, _2, _3));
}
\endcode

Here, a class registers a pointer to its member function "OnMouseClick", using std::bind to bind a class instance pointer.

See also
Utility::ParameterBox, Utility::MakeFunction

The documentation for this class was generated from the following files: