How do I use bind to pass a member function as a function pointer?

こ雲淡風輕ζ 提交于 2019-12-05 00:39:03

问题


I'm trying to pass a member function as a function pointer so that I don't need to rely on singletons or global functions to handle Qt messages in Qt 5. As far as I can tell my std::function is of the correct type, it has the correct signature, and bind should be allowing me to jam in the implicit this pointer, essentially passing off a member function as a global/un-owned function.

void ProgramMessageHandler::setAsMessageHandlerForProgram() {
    std::function<void(QtMsgType, const QMessageLogContext &, const QString &)> funcPtr;

    funcPtr = std::bind(handleMessages, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);

    qInstallMessageHandler(funkPtr);
}

This doesn't compile. I can succesfully create my funcPtr variable but passing it into the qInstallMessageHandler function causes the following:

log\ProgramMessageManager.cpp:16: error: cannot convert 'std::function<void(QtMsgType, const QMessageLogContext&, const QString&)>' to 'QtMessageHandler {aka void (*)(QtMsgType, const QMessageLogContext&, const QString&)}' for argument '1' to 'void (* qInstallMessageHandler(QtMessageHandler))(QtMsgType, const QMessageLogContext&, const QString&)'
 oldHandler = qInstallMessageHandler(hackedPointerToHandleFunction);
                                                                  ^

I have read:

how to pass a member function as a function pointer?

How do you pass a member function pointer?

How to pass a member function as a parameter to a function that doesn't expect it?

Get function pointer from std::function when using std::bind

but none have helped me.

EDIT:

So it has been said that this isn't possible without a singleton or a global funtion... but why? The only difference between a member function and a global function with the same signature is that they don't have the same signature, there is an implicit this pointer as the first parameter to a member function.

Knowing that, why cannot I use std::bind to bridge this gap, by saying 'I know that the function being called takes the this argument before all of the others, force it in there, be the thing that knows about this. That would be so much cleaner than a singleton and a global function is just crap.


回答1:


You are trying to pass a class instance where a function pointer is expected, while no such conversion exists.

You could do something like this:

class ProgramMessageHandler
{
  static void  myMessageHandler(QtMsgType, const QMessageLogContext &, const QString &);
};

in main.cpp (for example):

...
qInstallMessageHandler(ProgramMessageHander::myMessageHandler);
...

You still might have to deal with some issues as in singleton classes, but I think it makes sense that there is one message handler or at least one dispatcher that would somehow redirect different message to appropriate handlers. Hope this helps




回答2:


The result of std::bind is a function object and, as the error message says, you cannot convert a function object to a function pointer. A function pointer cannot store the this pointer like std::function can, you can't just "force it in there".

The only way to do something approaching what you want is to use a singleton to store the this pointer:

class ProgramMessageHandler {
private:
  static ProgramMessageHandler* currentHandler;
  void handleMessagesImpl(const std::string& message);
public:
  void setAsMessageHandlerForProgram(){
    currentHandler = this;
    qInstallMessageHandler(handleMessages);
  }
  static void handleMessages(const std::string& message) { 
    if (currentHandler) 
      currentHandler->handleMessagesImpl(message);
  }
};

ProgramMessageHandler* ProgramMessageHandler::currentHandler = nullptr;

int main() {
  ProgramMessageHandler handler;
  handler.setAsMessageHandlerForProgram();

  // trigger messages...
}

Live demo.



来源:https://stackoverflow.com/questions/32583771/how-do-i-use-bind-to-pass-a-member-function-as-a-function-pointer

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!