c++multithreadingfunctionc++11stdbind

How can I store a std::bind function pointer?


Here is the code I am using

#include <functional>
#include <iostream>
#include <thread>

class Context {
private:
  std::thread thread;
  bool running;
  void run() {
    while (running) {
      if (function != nullptr) {
        function();
        function = nullptr;
      }
    }
  }
  void (*function)();

public:
  Context() : running(true) { thread = std::thread(&Context::run, this); }
  ~Context() {
    running = false;
    thread.join();
  }

  template <typename T, typename... Args> void call(T function, Args... args) {
    this->function = std::bind(function, args...);
  }
};

// Here are some test functions
void f1() { std::cout << "f1" << std::endl; }

void f2(int a) { std::cout << "f2(" << a << ")" << std::endl; }

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

int main() {
  Context context;
  context.call(f1);
  context.call(f2, 1);
  context.call(f3, 1, 2);
  return 0;
}

I want this class to create a thread that will run some functions. The thread will be created when the class is created and will be stopped when the class is destroyed. In order to run a function, you can call the Context::call function with the function to be called and the arguments.

f2(2);

becomes

context.call(f2, 2);

and

f3(3, 4);

becomes

context.call(f3, 3, 4);

However I am getting errors when I try to compile this file :

t.cpp: In instantiation of 'void Context::call(T, Args ...) [with T = void (*)(); Args = {}]':
t.cpp:55:15:   required from here
t.cpp:42:31: error: cannot convert 'std::_Bind_helper<false, void (*&)()>::type' to 'void (*)()' in assignment
   42 |     this->function = std::bind(function, args...);
      |                      ~~~~~~~~~^~~~~~~~~~~~~~~~~~~
      |                               |
      |                               std::_Bind_helper<false, void (*&)()>::type
t.cpp: In instantiation of 'void Context::call(T, Args ...) [with T = void (*)(int); Args = {int}]':
t.cpp:56:15:   required from here
t.cpp:42:20: error: cannot convert 'std::_Bind_helper<false, void (*&)(int), int&>::type' to 'void (*)()' in assignment
   42 |     this->function = std::bind(function, args...);
      |     ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.cpp: In instantiation of 'void Context::call(T, Args ...) [with T = void (*)(int, int); Args = {int, int}]':
t.cpp:57:15:   required from here
t.cpp:42:20: error: cannot convert 'std::_Bind_helper<false, void (*&)(int, int), int&, int&>::type' to 'void (*)()' in assignment

I know this code is unsafe and has flaws but I used mutexes and security measures in the real implementation. This example is just the minimal to reproduce the error.


Solution

  • You can make use of std::function. In particular, replace void (*function)() with std::function<void ()> function as shown below:

    class Context {
    private:
      //other code here
      
      std::function<void ()> function;
    
    };
    

    Working demo