受到此处有关SO(C++ callback using class member)的另一篇文章的启发,我试图编写一个通用的CallbackHandler。
CallbackHandler.hpp
#pragma once
#include <functional>
template <typename CallbackClass, typename CallbackArgType>
class CallbackHandler
{
public:
std::function<void(CallbackArgType ct)> m_callbackFunc;
CallbackHandler(CallbackClass * handler, std::function<void(CallbackArgType)> method)
{
//m_callbackFunc is supposed to stand for a member to pointer callback function with one
//parameter of any type
m_callbackFunc = std::bind(method, handler, std::placeholders::_1);
}
};
#include "wrapper_T.cpp"
我想在其他几个模板化的命名空间/类中使用它,例如:
wrapper.hpp
//this wrappers main purpose is to combine the constructor of a non templated class (MyModule)
//and hold a (global) callback method for it (m_parentCallback)
namespace wrapper
{
extern std::function<void(wxImage *)> m_parentCallback;
template<typename ParentClass>
MyModule GetNewModule(ParentClass* parent, void (ParentClass::* method)(wxImage *));
}
wrapper.cpp
namespace wrapper
{
//This is only to avoid multiple definition error - actual definition is in wrapper_T.cpp
std::function<void(wxImage *)> m_parentCallback;
}
wrapper_T.cpp
namespace wrapper
{
template<typename ParentClass>
MyModule GetNewModule(ParentClass* parent, void (ParentClass::* method)(wxImage *))
{
//the callback type of this wrapper/class is wxImage*
std::shared_ptr<CallbackHandler<ParentClass, wxImage*>> handler =
std::make_shared< CallbackHandler<ParentClass, wxImage*>>(parent, method);
//EDIT - SOLVED: <- Error C2664: Cant convert argument 2 from "void (__thiscall MyModule::*)(void)" to "std::function<void(wxImage*)>"
m_parentCallback = std::bind(&CallbackHandler<ParentClass, wxImage*>::m_callbackFunc, handler, std::placeholders::_1);
//<- Error C2679: no suitable binary operator "=" found
return std::make_unique<MyModule>();
}
}
我想这样使用回调:
MyModule.cpp
wrapper::m_parentCallback(&img);
我想像这样初始化整个事情:
MainClass.cpp
MainClass::MainClass()
{
//declared in header: std::unique_ptr<MyModule> module
module = std::move(wrapper::GetNewModule(this, &MainClass::CallbackFunc));
}
void MainClass::CallbackFunc(wxImage * img)
{ /* do something with it */ }
我有一个带有“ this”指针和指向方法“ CallbackFunc”的指针的类,应该没问题。但是我看不到如何将我的CallbackHandler类用于std :: function回调指针。
或者我是否在包装器中保存了指向CallbackHandler方法的指针的方法,而该方法则保存了实际回调方法的方法?
所有这些都不是设计选择,我只希望CallbackHandler可移植并且可以工作,同时具有易于使用的接口。
编辑:我试图在代码上应用注释建议,但是我很快声称第一个问题已解决。该错误仅被下一个错误隐藏。如果我尝试仅使用以下行进行编译:
std::shared_ptr<CallbackHandler<ParentClass, wxImage*>> handler =
std::make_shared< CallbackHandler<ParentClass, wxImage*>>(parent, method);
//<- Error C2664: "CallbackHandler<ParentClass,wxImage *>::
//CallbackHandler(CallbackHandler<ParentClass,wxImage *> &&)"
//: converting argument 2 from "void (__thiscall MyFrame::* )(wxImage *)"
//to "std::function<void (wxImage *)>" not possible
// with
// [
// ParentClass=MyFrame
]
//(freely translated into english by me)
因此,缺少的论点不是唯一的问题。如果方法(成员函数)上的std :: bind不起作用,我也必须更改CallbackClass,不是吗?也许遵循这些原则:
std::function<void(CallbackArgType cat)> m_callbackFunc;
CallbackHandler(CallbackClass * handler, std::function<void(CallbackArgType)> method)
{
//m_callbackFunc = std::bind(method, handler, std::placeholders::_1);
m_callbackFunc = [method](auto img) { method(img); };
}
替换
m_parentCallback = std::bind(&CallbackHandler<ParentClass, wxImage*>::m_callbackFunc, handler, std::placeholders::_1);
with
m_parentCallback = [handler](auto img){ handler->m_parentCallback(img); };
我不认为bind
旨在与成员函子对象一起使用。但是lambda可以无缝处理。