pointer-to-method callbacks in C++11/14/17? - c++

(A previous question of mine has similar wording and examples, but is asking something quite different.
Before I was asking for ideas for approaches. Now I'm asking how to get a specific approach to work.)
I have some subscription function that will call my callback when something happens. (Let's say it's a timer, and will pass me an object when a certain number of milliseconds elapses.) After looking at lambdas, std:function and std:bind I think the solution of pointers-to-methods is higher performance and simpler to write (especially for the subscriber) but I can't quite figure out the last bit.
This example mirrors my project a bit: we have a framework, represented by Foo, which is written once, and we'll have many subclasses represented here by Bar that will be written by people with more domain knowledge but less C++ knowledge. So, we want that call to SubscribeTimer() to be as simple as possible. Finally the application is high performance and we'd like to eliminate heap usage, including creating implicit std::bind objects and so on.
#include <iostream>
#include <functional>
using namespace std;
class Data { int i; };
class Foo {
public:
typedef void (Foo::*Timer_T)( Data* pd );
virtual void SubscribeTimer( int iMilliseconds, Timer_T pmethod );
virtual void SubscribeTimer( int iMilliseconds, std::function<void(Data*)> pfn ); // undesired
virtual void OnTimerA( Data* pd ) { cout << "Foo::OnTimerA called" << endl; };
};
void Foo::SubscribeTimer( int iMilliseconds, Timer_T pmethod ) {
Data d;
(this->*pmethod)( &d );
}
void Foo::SubscribeTimer( int iMilliseconds, std::function<void(Data*)> pfn ) { // undesired
Data d;
pfn( &d );
}
class Bar: public Foo {
public:
void Init();
virtual void OnTimerA( Data* pd ) { cout << "Bar::OnTimerA called" << endl; };
virtual void OnTimerB( Data* pd ) { cout << "Bar::OnTimerB called" << endl; };
};
void Bar::Init() {
// Works like I want it to: easy to subscribe, and high performance.
SubscribeTimer( 1000, &Foo::OnTimerA );
// What I'd like to do, but doesn't work.
//SubscribeTimer( 1000, &Bar::OnTimerB );
// Does exactly what I want except more complicated to write and I believe slower to run.
SubscribeTimer( 1000, std::bind( &Bar::OnTimerB, this, std::placeholders::_1 ) );
}
int main( int nArg, const char* apszArg[] ) {
Bar bar;
bar.Init();
}
As expected (if you overlook the requirement to write Foo::, not Bar:: in Init()'s call to SubscribeTimer()) the program outputs:
Bar::OnTimerA called (from the version of SubscribeTimer() I like)
Bar::OnTimerB called (from the version of SubscribeTimer() I think is too verbose/slow)
So this example works perfectly and does what I need... except that the subclass can only register handlers for method names the superclass has thought to define, whether or not they are defined or not. In reality, though, the subclass may wish to register many handlers for different events, with names tha superclass wouldn't know.
So in a sentence: how can I pass OnTimerB() into the method-pointer version of SubscribeTimer()? I'm happy to change Timer_T definition, SubscribeTimer() or whatever. As a floor though, there is no point in a member-pointer solution more complicated for the subclass than the std::function implementation, and no point in a solution slower than thestd::function implementation either. On the other hand, added complexity in the superclass isn't a problem, as it's write-once code.

To call Bar::OnTimerB, you need a pointer of type Bar. You therefore need to implement some kind of type erasure.
class Foo {
public:
template <typename Derived>
void SubscribeTimer(int iMilliseconds, void (Derived::*pmethod)(Data* pd)) {
auto const self = static_cast<Derived*>(this);
Data d;
(self->*pmethod)(&d);
}
};
Obviously, if you are going to have the callback invoked later, then you need to store this somehow. This is what std::function<> abstracts away for you. You could, of course, do that yourself, but std::function<> isn't that bad, especially on platforms with the small-function optimization.
You could therefore do the std::function wrapper internally:
template <typename Derived>
void SubscribeTimer(int iMilliseconds, void (Derived::*pmethod)(Data* pd)) {
SubscribeTimer(iMilliseconds,
[self = static_cast<Derived*>(this), pmethod](Data* pd) {
(self->*pmethod)(pd);
});
}

Related

C++ Call functions based on enum values

I have this code
class Foo {
private:
enum class Heuristic {
ONE,
TWO,
THREE
};
Heuristic h;
void select();
};
void Foo::select() {
if (h == Heuristic::ONE)
selectONE();
else if (h == Heuristic::TWO)
selectTWO();
else
selectTHREE();
}
void selectONE() {};
void selectTWO() {};
void selectTHREE() {};
Based on the value of heuristic I want to call a specific function in select(). I don't know the value of heuristic at compile time, as it depends on user input. To avoid the conditional check in select() I would like to use templates. How can I accomplish this?
As it depends on runtime values there is no way to get rid of some sort of runtime checks. Which are either done by you with if, switch, … or by a container like std::map, std::unordered_map
Due to that, your concern there should be readability and maintainability.
I would - like already suggested in a comment - use switch instead of if, but not because the compiler can optimize it better (IMHO the compiler will be able to generate the same code for both), but to allow the static analyzer to warn you about not used enums.
If the question is about performance concerns, then this should only be a problem if you call these functions at a high frequency. So if this is the case you could create a template-based entry point to your task, to which you pass the function as template argument based on the user selection:
template<auto SelectedHeuristic>
void Foo::task() {
for( /* … */ ) {
SelectedHeuristic();
}
}
void Foo::select() {
switch(h) {
case Heuristic::ONE:
Foo::task<selectONE>();
break;
case Heuristic::TWO:
Foo::task<selectTWO>();
break;
case Heuristic::THREE:
Foo::task<selectTHREE>();
break;
}
}
void selectONE() {};
void selectTWO() {};
void selectTHREE() {};
To avoid the conditional check in select() [...]
A simple way to avoid all conditional checks (hidden or otherwise) in select() could be to create an array of pointers to your functions. You then look the function up by using its current Heuristic value (which must start at 0 and not have any gaps). If the Heuristic value changes rarely, you can even move the lookup out of select() completely.
Example:
##include <iostream>
void selectONE() { std::cout << "one\n"; };
void selectTWO() { std::cout << "two\n"; };
void selectTHREE() { std::cout << "three\n"; };
using func_ptr_t = void(*)(); // the signature of your functions
class Foo {
public:
enum class Heuristic {
ONE,
TWO,
THREE
};
void set_heuristic(Heuristic); // a function to do the lookup
void select();
private:
Heuristic h;
func_ptr_t current_func; // a pointer to the selected function
};
void Foo::set_heuristic(Heuristic value) {
// a simple map from Heuristic value to function pointer
static const func_ptr_t funcmap[] = {
&selectONE,
&selectTWO,
&selectTHREE,
};
h = value; // perhaps not needed?
// look up the function pointer based on "h"
current_func = funcmap[static_cast<unsigned>(h)];
}
void Foo::select() {
// a pretty fast callsite:
current_func();
}
int main() {
Foo bar;
bar.set_heuristic(Foo::Heuristic::ONE);
bar.select(); // prints "one"
}
define a map<Heuristic, lambdas> where the lambdas are defined as
void and taking no parameters
void f()
then take the user input and get the value of that input key and trigger the lambda

Uses of pointers non-type template parameters?

Has anyone ever used pointers/references/pointer-to-member (non-type) template parameters?
I'm not aware of any (sane/real-world) scenario in which that C++ feature should be used as a best-practice.
Demonstation of the feature (for pointers):
template <int* Pointer> struct SomeStruct {};
int someGlobal = 5;
SomeStruct<&someGlobal> someStruct; // legal c++ code, what's the use?
Any enlightenment will be much appreciated!
Pointer-to-function:
Pointer-to-member-function and pointer-to-function non-type parameters are really useful for some delegates. It allows you to make really fast delegates.
Ex:
#include <iostream>
struct CallIntDelegate
{
virtual void operator()(int i) const = 0;
};
template<typename O, void (O::*func)(int)>
struct IntCaller : public CallIntDelegate
{
IntCaller(O* obj) : object(obj) {}
void operator()(int i) const
{
// This line can easily optimized by the compiler
// in object->func(i) (= normal function call, not pointer-to-member call)
// Pointer-to-member calls are slower than regular function calls
(object->*func)(i);
}
private:
O* object;
};
void set(const CallIntDelegate& setValue)
{
setValue(42);
}
class test
{
public:
void printAnswer(int i)
{
std::cout << "The answer is " << 2 * i << "\n";
}
};
int main()
{
test obj;
set(IntCaller<test,&test::printAnswer>(&obj));
}
Live example here.
Pointer-to-data:
You can use such non-type parameters to extend the visibility of a variable.
For example, if you were coding a reflexion library (which might very useful for scripting), using a macro to let the user declare his classes for the library, you might want to store all data in a complex structure (which may change over time), and want some handle to use it.
Example:
#include <iostream>
#include <memory>
struct complex_struct
{
void (*doSmth)();
};
struct complex_struct_handle
{
// functions
virtual void doSmth() = 0;
};
template<complex_struct* S>
struct csh_imp : public complex_struct_handle
{
// implement function using S
void doSmth()
{
// Optimization: simple pointer-to-member call,
// instead of:
// retrieve pointer-to-member, then call it.
// And I think it can even be more optimized by the compiler.
S->doSmth();
}
};
class test
{
public:
/* This function is generated by some macros
The static variable is not made at class scope
because the initialization of static class variables
have to be done at namespace scope.
IE:
class blah
{
SOME_MACRO(params)
};
instead of:
class blah
{
SOME_MACRO1(params)
};
SOME_MACRO2(blah,other_params);
The pointer-to-data template parameter allows the variable
to be used outside of the function.
*/
std::auto_ptr<complex_struct_handle> getHandle() const
{
static complex_struct myStruct = { &test::print };
return std::auto_ptr<complex_struct_handle>(new csh_imp<&myStruct>());
}
static void print()
{
std::cout << "print 42!\n";
}
};
int main()
{
test obj;
obj.getHandle()->doSmth();
}
Sorry for the auto_ptr, shared_ptr is available neither on Codepad nor Ideone.
Live example.
The case for a pointer to member is substantially different from pointers to data or references.
Pointer to members as template parameters can be useful if you want to specify a member function to call (or a data member to access) but you don't want to put the objects in a specific hierarchy (otherwise a virtual method is normally enough).
For example:
#include <stdio.h>
struct Button
{
virtual ~Button() {}
virtual void click() = 0;
};
template<class Receiver, void (Receiver::*action)()>
struct GuiButton : Button
{
Receiver *receiver;
GuiButton(Receiver *receiver) : receiver(receiver) { }
void click() { (receiver->*action)(); }
};
// Note that Foo knows nothing about the gui library
struct Foo
{
void Action1() { puts("Action 1\n"); }
};
int main()
{
Foo foo;
Button *btn = new GuiButton<Foo, &Foo::Action1>(&foo);
btn->click();
return 0;
}
Pointers or references to global objects can be useful if you don't want to pay an extra runtime price for the access because the template instantiation will access the specified object using a constant (load-time resolved) address and not an indirect access like it would happen using a regular pointer or reference.
The price to pay is however a new template instantiation for each object and indeed it's hard to think to a real world case in which this could be useful.
The Performance TR has a few example where non-type templates are used to abstract how the hardware is accessed (the hardware stuff starts at page 90; uses of pointers as template arguments are, e.g., on page 113). For example, memory mapped I/O registered would use a fixed pointer to the hardware area. Although I haven't ever used it myself (I only showed Jan Kristofferson how to do it) I'm pretty sure that it is used for development of some embedded devices.
It is common to use pointer template arguments to leverage SFINAE. This is especially useful if you have two similar overloads which you couldn't use std::enable_if default arguments for, as they would cause a redefinition error.
This code would cause a redefinition error:
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
void foo (T x)
{
cout << "integral";
}
template <typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
void foo (T x)
{
cout << "floating";
}
But this code, which utilises the fact that valid std::enable_if_t constructs collapse to void by default, is fine:
// This will become void* = nullptr
template <typename T, std::enable_if_t<std::is_integral<T>::value>* = nullptr>
void foo (T x)
{
cout << "integral";
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value>* = nullptr>
void foo (T x)
{
cout << "floating";
}
Occasionally you need to supply a callback function having a particular signature as a function pointer (e.g. void (*)(int)), but the function you want to supply takes different (though compatible) parameters (e.g. double my_callback(double x)), so you can't pass its address directly. In addition, you might want to do some work before and after calling the function.
It's easy enough to write a class template that tucks away the function pointer and then calls it from inside its operator()() or some other member function, but this doesn't provide a way to extract a regular function pointer, since the entity being called still requires the this pointer to find the callback function.
You can solve this problem in an elegant and typesafe way by building an adaptor that, given an input function, produces a customised static member function (which, like a regular function and unlike a non-static member function, can have its address taken and used for a function pointer). A function-pointer template parameter is needed to embed knowledge of the callback function into the static member function. The technique is demonstrated here.

Copy-and-swap done through interfaces

I'm trying to implement a copy+swap idiom to achieve strong-exception safety through a level of abstraction and, although the principle is clear, as it's often the case the devil is in the detail.
Say I have a class that looks like this:
class AConcreteType :
public ISomething,
public ISwappable
{
public:
// From ISwappable
void Swap( ISwappable& );
};
I can now do this within a method that only deals with ISomething:
void AClass::DoSomething( ISomething& something )
{
// say there is a function that allows me to clone 'something'
// Probably it ought to go into an auto_ptr, but for clarity:
ISomething& somethingElse( clone( something ) );
// ... so that at the end, after doing stuff with somethingElese I can do
ISwappable& swappable1 = dynamic_cast<ISwappable&>( something );
ISwappable& swappable2 = dynamic_cast<ISwappable&>( somethingElse );
// ... I may want to check that the concrete types behind the interface are
// actually the same too with something like typeid, but I'll leave that out for clarity
swappable1.Swap( swappable2 );
}
where
void AConcreteType::Swap( ISwappable& swappable )
{
AConcreteType& somethingConcrete = dynamic_cast<AConcreteType&>(swappable);
std::swap( *this, somethingConcrete );
}
This all works, as all the dynamic_casts are on references, which is an operation that throws when the type is not supported; this leaves my objects in a good state as the swap doesn't happen until the very end. But what I'm not comfortable with is the fact that the call swappable1.Swap(swappable2) can still throw (via the same dynamic_cast mechanism), and that would be counter-intuitive for the user of Swap as he would probably not expect anything to throw at that point.
An alternative I thought of was to template ISwappable so as to do away with the dynamic_cast inside the implementation of Swap:
template< typename T >
class ISwappable
{
public:
virtual void Swap( T& ) = 0;
};
so that its implementation is simply
class AConcreteType :
public ISomething,
public ISwappable<AConcreteType>
{
void Swap( AConcreteType& act ) { std::swap( *this, act ); }
};
This allows the Swap call to be non-throw (and allows me to guarantee that the two objects are actually swappable at compile-time), but the problem now is that I have to deal with a concrete type inside DoSomething, but I don't have access to AConcreteType inside that function.
Any ideas?
C++ isn't particularly geared toward inheritance based interfaces. For example, you're implementing a function that takes an ISomething, but it also expects the object to be an ISwappable. Languages geared toward using interfaces like this usually have a direct way to express requirements for multiple interfaces on a single type.
Instead it's probably better in C++ to use templates and then express requirements on those template parameters when necessary. Static assertions and type traits are a pretty simple and readable way of doing this in C++.
template<typename T,typename Interface>
struct implements {
static constexpr bool value = std::is_base_of<Interface,T>::value;
}
template<typename T>
void AClass::DoSomething(T &something ) {
static_assert(implements<T,ISomething>::value, "requires ISomething");
static_assert(implements<T,ISwappable<T>>::value, "requires ISwappable");
T somethingElse = clone(something);
something.Swap(somethingElse);
}
You might also want to move away from using inheritance for interfaces altogether. You can usually get the static type checking on your classes via static_asserts and type traits without inheritance:
template<typename T>
struct is_swappable { static constexpr bool value = ... };
class AConcreteType {
...
};
static_assert(is_swappable<AConcreteType>,"...");
template<typename T>
void AClass::DoSomething(T &something ) {
static_assert(is_something<T>::value, "requires something");
static_assert(is_swappable<T>::value, "requires swappable");
If you ask me, the idea of a ISwappable is already "ill-posed" since you cannot swap abstract types into each other without consequences... What you can swap safely are addresses of interfaces (pointers):
std::unique_ptr<ISomething> tI1(new AConcreteType(1)), tI2(new BConcreteType(2));
std::cout << tI1->IdentifyYourSelf() << std::endl; // -> prints "1"
std::cout << tI2->IdentifyYourSelf() << std::endl; // -> prints "2"
tI1.swap(tI2);
// contents are swapped now
std::cout << tI1->IdentifyYourSelf() << std::endl; // -> prints "2"
std::cout << tI2->IdentifyYourSelf() << std::endl; // -> prints "1"

static if in plain c++?

Problem in short:
How could one implement static if functionality, proposed in c++11, in plain c++ ?
History and original problem:
Recently I came up with a problem like this. I need a class Sender with an interface like
class Sender
{
void sendMessage( ... );
void sendRequest( ... );
void sendFile( ... );
// lots of different send methods, not important actually
}
In some cases I will need to create a DoubleSender, i.e. an instance of this class, which would call its methods twice, i.e. when calling, let's say, a sendMessage(...) method, the same message has to be sent twice.
My solutions:
First approach:
Have an isDouble member, and in the end of each method call make a check
sendMessage(...) { ... if( isDouble ) { sendMessage( ... ); }
Well, I don't want this, because actually I will need double posting very recently, and this part of code in time-critical section will be 98% passive.
Second approach:
Inherit a class DoubleSender from Sender, and implement its methods like:
void DoubleSender::sendMessage( ... )
{
Sender::sendMessage(...);
Sender::sendMessage(...);
}
Well, this is acceptable, but takes much space of unpleasant code (really much, because there are lots of different send.. methods.
Third approach:
Imagine that I am using c++11 :). Then I can make this class generic and produce the necessary part of code according to tempalte argument using static if:
enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
void sendMessage(...)
{
// do stuff
static if ( T == Single )
{
sendMessage(...);
}
}
};
This is shorter, easier to read than previous solutions, does not generate additional code and... it's c++11, which I unfortunately cannot use in my work.
So, here is where I came to my question - how can I implement static if analog in c++ ? Also, I would appreciate any other suggestions about how to solve my original problem.
Thanks in advance.
Quoting #JohannesSchaubLitb
with my static_if that works on gcc one can do it :)
in some limited fashion
(see also here)
This trick involves a specific GCC interpretation of the specs on Lambdas in C++11. As such, it will (likely) become a defect report against the standard. This will lead to the trick no longer working in more recent version of GCC (it already doesn't work in 4.7).
See the comment thread below for some more details from Johanness
http://ideone.com/KytVv:
#include <iostream>
namespace detail {
template<bool C>
struct call_if { template<typename F> void operator<<(F) { } };
template<>
struct call_if<true> {
template<typename F>
void operator<<(F f) { f(); }
};
}
#define static_if(cond) detail::call_if<cond>() << [&]
template<bool C, typename T>
void f(T t) {
static_if(C) {
t.foo();
};
}
int main() {
f<false>(42);
}
Why not make the send implementation a policy of the sender class and use CRTP:
template<class Derived>
class SingleSenderPolicy
{
public:
template< class memFunc >
void callWrapperImpl(memFunc f, ...)
{
static_cast<Derived *>(this)->f(...);
}
};
template< class Derived >
class DoubleSenderPolicy
{
public:
template< class memFunc >
void callWrapperImpl(memFunc f, ...)
{
static_cast<Derived *>(this)->f(...);
static_cast<Derived *>(this)->f(...);
}
};
template< class SendPolicy>
class Sender : public SendPolicy< Sender >
{
public:
void sendMessage( ... )
{
// call the policy to do the sending, passing in a member function that
// acutally performs the action
callWrapperImpl( &Sender::sendMessageImpl, ... );
}
void doSomethingElse( ... )
{
callWrapperImpl( &Sender::doSomethingElseImpl, ... );
}
protected:
void sendMessageImpl(... )
{
// Do the sending here
}
void doSomethingElseImpl(... )
{
// Do the sending here
}
};
The public sendXXX functions in you class simply forward to the call wrapper, passing in a member function that implements the real functionality. This member function will be called according to the SendPolicy of the class. CRTP saves the use of bind to wrap the arguments and this pointer up with the member function to call.
With one function it doesn't really cut down on the amount of code, but if you have a lot of calls it could help.
Note: This code is a skeleton to provide a possible solution, it has not been compiled.
Note: Sender<DoubleSenderPolicy> and Sender<SingleSenderPolicy> are completely different types and do not share a dynamic inheritance relationship.
Most compilers do constant folding and dead code removal, so if you write a regular if statement like this:
enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
void sendMessage(...)
{
// do stuff
if ( T == Single )
{
sendMessage(...);
}
}
};
The if branch will get removed when the code is generated.
The need for static if is when the statements would cause a compiler error. So say you had something like this(its somewhat psuedo code):
static if (it == random_access_iterator)
{
it += n;
}
Since you can't call += on non-random access iterators, then the code would always fail to compile with a regular if statement, even with dead code removal. Because the compiler still will check the syntax for before removing the code. When using static if the compiler will skip checking the syntax if the condition is not true.
std::string a("hello world");
// bool a = true;
if(std::is_same<std::string, decltype(a)>::value) {
std::string &la = *(std::string*)&a;
std::cout << "std::string " << la.c_str() << std::endl;
} else {
bool &la = *(bool*)&a;
std::cout << "other type" << std::endl;
}

What is the best way to expose a callback API - C++

I have a C++ library that should expose some system\ resource calls as callbacks from the linked application. For example: the interfacing application (which uses this library) can send socket management callback functions - send, receive, open, close etc., and the library will use this implementation in stead of the library's implementation.
(This way enables the application to manage the sockets by itself, can be useful).
This library has to expose also more callbacks, like, for example, a password validation, so I wonder if there is a preferred method to expose the callback sending option in one API.
Something like:
int AddCallbackFunc (int functionCallbackType, <generic function prototype>, <generic way to pass some additional arguments>)
Then within my library I will assign the callback to the appropriate function pointer according to the functionCallbackType parameter.
Is there any way to implement it in a generic way which will fit ANY function prototype and ANY additional arguments?
Your help will be more than appreciated...
Thanks!
Why not have it accept a 0 argument functor and just have the user use boost::bind to build the arguments into it before registering it? Basically example (calls instead of stores, but you get the point):
#include <tr1/functional>
#include <iostream>
void callback(const std::tr1::function<int()> &f) {
f();
}
int x() {
std::cout << "x" << std::endl;
return 0;
}
int y(int n) {
std::cout << "y = " << n << std::endl;
return 0;
}
int main(int argc, char *argv[]) {
callback(x);
callback(std::tr1::bind(y, 5));
}
EDIT: There is an option B, which is to basically implement what bind does under the hood with structures to store all the needed info and inheritance for polymorphism... it becomes a mess real quick. I would not recommend it, but it will work. You can also save from grief by forcing a return type of int, but that only saves you a little.
#include <iostream>
struct func_base {
virtual int operator()() = 0;
};
// make one of these for each arity function you want to support (boost does this up to 50 for you :-P
struct func0 : public func_base {
typedef int (*fptr_t)();
func0(fptr_t f) : fptr(f) {
}
virtual int operator()() { return fptr(); }
fptr_t fptr;
};
// demonstrates an arity of 1, templated so it can take any type of parameter
template <class T1>
struct func1 : public func_base {
typedef int (*fptr_t)(T1);
func1(fptr_t f, T1 a) : fptr(f), a1(a) {
}
virtual int operator()() { return fptr(a1); }
fptr_t fptr;
T1 a1;
};
void callback(func_base *f) {
(*f)();
}
int x() {
std::cout << "x" << std::endl;
return 0;
}
int y(int n) {
std::cout << "y = " << n << std::endl;
return 0;
}
int main(int argc, char *argv[]) {
// NOTE: memory leak here...
callback(new func0(x));
callback(new func1<int>(y, 5));
}
If you don't want to go for any of the C++ options available; std::tr1::function, functors, polymorphism with common base class etc. you can use the C method instead.
The client passes a callback and a pointer to its arguments as a void*, then the callback casts the void* to the correct type when it's called. You'll need to store the void* alongside the callback and you'll need to be very careful with object lifetimes.
int AddCallbackFunc (int type, int(*callback)(void*), void* callbackData)
It can be done, using a combination of template and type-erasure.
The idea is to take any type and wrap it into an object with a known interface.
class CallbackBase
{
public:
virtual ~CallbackBase();
virtual void execute();
};
template <class T>
class Callback: public CallbackBase
{
public:
explicit Callback(T functor): mFunctor(functor) {}
void execute() { mFunctor(); }
private:
T mFunctor;
};
And now, we can wrap it:
template <class Function>
int AddCallbackFunc (int functionCallbackType, Function f)
{
std::auto_ptr<CallbackBase> c(new Callback<Function>(f));
// do something with `c`.
}
I leave it up to you to bind the arguments, the no library way is to create a functor.
Sounds like you're looking for a Functor. Basically a class for each type of callback, with the arguments as data members and operator() to invoke the functionality.