Согласно комментариям, вы можете использовать либо std::function
, либо структуру, похожую на предлагаемую here.
следует, минимальный и рабочий пример второго предложения:
class Dispatcher {
Dispatcher() { }
template<class C, void(C::*M)() = C::receive>
static void invoke(void *instance) {
(static_cast<C*>(instance)->*M)();
}
public:
template<class C, void(C::*M)() = &C::receive>
static Dispatcher create(C *instance) {
Dispatcher d;
d.fn = &invoke<C, M>;
d.instance = instance;
return d;
}
void operator()() {
(fn)(instance);
}
private:
using Fn = void(*)(void *);
Fn fn;
void *instance;
};
struct S {
void receive() { }
};
int main() {
S s;
Dispatcher d = Dispatcher::create(&s);
d();
};
Заметьте, что он должен быть соответствующим образом изменен с вашими требованиями (в настоящее время, целевой метод член не имеет возвращаемого значения и не принимает аргументов).
Кроме того, он может быть легко расширен, чтобы хранить массив методов-членов-мишеней, вот что вы искали: просто сохраните вектор пар instance
s и invoke
функций.
Кроме того, вы можете использовать вариационный шаблон с функцией Dispatcher
, чтобы он был более гибким. Таким образом, вы сможете определить Dispatcher
с разными типами возвращаемых типов и списков аргументов.
РЕДАКТИРОВАТЬ
Отсюда следует пример Dispatcher
, который принимает более чем одну функцию целевого члена.
Чтобы расширить его с помощью вариационного шаблона, как указано выше, все еще достаточно просто.
#include <vector>
#include <utility>
class Dispatcher {
template<class C, void(C::*M)() = C::receive>
static void invoke(void *instance) {
(static_cast<C*>(instance)->*M)();
}
public:
template<class C, void(C::*M)() = &C::receive>
void bind(C *instance) {
auto pair = std::make_pair(&invoke<C, M>, instance);
targets.push_back(pair);
}
void operator()() {
for(auto pair: targets) {
(pair.first)(pair.second);
}
}
private:
using Fn = void(*)(void *);
std::vector<std::pair<Fn, void*>> targets;
};
struct S {
void receive() { }
};
struct T {
void receive() { }
};
int main() {
S s;
T t;
Dispatcher d;
d.bind(&s);
d.bind(&t);
d();
};
Пожалуйста, обратите внимание, что в приведенных выше примерах нет никакой гарантии, что указатель, представленный в instance
все еще действует один раз на самом деле используется. Вы должны либо позаботиться о жизни ваших связанных объектов, либо немного изменить пример, чтобы ввести более безопасный дескриптор.
Посмотрите на [std :: function] (http://en.cppreference.com/w/cpp/utility/functional/function). –
[This] (http://blog.molecular-matters.com/2011/09/19/generic-type-safe-delegates-and-events-in-c/) также может быть хорошим моментом, из которого можно Начало. – skypjack