-1

I have a QThread based class, basically a GUI thread. In this thread I'm using another class which have this function type definition:

void SomFunc(const std::function<void (int, std::string, int)> &data)

I want to create a callback function in my class like MyThread::Callback and call above function and pass my MyThread::Callback function as actual callback function. Whatever I try, I miss something at the end, I'm really confused with std::function thing and need help. How do I define a function that I can pass as argument to SomFunc and get proper callbacks in my MyThread class context

If I simply create a void function this is what I get:

error: reference to type 'const std::function<void (int, std::string, int)>' (aka 'const function<void (int, basic_string<char>, int)>') could not bind to an rvalue of type 'void (MyClass::*)(int, std::string, int)'

zawarasal
  • 11
  • 3
  • What do you mean by "miss something at the end"? Have you tried `void f(int, std::string, int) {}`? – nwp May 12 '19 at 20:09
  • How do I pass this f to SomFunc? @nwp – zawarasal May 12 '19 at 20:11
  • `SomFunc(f);`. That seems like a trick question though. – nwp May 12 '19 at 20:17
  • error: reference to type 'const std::function' (aka 'const function, int)>') could not bind to an rvalue of type 'void (MyClass::*)(int, std::string, int)' @nwp – zawarasal May 12 '19 at 20:19
  • You used a member function that is part of `MyClass`, not a free function. It's probably a duplicate of [this question](https://stackoverflow.com/questions/23962019/how-to-initialize-stdfunction-with-a-member-function). – nwp May 12 '19 at 20:21
  • Saw that question, but couldn't make it work in my case with std::bind @nwp – zawarasal May 12 '19 at 20:23
  • You didn't "simply create a void function". You created a member function. You should show that function, ideally with a [MCVE]. Also you should show your `std::bind` attempt so people can figure out what went wrong. Currently there is only guessing. Also try the lambda solution. It should be easier and better. – nwp May 12 '19 at 20:26
  • I tried lambda, but function inside lambda can't access anything outside my lambda function (e.g. objects in mainwindow), its a QT MainWindow GUI class. When I call SomFunc and I expect the callback, result of Callback should update label in QT GUI. That function doesn't have anything just a callback skeleton that will set QT label value to what I get in callback @nwp – zawarasal May 12 '19 at 20:28
  • 1
    You have to capture the things you want to access. `[variable]` to make a copy and `[&variable]` to capture a reference (make sure the referenced variable has not died when the function is called). You might need to do `[this]` to capture the window which gives you access to all the MainWindow stuff. You can capture multiple things with `[variable, this, &other_variable]`. – nwp May 12 '19 at 20:31
  • For the function above like in your `f` function and my SomeFunc, can you give me an example with the [this] you mention? How do I call SomFunc and pass pointer to f function thats member of `this` / `MainWindow`? @nwp – zawarasal May 12 '19 at 20:39
  • `SomeFunc([this](int i, std::string s, int j){ f(i, s, j); });`. If it complains that you didn't capture some variable add it to the list in the `[]`. – nwp May 12 '19 at 20:42
  • @nwp Thank you very much!! That did the trick – zawarasal May 12 '19 at 20:57

1 Answers1

0

You can do as follows:

#include <iostream>
#include <string>

void f(int a, std::string b, int c)
{
    std::cout << a << " -- " << b << " -- " << c << std::endl;
}

void someFunc(void (inner)(int, std::string, int), int a, std::string b, int c)
{
    inner(a, b, c);
}

int main()
{
    int a = 5;
    std::string b("text");
    int c = 10;

    someFunc(f, a, b, c);

    return 0;
}

It is also possible to explicitly pass a pointer or reference:

void someFunc(void (*inner)(int, std::string, int), int a, std::string b, int c)
// OR
void someFunc(void (&inner)(int, std::string, int), int a, std::string b, int c)

If you use the pointer syntax, you can replace the call by :

someFunc(&f, a, b, c);

But in any case, the compiler will silently replace you syntax choice by a pointer so you don't need to explicitly use the pointer syntax in C++.

Hope it can help.

Fareanor
  • 5,900
  • 2
  • 11
  • 37