将成员函数和 lambda 传递给 std::function
Passing both member functions and lambdas to std::function
我正在尝试创建 control/window 类似于在 C# Windows Forms/WPF 中完成的事件。每个事件 class 都包含一个参数类型并传递该类型以及指向发送对象的指针。当使用 lambda 函数时,这一切都很好,但当我尝试向事件添加成员函数时,我得到了 C2276 '&': illegal operation on bound member function expression
和 C2660 'Event<MouseButtonEventArgs>::add': function does not take 1 arguments
.
的编译错误
我如何创建一个可以从任何 class 获取 lambda 函数和成员函数的事件 class(无论 class 是否是 "sender")?
Event.h
template<class Args> struct EventListener {
/* The function type to be called by the event. */
typedef function<void(ControlBaseSPtr, Args&)> ArgsFunction;
string name;
ArgsFunction function;
};
template<class Args> class Event {
/* The function type to be called by the event. */
typedef function<void(ControlBaseSPtr, Args&)> ArgsFunction;
deque<EventListener<Args>> listeners;
Event(EventDirections direction) {
this->direction = direction;
}
void add(const string& name, ArgsFunction function) {
EventListener<Args> listener = EventListener<Args>(name, function);
for (auto it = listeners.begin(); it != listeners.end(); it++) {
if (it->name == name) {
throw exception("Event::operator+= listener already exists in the event");
}
}
listeners.push_back(listener);
}
//...
};
Control.h
class ControlBase {
Event<MouseEventArgs> _eventMouseMovedGlobal;
Event<MouseButtonEventArgs> _eventMouseButtonGlobal;
ControlBase();
void onMouseMovedGlobal(ControlBaseSPtr sender, MouseEventArgs e);
};
Control.cpp
ControlBase::ControlBase() {
// Works
_eventMouseButtonGlobal.add("some name", [](ControlSPtr control, MouseButtonEventArgs e){
//...
};
// Doesn't work
_eventMouseMovedGlobal.add("some name", bind(&onMouseMovedGlobal, this, placeholders::_2))
// Doesn't work
_eventMouseMovedGlobal.add("some name", bind(&onMouseMovedGlobal, this))
}
void ControlBase::onMouseWheelGlobal(ControlBaseSPtr sender, MouseWheelEventArgs e) {
//...
}
好吧,由于 onMouseMovedGlobal
有 2 个输入参数,因此在创建活页夹时您需要为它们提供占位符或值。所以,而不是
_eventMouseMovedGlobal.add("some name", bind(&onMouseMovedGlobal, this, placeholders::_2))
你需要
_eventMouseMovedGlobal.add("some name", bind(&ControlBase::onMouseMovedGlobal, this, placeholders::_1, placeholders::_2))
我正在尝试创建 control/window 类似于在 C# Windows Forms/WPF 中完成的事件。每个事件 class 都包含一个参数类型并传递该类型以及指向发送对象的指针。当使用 lambda 函数时,这一切都很好,但当我尝试向事件添加成员函数时,我得到了 C2276 '&': illegal operation on bound member function expression
和 C2660 'Event<MouseButtonEventArgs>::add': function does not take 1 arguments
.
我如何创建一个可以从任何 class 获取 lambda 函数和成员函数的事件 class(无论 class 是否是 "sender")?
Event.h
template<class Args> struct EventListener {
/* The function type to be called by the event. */
typedef function<void(ControlBaseSPtr, Args&)> ArgsFunction;
string name;
ArgsFunction function;
};
template<class Args> class Event {
/* The function type to be called by the event. */
typedef function<void(ControlBaseSPtr, Args&)> ArgsFunction;
deque<EventListener<Args>> listeners;
Event(EventDirections direction) {
this->direction = direction;
}
void add(const string& name, ArgsFunction function) {
EventListener<Args> listener = EventListener<Args>(name, function);
for (auto it = listeners.begin(); it != listeners.end(); it++) {
if (it->name == name) {
throw exception("Event::operator+= listener already exists in the event");
}
}
listeners.push_back(listener);
}
//...
};
Control.h
class ControlBase {
Event<MouseEventArgs> _eventMouseMovedGlobal;
Event<MouseButtonEventArgs> _eventMouseButtonGlobal;
ControlBase();
void onMouseMovedGlobal(ControlBaseSPtr sender, MouseEventArgs e);
};
Control.cpp
ControlBase::ControlBase() {
// Works
_eventMouseButtonGlobal.add("some name", [](ControlSPtr control, MouseButtonEventArgs e){
//...
};
// Doesn't work
_eventMouseMovedGlobal.add("some name", bind(&onMouseMovedGlobal, this, placeholders::_2))
// Doesn't work
_eventMouseMovedGlobal.add("some name", bind(&onMouseMovedGlobal, this))
}
void ControlBase::onMouseWheelGlobal(ControlBaseSPtr sender, MouseWheelEventArgs e) {
//...
}
好吧,由于 onMouseMovedGlobal
有 2 个输入参数,因此在创建活页夹时您需要为它们提供占位符或值。所以,而不是
_eventMouseMovedGlobal.add("some name", bind(&onMouseMovedGlobal, this, placeholders::_2))
你需要
_eventMouseMovedGlobal.add("some name", bind(&ControlBase::onMouseMovedGlobal, this, placeholders::_1, placeholders::_2))