Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Version 2 (modified by landauf, 16 years ago) (diff)

Functor

TracNav(TracNav/TOC_Development)?

Description

The Functor is a wrapper around a function-pointer. You can call the function by executing the Functor without taking care of the types of parameters and return value. This is achieved by using MultiType to pass arguments.

Functor works with (almost) every function. This is possible because of a number of derived templates, one for every possible combination:

  • Static, member or const member
  • With or without returnvalue
  • With or without parameters (up to five parameters are allowed)

As you see, this results in a total amount of 3*2*6 = 36 combinations, each of them implemented as a template to allow arbitrary types for classes, returnvalues and parameters.

Functor.h implements all those templates by using a macro to avoid annoying code repetition.

Limitation: Because Functor uses MultiType to pass the arguments, parameters and return values must be of a supported type.

Usage

Creation

To simplify creation of a new Functor, the helper function createFunctor(function-pointer) was created. Without that function, you would have to pick the right template (out of 36 possibilities) and specify all template arguments - quite annoying. But with createFunctor it's really easy:

int someFunction(float param1, bool param2);

Functor* myFunctor = createFunctor(&someFunction);

In this case, &someFunction is the function-pointer of the static function "someFuncton". For memberfunctions, this looks a bit different:

class SomeClass
{
    float someFunction(const std::string& param);
};

Functor* myFunctor = createFunctor(&SomeClass::someFunction);

Remember: This is just basic function-pointer knowledge, nothing special here. Functor does what it has to do and createFunctor works as usual.

Important: createFunctor uses new to create the Functor and returns a pointer. If you are responsible for the pointer, you have to delete the Functor after usage.

Call

To call the function, just use operator() and pass the arguments as if you would call the function-pointer directly:

void someFunction(int value);
Functor* myFunctor = createFunctor(&someFunction);

(*myFunctor)(10); // equivalent to someFunction(10);

Returnvalue

If your function returns a value, use getReturnvalue():

int doubleValue(int value) { return value*2; }
Functor* myFunctor = createFunctor(&doubleValue);

(*myFunctor)(10); // equivalent to doubleValue(10);

int result = myFunctor->getReturnvalue(); // result = 20

Information

There are some functions returning some information about the function:

  • getParamCount(): Returns the amount of parameters the function takes
  • hasReturnvalue(): Returns true if the function returns a value
  • getType(): Returns the type of the function as an enum: FT_MEMBER, FT_CONSTMEMBER, FT_STATIC
  • getTypenameParam(param number (0-4)): Returns the typename of the given parameter as a string
  • getTypenameReturnvalue(): Returns the typename of the returnvalue as a string

Types

There are two types of Functors: Functors for static functions and Functors for member functions. The following sections explain the difference.

FunctorStatic

C++ knows two types of static functions:

Static functions in a class:

class SomeClass
{
    static void someFunction();
};

And C functions outside of a class:

void someOtherFunction();

Both types are covered by FunctorStatic. FunctorStatic is in fact just a Functor, but you can use it to force static functions:

class SomeClass
{
    static void staticFunction();
    void nonstaticFunction();
};

FunctorStatic* functor1 = createFunctor(&SomeClass::staticFunction);    // this works
FunctorStatic* functor2 = createFunctor(&SomeClass::nonstaticFunction); // this fails

However, this would work:

Functor* functor2 = createFunctor(&SomeClass::nonstaticFunction);

FunctorMember

There are two types of member functions: constant and non-constant.

class SomeClass
{
    void constFunction() const;
    void nonconstFunction();
};

Both types are covered by FunctorMember, but in some cases you have to be aware of the intern difference.

FunctorMember is in fact just a Functor, but it needs an object to call the function. Just pass the object in front of the arguments when calling the function:

class SomeClass
{
    void someFunction(int value);
};

SomeClass* object = new SomeClass();
FunctorMember* functor = createFunctor(&SomeClass::someFunction);

(*functor)(object, 10); // this is equivalent to object->someFunction(10);

You can bind an object to a Functor by adding the object with setObject(object). If an object is bound to a Functor, you can call the functor without passing the object again:

class SomeClass
{
    void someFunction(int value);
};

SomeClass* object = new SomeClass();
FunctorMember* functor = createFunctor(&SomeClass::someFunction);

function->setObject(object); // binds object to the Functor

(*functor)(10); // this is equivalent to object->someFunction(10);

Note: If you add a constant object, you can only call the Functor if the assigned function-pointer leads to a constant function too.

Template and ambiguity

Examples

Attachments (1)

Download all attachments as: .zip