c++-gtk-utils
Constructing callback objects for more than one unbound argument

From version 1.2.10 of the library, by default Cgu::Callback::CallbackArg, Cgu::Callback::FunctorArg and Cgu::EmitterArg objects can be constructed to represent functions which are to take two or three unbound arguments. This is done by means of the Cgu::TypeTuple struct. This struct is never instantiantiated so it adds no overhead: it just gives type information when the callback templates are instantiated.

Syntax is similar to that used when constructing an object for one unbound argument. For a class object my_obj of type MyObj, with a method void MyObj::my_method(int, int, int, const char*), usage with two unbound arguments would be:

int arg1 = 1, arg2 = 2, arg3 = 3;
Cgu::Callback::make(my_obj, &MyObj::my_method, arg1, arg2);
cb->dispatch(arg3, "Hello\n");
delete cb;
f(arg3, "Hello\n");
e.connect(Cgu::Callback::make(my_obj, &MyObj::my_method, arg1, arg2));
e(arg3, "Hello\n");

and for three unbound arguments:

int arg1 = 1, arg2 = 2, arg3 = 3;
Cgu::Callback::make(my_obj, &MyObj::my_method, arg1);
cb->dispatch(arg2, arg3, "Hello\n");
delete cb;
f(arg2, arg3, "Hello\n");
e.connect(Cgu::Callback::make(my_obj, &MyObj::my_method, arg1));
e(arg2, arg3, "Hello\n");

Three points should be noted. First, as in the case of a single unbound argument, if there are bound arguments these multiple unbound arguments must be the last (trailing) arguments of the function to be called.

Secondly, Cgu::TypeTuple is not used for objects constructed for a single unbound argument. Where there is a single unbound argument of type T, Callback::make() and Callback::make_val() construct a callback of type Callback::CallbackArg<T> and not Callback::CallbackArg<TypeTuple<T> >, and the corresponding Callback::FunctorArg and EmitterArg objects are of type Callback::FunctorArg<T> and EmitterArg<T> respectively.

Thirdly, being able to construct a callback object for more than one unbound argument creates additional scope for ambiguities when calls are made to Callback::make() and Callback::make_val() with respect to overloaded functions. Take this example:

class MyClass {
...
void add(int i, int j, int k);
void add(int i, int j, int k, int l);
};
MyClass obj;
using namespace Cgu;
Callback::CallbackArg<int>* cb1 = Callback::make(obj, &MyClass::add, 1, 2);

Prior to version 1.2.10 this is unambiguous, as a callback object could only have been constructed for the first add() function above. With version 1.2.10 onwards, specific disambiguation is required:

Callback::CallbackArg<int>* cb1 =
Callback::make(obj, static_cast<void (MyClass::*)(int, int, int)>(&MyClass::add), 1, 2); // represents first add() function
Callback::CallbackArg<TypeTuple<int, int> >* cb2 =
Callback::make(obj, static_cast<void (MyClass::*)(int, int, int, int)>(&MyClass::add), 1, 2); // represents second add() function

If the add() methods were static class functions (or ordinary functions) the disambiguation would comprise:

Callback::CallbackArg<int>* cb1 =
Callback::make(obj, static_cast<void (*)(int, int, int)>(&MyClass::add), 1, 2);
Callback::CallbackArg<TypeTuple<int, int> >* cb2 =
Callback::make(obj, static_cast<void (*)(int, int, int, int)>(&MyClass::add), 1, 2);

In order to allow code relying on the previous behaviour to continue to compile without being modified to provide this disambiguation, with version 1.2.10 onwards the library can be compiled with the --with-type-tuple-args=no (or --without-type-tuple-args) option. This does not affect binary compatibility (version 1.2.10 onwards of the library is binary compatible with earlier versions in the 1.2 series either with or without this option), but if that option is used, Callback::CallbackArg objects will only be able to represent functions taking a single unbound argument.

Cgu::Callback::CallbackArg
The callback interface class.
Definition: callback.h:904
Cgu
Definition: application.h:45
Cgu::Callback::make
Callback * make(T &t, void(T::*func)())
Definition: callback.h:2376
Cgu::EmitterArg::connect
Callback::FunctorArg< FreeArg > connect(const Callback::FunctorArg< FreeArg > &f)
Cgu::EmitterArg
A class to execute callbacks connected to it, with provision for automatic disconnection.
Definition: emitter.h:342
Cgu::Callback::FunctorArg
Functor class holding a Callback::CallbackArg object.
Definition: callback.h:1077
Cgu::Callback::CallbackArg::dispatch
virtual void dispatch(typename Cgu::Param< FreeArg >::ParamType arg) const =0