最近我一直在学习lambda和函数指针,并希望在简单的回调系统中使用它们。存储事件以及触发事件时应调用的所有回调的映射如下所示:std::unordered_map< sf::Event::EventType , std::vector< Callback > > eventMap;
。
我以此方式定义了回调typedef void(*Callback)(sf::Event const&);
。我的registerEvent()
函数将一个事件和一个回调作为参数。然后可以这样调用registerEvent()
:
inputHandler.registerEvent(/*Any event type*/, [](sf::Event const&)
{
//do something
});
效果很好,但是当我要捕获对象时,出现编译错误,提示error: no matching function for call to ‘InputHandler::registerEvent(sf::Event::EventType, Button::Button(ID, Callback, InputHandler&)::<lambda(const sf::Event&)>)’
产生该错误的代码如下:
class Button
{
//
public:
Button(ID id, Callback callback, InputHandler& inputhandler)
{
inputhandler.registerEvent(sf::Event::MouseButtonPressed, [this](sf::Event const&)
{
{
getTextureRect();
}
});
}
};
[似乎this
捕获正在更改lambda的类型,这使其与registerEvent()
函数不兼容。但是,由于许多不同的类应该能够创建这样的lambda,并且向量中也应包含没有任何捕获的lambda,因此我不知道如何判断向量应为哪种类型。我听说过std::function
,但(听起来可能很愚蠢)我想使用C-Style方式来更好地理解。我认为this帖子对此有所说明,但我不太了解。我考虑过要创建两张地图,一张地图用于所有不带捕获功能的lambda,而另一张地图则用于其他地图。然后,我可以让每个类都从基类继承,并使向量中的捕获类型成为指向基类的指针,尽管这非常复杂,并且会增加不必要的开销,而且我什至不知道这样做是否可行。对于这种情况,一般的解决方案是什么?
感谢所有答复和最诚挚的问候,
[Daniel Schreiber Mendes:)
具有捕获功能的Lambda无法转换为函数指针。一个普通的函数指针没有任何地方可以存储lambda捕获的状态。
[std::function
是一个对象,因此可以存储带或不带捕获的lambda。
如果必须使用原始函数指针,则需要存储一个函数指针和一个状态,然后在调用它时将状态传递给该函数。例如
typedef void(*Callback)(sf::Event const&, void* data);
std::unordered_map< sf::Event::EventType , std::vector< std::pair< Callback, void* > > > eventMap;
然后,您需要将状态存储在一个对象中,将该对象存储在某个位置,以使其保持活动状态。在对象内部,您需要从void*
强制转换回状态对象指针。如果您不使用需要普通函数指针的c库,那么仅使用std::function
为您完成所有这些工作确实要简单得多。