Почему бы ему не принять аргумент 0 функтор и просто заставить пользователя использовать boost::bind
для встраивания аргументов в него перед его регистрацией? В основном пример (звонки вместо магазинов, но вы получаете точку):
#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));
}
РЕДАКТИРОВАТЬ: Существует опция B, которая в основном реализует то, что bind делает под капотом, со структурами для хранения всей необходимой информации и наследования для полиморфизма ... это очень быстро становится беспорядком. Я не рекомендовал бы это, но это будет работать. Вы также можете спасти от горя, принудительно возвращая тип int
, но это только немного экономит.
#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));
}