如何创建由C样式函数指针和lambda填充的矢量(有和没有捕获)

问题描述 投票:0回答:1

最近我一直在学习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:)

c++ lambda function-pointers member-function-pointers
1个回答
0
投票

具有捕获功能的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为您完成所有这些工作确实要简单得多。

© www.soinside.com 2019 - 2024. All rights reserved.