具有方法回调指针的通用回调模板类

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

受到此处有关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); };
}

c++ templates callback function-pointers std-function
1个回答
0
投票

替换

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可以无缝处理。

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