5.16 Functor Quick Facts
Functor is a template that allows the expression of calls with up to 15 arguments. The first parameter is the return type, and the second is a typelist containing the parameter types. The third template parameter establishes the threading model of the allocator used with Functor. Refer to Chapter 3 for details on typelists, the appendix for details on threading models, and Chapter 4 for details on small-object allocation.
You initialize a Functor with a function, a functor, another Functor, or a pointer to an object and a pointer to a method, as exemplified in the following code:
void Function(int);
struct SomeFunctor
{
void operator()(int);
};
struct SomeClass
{
void MemberFunction(int);
};
void example()
{
// Initialize with a function
Functor<void, TYPELIST_1(int)> cmd1(Function);
// Initialize with a functor
SomeFunctor fn;
Functor<void, TYPELIST_1(int)> cmd2(fn);
// Initialize with a pointer to object
// and a pointer to member function
SomeClass myObject;
Functor<void, TYPELIST_1(int)> cmd3(&myObject,
&SomeClass::MemberFunction);
// Initialize a Functor with another
// (copying)
Functor<void, TYPELIST_1(int)> cmd4(cmd3);
}
You also can initialize Functor with a std::auto_ptr< FunctorImpl<R,TList> >. This enables user-defined extensions.
Functor supports automatic conversions for arguments and return values. For instance, in the previous example, Function, SomeFunctor::operator(), and SomeClass:: MemberFunction might take a double, instead of an int, as an argument.
Manual disambiguation is needed in the presence of overloading.
Functor fully supports first-class semantics: copying, assigning to, and passing by value. Functor is not polymorphic and is not intended to be derived from. If you want to extend Functor, derive from FunctorImpl.
Functor supports argument binding. A call to BindFirst binds the first argument to a fixed value. The result is a Functor parameterized with the rest of the arguments. Example:
void f()
{
// Define a Functor of three arguments
Functor<void, TYPELIST_3(int, int, double)> cmd1(
someEntity);
// Bind the first argument to 10
Functor<void, TYPELIST_2(int, double)> cmd2(
BindFirst(cmd1, 10));
// Same as cmd1(10, 20, 5.6)
cmd2(20, 5.6);
}
Multiple Functors can be chained in a single Functor object by using the Chain function.
void f()
{
Functor<> cmd1(something);
Functor<> cmd2(somethingElse);
// Chain cmd1 and cmd2
// as the container
Functor<> cmd3(Chain(cmd1, cmd2));
// Equivalent to cmd1(); cmd2();
cmd3();
}
The cost of using Functor is one indirection (call via pointer) for simple Functor objects. For each binding, there is an extra virtual call cost. For chaining, there is an extra virtual call cost. Parameters are not copied, except when conversion is necessary.
FunctorImpl uses the small-object allocator defined in Chapter 4.
|