如何创建一个充满 C 风格函数指针和 lambda 的向量(有和没有捕获)

How to create a vector filled with C-Style function pointers and lambdas(with and without captures)

我最近一直在学习 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() 函数不兼容。但是由于许多不同的 classes 应该能够创建这样的 lambda 并且没有任何捕获的 lambda 应该包含在向量中,我不知道如何判断向量应该是什么类型。我听说过 std::function 但是(这听起来很傻)我想使用 C 风格的方式来更好地理解。我认为 post 对此有所说明,但我不太理解。我考虑过创建两张地图,一张用于所有无捕获 lambda,另一张用于其他。然后我可以让每个 class 继承自基 class 并使向量中的捕获类型成为指向基 class 的指针,尽管这非常复杂并且增加了不必要的开销而且我不甚至不知道这是否可行。 这种情况的一般解决方案是什么?

感谢所有回复和最诚挚的问候,

丹尼尔·施赖伯·门德斯 :)

编辑:
回调现在看起来像这样: typedef std::function< void(sf::Event const&) > Callback; 当我想使用它时:

//inside the Button Constructor
inputhandler.registerEvent(sf::Event::MouseButtonPressed, Callback([this](sf::Event const& event)
        {
            //memberFunc();
        }));

这并没有给我一个错误,而是以错误的方式表现。它确实执行了 lambda,但没有更改定义它的 class。所以我在构造函数中添加了一行,它只打印刚刚创建的对象的地址。我只创建了一个按钮,因此应该只打印一个地址。但是有两个不同。这意味着当将包裹在 std::function 中的 lambda 插入向量时,将创建一个新的 Button 对象。怎么可能?隐式对象创建?

感谢您的回答:)

带捕获的 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 确实会简单得多,它会为您完成所有这些工作。