Я хочу зарегистрировать функции обратного вызова и сохранить их в векторе для их вызова. Также должно быть разрешено использовать функции-члены в качестве функций обратного вызова.Member function как параметр для шаблона функции
Мой первоначальный был подход с использованием <functional>
следующим образом:
#include <functional>
#include <vector>
#include <iostream>
std::vector<std::function<void()>> functions;
struct Foo {
void Bar() {
std::cout << "Hello" << std::endl;
}
};
template<class T>
void Register(T* obj, std::function<void(T*)> function) {
functions.push_back(std::bind(function, obj));
}
void main(){
Foo foo;
Register(&foo, &Foo::Bar);
}
Это не работает, так как компилятор не может вывести тип параметра. Он работает только в том случае, если я укажу тип явно: Register<Foo>(&foo, &Foo::Bar);
. Это не то, что я хотел, поэтому я попытался использовать старые указатели функций:
template<class T>
void Register(T* obj, void(T::* function)()) {
functions.push_back(std::bind(function, obj));
}
И это сработало. Так как я не люблю эту форму указателей на функции я сделал тип для указателей Memberfunction:
template<class Owner>
using Memberfunction = void(Owner::*)();
template<class T>
void Register(T* obj, Memberfunction<T> function) {
functions.push_back(std::bind(function, obj));
}
Это работало просто отлично. Но теперь я хотел поддерживать функции с одним единственным параметром, так как я не хотел указывать функцию-член для каждого типа параметра, я хотел снова использовать шаблоны.
template<class Owner, class Param>
using Memberfunction = void(Owner::*)(Param);
template<class T>
void Register(T* obj, Memberfunction<T,float> function) {
using namespace std::placeholders;
functions.push_back(std::bind(function, obj, _1));
}
Это работало хорошо до сих пор, но я не хочу, чтобы задать функцию члена для одного или нет параметра, поэтому я хотел бы использовать void
в качестве второго параметра Memberfunction
, но это приведет к внутренняя ошибка компилятора, поэтому я думаю, что это не работает.
Интересно Memberfunction<Foo,void> bar = &Foo::Bar;
приводят к следующей ошибке:
cannot convert from 'void (__thiscall Foo::*)(void)' to 'void (__thiscall Foo::*)(void)'
Так что теперь мои вопросы:
ли это как-то можно использовать std::function
для этого?
Если это не помогает, я могу избежать указания как минимум двух типов функций-членов?
Заранее за вашу помощь.
Мне просто интересно, есть причина, вы не хотите использовать 'зЬй :: bind' при вызове' Register' функцию, т.е. 'Register (станд :: привязывать (...)) '? –
Это тоже была идея, но я хотел сделать эту функцию максимально простой в использовании. И я думаю, что необходимость использования 'std :: bind' для регистрации функции обратного вызова не так понятна, как просто использование функции-члена. Я сам давно этого не знал и использовал lamdas для инкапсуляции вызова функции, а это не лучший подход, я думаю. – Grimkin
Ну, если вы просто передали вызываемый объект, то вам было бы намного легче!). Тогда также можно было бы использовать другие вызываемые объекты, такие как функции, не являющиеся членами, или лямбда. –