gpt4 book ai didi

c++ - std::bind 到 void* 到 std::function

转载 作者:太空狗 更新时间:2023-10-29 21:33:11 26 4
gpt4 key购买 nike

我正在尝试制作一个事件系统该系统的用户必须执行此操作以添加输入事件,例如:

addEventHandler(Event::KEYBOARD_INPUT, reinterpret_cast<void*>(&std::bind(&Game::On_Input, this)));

传递的函数将在事件触发时调用,这些函数存储在 std::vectors 中,直到现在没有问题。但是不同的事件有不同的函数签名。由于 std::function 本身就是一个类型,我不能让这个函数接受所有事件我试图将 std::bind 转换为 void* 然后将其转换回 std::function 但它不会工作,因为 impl 未定义(0xCCCCCCCC)

当前代码:

void EventManager::addEventHandler(Event event, void* p_Fun)
{
if (event == Event::KEYBOARD_INPUT) {
m_InputCallbacks.push_back(*reinterpret_cast<std::function<void(Keycode, unsigned int)>*>(p_Fun));
}
/*else if(...){ // other events other push backs in other vectors

}*/
}

存储的函数是这样调用的:

void EventManager::HandleEvents(SDL_Event& Event)
{
while (PollEvent(&Event) != 0) {
if (Event.type == KEYDOWN || Event.type == KEYUP) {
//On_Input(Event.key.keysym.sym, Event.type);
for (auto inputCallbackFunc : m_InputCallbacks) {
inputCallbackFunc(Event.key.keysym.sym, Event.type);//CRASH HERE!
}
}
}
}

请注意,此版本仅处理输入我不知道将来会添加多少事件(碰撞、多人连接等),这就是为什么我想通过 addEventHandler 函数自动执行该过程,它将检查以下内容:1) 什么是事件类型并将 void 函数指针转换为该事件回调函数签名2) 将它们存储在适当的 std::vector

那么总而言之,如何让 AddEventHandler 接受传递给它的每个 std::bind 以便可以存储并在以后调用?

最佳答案

std::function 提供了存储单个类型的 std::vector 所需的所有类型删除,该类型具有您将调用它的签名.无需转换为 void*

为简单起见,您需要这样的东西。

#include <iostream>
#include <vector>
#include <functional>
#include <type_traits>
using namespace std;

enum Event
{
KEYBOARD_INPUT,
MOUSE_INPUT
};


std::vector< std::function<void(int,int)> > keyboard_handlers;
std::vector< std::function<void(int,int,int)> > mouse_handlers;



template <Event EventType,typename Func,
typename std::enable_if<EventType==KEYBOARD_INPUT,bool>::type=true>
void addEventHandler(Func&& func)
{
keyboard_handlers.push_back(
std::function<void(int,int)>(std::forward<Func>(func)));
}

template <Event EventType,typename Func,
typename std::enable_if<EventType==MOUSE_INPUT,bool>::type=true>
void addEventHandler(Func&& func)
{
mouse_handlers.push_back(
std::function<void(int,int,int)>(std::forward<Func>(func)));
}

void call_keyboard_handlers(int a,int b)
{
for (auto inputCallbackFunc : keyboard_handlers) {
inputCallbackFunc(a,b);
}
}


void keyboard_callback_1(std::string name, int a , int b)
{
std::cout << "keyboard_callback_1 " << name << " " << a << " " << b << std::endl;
}

void keyboard_callback_2(int a , int b)
{
std::cout << "keyboard_callback_2 " << a << " " << b << std::endl;
}

struct keyboard_callback_3_type
{
void operator()(int a,int b)
{
std::cout << "keyboard_callback_3 " << a << " " << b << std::endl;
}
};

int main() {
//With an extra bound in string argument.
addEventHandler<KEYBOARD_INPUT>(std::bind(&keyboard_callback_1,"somestring",std::placeholders::_1,std::placeholders::_2));
//From a plain function pointer
addEventHandler<KEYBOARD_INPUT>(&keyboard_callback_2);

//From a memberfunction pointer
keyboard_callback_3_type keyboard_callback_3;
addEventHandler<KEYBOARD_INPUT>(std::bind(&keyboard_callback_3_type::operator(),&keyboard_callback_3,std::placeholders::_1,std::placeholders::_2));

//From a non capturing lambda
addEventHandler<KEYBOARD_INPUT>([](int a,int b){ std::cout << "lambda_callback " << a << " " << b <<std::endl;});

std::string capture = "Captured";
//From a capturing lambda
addEventHandler<KEYBOARD_INPUT>([&](int a,int b){ std::cout << "lambda_callback " << capture << " " << a << " " << b <<std::endl;});


call_keyboard_handlers(10,20);

return 0;
}

Demo

请注意,如果您想将函数名称保留为 addEventHandler,您将必须根据事件类型启用该函数的不同变体(如示例中所示),或者以不同的方式命名它们(即 addKeyboardEventHandler、addMouseEventHandler 等。)

关于c++ - std::bind 到 void* 到 std::function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52358944/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com