c++-gtk-utils
|
This file provides classes encapsulating callbacks. More...
Go to the source code of this file.
Namespaces | |
namespace | Cgu::Callback |
This namespace provides classes encapsulating callbacks. | |
namespace | Cgu |
Typedefs | |
typedef CallbackArg | Cgu::Callback::Callback |
typedef FunctorArg | Cgu::Callback::Functor |
typedef SafeFunctorArg | Cgu::Callback::SafeFunctor |
Functions | |
template<class... T> | |
bool | Cgu::Callback::operator== (const FunctorArg< T...> &f1, const FunctorArg< T...> &f2) |
template<class... T> | |
bool | Cgu::Callback::operator!= (const FunctorArg< T...> &f1, const FunctorArg< T...> &f2) |
template<class... T> | |
bool | Cgu::Callback::operator< (const FunctorArg< T...> &f1, const FunctorArg< T...> &f2) |
template<class... T> | |
bool | Cgu::Callback::operator== (const SafeFunctorArg< T...> &f1, const SafeFunctorArg< T...> &f2) |
template<class... T> | |
bool | Cgu::Callback::operator!= (const SafeFunctorArg< T...> &f1, const SafeFunctorArg< T...> &f2) |
template<class... T> | |
bool | Cgu::Callback::operator< (const SafeFunctorArg< T...> &f1, const SafeFunctorArg< T...> &f2) |
template<class T , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (T &t, void(T::*func)(FreeArgs...)) |
template<class T , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (T &t, void(T::*func)(FreeArgs...)) |
template<class T , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (T &t, void(T::*func)(FreeArgs...)) |
template<class T , class BoundArg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (T &t, void(T::*func)(BoundArg, FreeArgs...), BoundArg arg) |
template<class T , class BoundArg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (T &t, void(T::*func)(BoundArg, FreeArgs...), const BoundArg &arg) |
template<class T , class BoundArg , class Arg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (T &t, void(T::*func)(BoundArg, FreeArgs...), Arg &&arg) |
template<class T , class BoundArg1 , class BoundArg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (T &t, void(T::*func)(BoundArg1, BoundArg2, FreeArgs...), BoundArg1 arg1, BoundArg2 arg2) |
template<class T , class BoundArg1 , class BoundArg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (T &t, void(T::*func)(BoundArg1, BoundArg2, FreeArgs...), const BoundArg1 &arg1, const BoundArg2 &arg2) |
template<class T , class BoundArg1 , class BoundArg2 , class Arg1 , class Arg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (T &t, void(T::*func)(BoundArg1, BoundArg2, FreeArgs...), Arg1 &&arg1, Arg2 &&arg2) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...), BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...), const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class Arg1 , class Arg2 , class Arg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...), BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3, BoundArg4 arg4) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...), const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3, const BoundArg4 &arg4) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class Arg1 , class Arg2 , class Arg3 , class Arg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...), BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3, BoundArg4 arg4, BoundArg5 arg5) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...), const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3, const BoundArg4 &arg4, const BoundArg5 &arg5) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class Arg1 , class Arg2 , class Arg3 , class Arg4 , class Arg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) |
template<class T , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (const T &t, void(T::*func)(FreeArgs...) const) |
template<class T , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (const T &t, void(T::*func)(FreeArgs...) const) |
template<class T , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (const T &t, void(T::*func)(FreeArgs...) const) |
template<class T , class BoundArg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (const T &t, void(T::*func)(BoundArg, FreeArgs...) const, BoundArg arg) |
template<class T , class BoundArg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (const T &t, void(T::*func)(BoundArg, FreeArgs...) const, const BoundArg &arg) |
template<class T , class BoundArg , class Arg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (const T &t, void(T::*func)(BoundArg, FreeArgs...) const, Arg &&arg) |
template<class T , class BoundArg1 , class BoundArg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (const T &t, void(T::*func)(BoundArg1, BoundArg2, FreeArgs...) const, BoundArg1 arg1, BoundArg2 arg2) |
template<class T , class BoundArg1 , class BoundArg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (const T &t, void(T::*func)(BoundArg1, BoundArg2, FreeArgs...) const, const BoundArg1 &arg1, const BoundArg2 &arg2) |
template<class T , class BoundArg1 , class BoundArg2 , class Arg1 , class Arg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (const T &t, void(T::*func)(BoundArg1, BoundArg2, FreeArgs...) const, Arg1 &&arg1, Arg2 &&arg2) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const, BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const, const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class Arg1 , class Arg2 , class Arg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const, Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...) const, BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3, BoundArg4 arg4) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...) const, const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3, const BoundArg4 &arg4) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class Arg1 , class Arg2 , class Arg3 , class Arg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...) const, Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...) const, BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3, BoundArg4 arg4, BoundArg5 arg5) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...) const, const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3, const BoundArg4 &arg4, const BoundArg5 &arg5) |
template<class T , class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class Arg1 , class Arg2 , class Arg3 , class Arg4 , class Arg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (const T &t, void(T::*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...) const, Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (void(*func)(FreeArgs...)) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (void(*func)(FreeArgs...)) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (void(*func)(FreeArgs...)) |
template<class BoundArg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (void(*func)(BoundArg, FreeArgs...), BoundArg arg) |
template<class BoundArg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (void(*func)(BoundArg, FreeArgs...), const BoundArg &arg) |
template<class BoundArg , class Arg , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (void(*func)(BoundArg, FreeArgs...), Arg &&arg) |
template<class BoundArg1 , class BoundArg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (void(*func)(BoundArg1, BoundArg2, FreeArgs...), BoundArg1 arg1, BoundArg2 arg2) |
template<class BoundArg1 , class BoundArg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (void(*func)(BoundArg1, BoundArg2, FreeArgs...), const BoundArg1 &arg1, const BoundArg2 &arg2) |
template<class BoundArg1 , class BoundArg2 , class Arg1 , class Arg2 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (void(*func)(BoundArg1, BoundArg2, FreeArgs...), Arg1 &&arg1, Arg2 &&arg2) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (void(*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...), BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (void(*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...), const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class Arg1 , class Arg2 , class Arg3 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (void(*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (void(*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...), BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3, BoundArg4 arg4) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (void(*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...), const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3, const BoundArg4 &arg4) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class Arg1 , class Arg2 , class Arg3 , class Arg4 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (void(*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (void(*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...), BoundArg1 arg1, BoundArg2 arg2, BoundArg3 arg3, BoundArg4 arg4, BoundArg5 arg5) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (void(*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...), const BoundArg1 &arg1, const BoundArg2 &arg2, const BoundArg3 &arg3, const BoundArg4 &arg4, const BoundArg5 &arg5) |
template<class BoundArg1 , class BoundArg2 , class BoundArg3 , class BoundArg4 , class BoundArg5 , class Arg1 , class Arg2 , class Arg3 , class Arg4 , class Arg5 , class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (void(*func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, BoundArg5, FreeArgs...), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (const std::function< void(FreeArgs...)> &f) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (const std::function< void(FreeArgs...)> &f) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (const std::function< void(FreeArgs...)> &f) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make (std::function< void(FreeArgs...)> &&f) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_val (std::function< void(FreeArgs...)> &&f) |
template<class... FreeArgs> | |
CallbackArg< FreeArgs...> * | Cgu::Callback::make_ref (std::function< void(FreeArgs...)> &&f) |
template<class... FreeArgs, class Lambda > | |
CallbackArg< FreeArgs...> * | Cgu::Callback::lambda (Lambda &&l) |
void | Cgu::Callback::post (const Callback *cb, gint priority=G_PRIORITY_DEFAULT_IDLE, GMainContext *context=0) |
void | Cgu::Callback::post (const Callback *cb, Releaser &r, gint priority=G_PRIORITY_DEFAULT_IDLE, GMainContext *context=0) |
This file provides classes encapsulating callbacks.
#include <c++-gtk-utils/callback.h>
These classes encapsulate callbacks (they are closures). They comprise a generic callback creation and execution interface. There is a basic Callback::Callback type, which is an entire closure or 'thunk', where all the arguments are bound in the constructor and is completely opaque. Callback::CallbackArg<T...> is a class which takes unbound arguments of the template types when the callback is dispatched, with any other arguments being bound at construction time. (The opaque Callback::Callback type is in fact just a typedef for Callback::CallbackArg<>: the two types are interchangeable.)
The classes can represent static and non-static member functions and plain functions. In the case of a non-static member function, the object whose member function the callback represents must remain in existence until any invocations of the callback have completed. The function referred to must be one of void return type. A callback object can also be constructed from a std::function object, provided that it is of void return type (which would amongst other things enable, where necessary, the binding of the referenced object of a non-static member function by taking an internal copy of it using std::bind).
They are particularly useful where a callback object may need to be handed between threads.
The classes can also be useful for general event passing when used together with the Callback::post() functions, or as the data argument of a call to g_signal_connect_data() in a case where a better design arises when passing arguments known at connect time by storing them in the callback object itself (say, where otherwise you would pass a plain struct as the data argument).
These classes are also used in the Emitter/EmitterArg classes in emitter.h, which enable callbacks to be connected to an emitter and provide for automatic disconnection where a class object whose member a callback represents ceases to exist.
The Callback::make() functions
The templated helper Callback::make() functions make it trivial to create a callback object of the correct type. The ordinary Callback::make() functions (that is, those not taking a std::function object) provide for a maximum of five bound arguments to pass to the relevant function or class method, and an unlimited number of unbound arguments, but unbound arguments must be the last (trailing) arguments of the relevant function or method to be called if there is a bound argument. Callback/CallbackArg classes do not provide for a return value. If a result is wanted, users should pass an unbound argument by reference or pointer (or pointer to pointer).
Although as mentioned above only five bound arguments are provided for by callbacks constructed by the ordinary Callback::make() functions, as any of those arguments can be a struct, any number of arguments can be passed as members of a struct or a std::tuple. In addition, a callback object can be constructed from a std::function object, which can have any number of arguments bound to it, and in any order (that is, unbound arguments may precede bound arguments).
The Callback::make() functions not taking a std::function object do a direct type mapping from the bound arguments of the function or method represented by the callback object to the arguments stored by the callback object. Bound value arguments of the relevant function or method to be called are therefore stored by value in the callback object. A bound argument can comprise a reference argument (T& or const T&) if the template parameters of the Callback::make() call are qualified by hand to avoid a type mismatch: see under "Usage" below for further particulars, and if the reference argument is non-const this allows the referenced argument to be mutated. However as this would result in the lifetime of the argument not being controlled by the callback object (it would not keep its own copy), it will often be unsafe to do so. (The documentation on Thread::JoinableHandle gives a usage where where binding a reference argument would be safe.)
From version 2.0.0-rc3, the library also provides Callback::make_ref() functions, which force the callback object to keep a copy of the value passed where a target function argument is a const reference. It is therefore safe with const reference arguments. No explicit type qualification is required by Callback::make_ref(). In addition the Callback::make_ref() functions provide for more efficient passing of class type bound arguments (by l-value or r-value reference) than does Callback::make(): see further below.
The Callback::make_ref() functions
In order to enable the widest variety of types to be accepted as arguments (including reference arguments in those cases where it is safe, and also string literals), as mentioned above when constructing a callback object from other than a std::function object, Callback::make() receives non-reference bound arguments by value, and if unoptimised these may be copied up to two times, and once more when the target function is dispatched. Where a bound argument is a pointer or a fundamental type (an integral or floating-point type), optimization by copy elision will reduce the number of times argument copying takes place when constructing a callback object to once, but the standard does not permit that with class types where the constructor or destructor have side effects or it cannot be ascertained whether they have side effects.
Therefore, to cater for cases where a target function takes a class type argument by const reference or value, from version 2.0.0-rc3 the Callback::make_ref() functions are provided. Unlike Callback::make(), when constructing a callback for a target function taking a const reference bound argument, Callback::make_ref() will force the callback object to keep a copy of the argument instead of a reference to that argument. This makes the use of const reference arguments safe (at the cost of the storing of that copy). It cannot be used with non-const references. In addition Callback::make_ref() automatically chooses the most efficient means of passing class type arguments for storage by the callback object, that is by l-value reference or r-value reference, as appropriate.
In the case of a value argument, at callback dispatch time one additional copy will be made in the normal way when the target function is called, but in the case of a const reference argument no such additional copy will be made. What all this means is that, where bound arguments include a non-trivial class type, the most efficient and exception safe strategy is usually:
This flexibility of Callback::make_ref() has a downside: unlike Callback::make(), Callback::make_ref() cannot resolve overloaded functions by argument type. Where a function has two or more overloads taking the same number of arguments, explicit disambiguation by the user is required (see further below under Overloaded Functions).
Summary: If a callback object's bound arguments are all simple fundamental types such as pointers (including C strings), integers or floating points, use Callback::make(). Where bound arguments include class types, use Callback::make_ref().
The Callback::make_val() functions
The library also provides Callback::make_val() functions. These are provided to retain code compatibility with version 1.2 of the library. They were optimised for use where a target function takes bound arguments of class type by value, but are now deprecated and superseded by the automatic variable type mapping of Callback::make_ref(). Callback::make_ref() should now be used instead of Callback::make_val().
Constructing callbacks from std::function objects
The Callback::make() factory functions can also construct a callback object from a std::function object, which would enable a callback to take more than 5 bound arguments, or to have a bound argument which is passed after (or mixed with) unbound arguments, or to have its own copy of the referenced object of a non-static member function bound to it.
However, the genericity of the binding of arguments implemented in std::function and std::bind comes at a cost. Arguments bound to a std::function object can be copied a significant number of times (libstdc++ for example can copy class types four times when constructing a std::function object and two more times when executing the function, unless they have a r-value constructor, in which case they are copied twice and once respectively with two and one additional calls to the r-value constructor). Non-trivial class types should therefore only be passed as bound arguments to std::function objects by pointer or smart pointer.
Note that the overload of Callback::make() for std::function objects has a version taking a r-value reference for the lossless passing through of temporaries to the callback object, and a version taking a const reference for std::function objects which are l-values. For std::function objects, Callback::make() and Callback::make_ref() are all synonyms (the way arguments are dealt with for std::function objects is determined by std::bind() and std::ref()).
The Callback::lambda() functions
Callback objects for C++11 lambda functions can be constructed using Callback::make() by passing the lambda object via a temporary std::function object (see under Usage below for an example). However, from version 2.0.9 the Callback::lambda() factory function is provided enabling callbacks for C++11 lambda functions to be constructed more directly. This is nice, as by using Callback::lambda() a callback can, for example, be executed by a glib main loop using Callback::post() with:
Further examples are given under Usage below.
Using Callback::lambda() to construct a callback object from a C++11 lambda function, rather than using Callback::make() with a temporary std::function object, will also be more efficient, as when executed it would normally avoid the additional virtual function call that would arise with std::function.
When using Callback::lambda(), the unbound argument types must be specified explicitly (they cannot be deduced from the lambda expression).
From version 2.0.10, Callback::lambda() can be called for lambda expressions which are declared mutable capturing bound arguments by value (in version 2.0.9, the function could only be called for non-mutable lambda expressions)
Callback::lambda() can be used to construct a callback object from any arbitrary callable object. It could therefore be used to construct callback objects from plain function pointers where no arguments are to be bound, and from std::function objects. However, that is rarely useful as employing Callback::make() with function pointers and std::function objects provides the benefit of automatic type deduction of the arguments. One possible case where Callback::lambda() might be useful with non-lambda callable objects relates to another feature of Callback::lambda(), namely that the callable object passed to it need not be of void return type. However, if the callable object does return a value, that value is discarded. If a result is wanted, an unbound reference or pointer argument should be passed when the callback is executed, to which the result can be assigned.
If using lambda expressions with gcc, gcc-4.5 or greater is needed. The header file callback.h can be included without error with gcc-4.4, but callable objects cannot be constructed using C++11 lambda syntax.
Functors
If a functor class of void return type is required (say for passing to a c++ algorithm or container, or for automatic lifetime management of the Callback object), the Callback::Functor and Callback::FunctorArg wrapper classes can be used. However, for many c++ algorithms where anonymous functors created as temporaries can be used, the std::ptr_fun(), std::mem_fn() and std::bind() factory functions or a lambda function will be a more obvious choice. Callback::Functor and Callback::FunctorArg are to be preferred to std::function where value arguments are to be bound (see above), unless something other than a void return type is required.
Callback::SafeFunctor and Callback::SafeFunctorArg classes are the same as Callback::Functor and Callback::FunctorArg classes, except that objects of the safe version may be passed and copied between threads and put in different containers in different threads (that is, the reference count maintained with respect to the contained callback object is thread-safe). They use a SharedLockPtr object to hold the referenced callback object.
Memory allocation
If the library is installed using the –with-glib-memory-slices-compat or –with-glib-memory-slices-no-compat configuration options, any Callback::Functor, Callback::FunctorArg, Callback::SafeFunctor or Callback::SafeFunctorArg objects constructed on free store (usually they won't be) will be constructed in glib memory slices. A contained Callback::Callback or Callback::CallbackArg object, which will always be constructed on free store, will be constructed in glib memory slices if the –with-glib-memory-slices-no-compat configuration option is chosen.
Usage
For a class object my_obj of type MyClass, with a method void MyClass::my_method(int, int, const char*), usage for a fully bound callback or functor would be:
Or for a partially bound callback or functor:
The syntax for the construction of a callback object representing a static member function with a signature void MyClass::my_func(int, const char*), or for a normal function, is similar to the non-static member function case, except that the call to Callback::make would comprise:
(fully bound), or
(partially bound), and so on.
To bind to reference arguments, the call to Callback::make() must be explicitly typed. For a class object my_obj of type MyClass, with a method void MyClass::my_method(int&), usage for a fully bound callback or functor would be:
Note however the caveats above about binding to reference arguments.
No similar explicit typing is required by Callback::make_ref(). Thus for a class object my_obj of type MyClass, with a method void MyClass::my_method(int, const Something&), usage for a fully bound callback or functor would be:
Usage for constructing a callback object from a std::function object is as follows, for a class object my_obj of type MyClass, with a method void MyClass::my_method(int, int, int, double, const char*), where a value is to be bound to the second argument:
In this example, if the bound argument were a reference (that is, the signature of MyClass::my_method were (int, int&, int, double, const char*) and it were safe to do so (see above), it could be bound with std::ref(), as in:
Lambda expressions can also be passed to callback objects via std::function, and arguments can be bound with the [=] capture expression, as in:
However, from version 2.0.9, Callback::lambda() provides an easier way of dealing with lambda expressions. The same code could be implemented as:
With Callback::lambda(), the types of the unbound arguments must be explicitly specified as they cannot be deduced. Unbound arguments can comprise reference arguments. For example:
Overloaded functions
Note that creating callbacks for overloaded functions can give rise to an ambiguity when using Callback::make(), arising from the fact that the callback object may have an unbound argument. For example:
The third call to Callback::make() is ambiguous, as it could be creating a callback for either the function MyClass::add(int) with no unbound argument (that is, creating a Callback::Callback object), or the function MyClass::add(int, int) with an unbound int argument (that is, creating a Callback::CallbackArg<int> object). This situation could be disambiguated by specifically stating the type of the function which is to be chosen, namely, to instantiate the callback in the third call with:
Callback::make_ref() is less capable than Callback::make() at deducing template types. It cannot resolve overloaded functions by examining the arguments passed to it. For example, take a class MyClass as follows:
Callback::make_ref() would require explicit disambiguation like this:
Note also that, for CallbackArg objects created from std::function objects, the std::function constructors and the std::mem_fn() and std::bind() functions normally do not allow any function overloading without explicit disambiguation.
Posting of callbacks
This file also provides Callback::post() functions which will execute a callback in a glib main loop and can be used (amongst other things) to pass an event from a worker thread to the main program thread. In that respect, it provides an alternative to the Notifier class. It is passed a pointer to a Callback::CallbackArg object created with a call to Callback::make() or Callback::lambda().
To provide for thread-safe automatic disconnection of the callback if the object whose method it represents is destroyed before the callback executes in the main loop, include a Releaser as a public member of that object and pass the Releaser object as the second argument of Callback::post(). Note that for this to be race free, the lifetime of the remote object whose method is to be invoked must be determined by the thread to whose main loop the callback has been attached. When the main loop begins invoking the execution of the callback, the remote object must either wholly exist (in which case the callback will be invoked) or have been destroyed (in which case the callback will be ignored), and not be in some transient half-state governed by another thread.
Advantages as against Notifier:
Disadvantages as against Notifier: