Introduction
Sometimes functions only differ in a few things you cannot express by using variables, what you really love to do is passing a function that can handle the 'special' case and keep your abstraction nice. In some languages like Scheme, you can pass functions as arguments; in C++, you have to use function pointers.
Function pointers are a good system for C, but not for C++; you have to define a non-class member or static class member... So, we cannot access non-static data members of a class without using global variables.
The solution is creating a wrapper around the function pointers that contains the function pointer and a pointer to the class.
Note: an alternative used by STL are function objects; I don't like this approach since it causes too much type-work ;).
Usage
I'll describe a short guide on how to incorporate/use the function pointer wrappers.
- Add the following statements to your header file:
...
#include "functor.h"
...
- (optional) Do a
typedef
of the templated function pointer, this makes it much easier to read :).
It is recommended to make this typedef
inside your class definition, to prevent polluting your global namespace. I usually place them in the private declarations of my class.
typedef Functor<Test, void, int> Function;
In this example, Test
is the class that contains the function, void
is the return value of the function, and int
is the only argument of the function.
- Define your class, I added a quick sample of a class here:
class Test
{
public:
void TestFunc();
private:
void Add(int x);
void Mul(int x);
void DoSomething(int x, Function f);
int value_;
};
void Test::Add(int x)
{
value_ += x;
}
void Test::Mul(int x)
{
value_ *= x;
}
void Test::DoSomething(int x, Function f)
{
...
f(x);
...
}
In the example, you should note f(x)
, this is the calling of the function pointer wrapper. Looks exactly like a regular function call, but the f
is an argument of the function.
- Create the function pointer wrapper:
void Test::TestFunc()
{
Function myadd(this, &Test::Add);
Function mymul(this, &Test::Mul);
DoSomething(5, myadd);
}
You create a wrapper object just by passing two arguments to the constructor: the host class of the functions, usually a this
, and the name of the method that the wrapper should use.
You can now pass the function to any method and call it as it was a normal function :)
Technical Stuff
The system of the wrapper is based on the usage of templates and operator overloading. Templates are used to make it more generic (i.e., to be able to create a wrapper for any function with a specified number of arguments). The operator overloading is used to simulate a regular procedure call, we overload the operator()
to achieve this.
Known Limitations
The source code only contains a wrapper for 1 and 2 arguments. If you need more, you'll need to extend the classes or pass a struct
/class
that contains the data as single argument.
Todo
- Compatibility with
const
member functions
- Create an example project
- Create an inline version for compatibility with VC++ 6 or lower.
History