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.
CodePudding user response:
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;
};
CodePudding user response:
I would choose some other approach. Take a look:
#include <functional>
#include <iostream>
#include <thread>
using namespace std;
class Context
{
thread t;
public:
template<class Func, class... Args>
Context(Func func, const Args&... args) : t{ func, cref(args)... } {
}
~Context() {
if (t.joinable())
t.join();
}
};
void f1() {
cout << "f1" << endl;
}
void f2(int) {
cout << "f2" << endl;
}
void f3(int, int) {
cout << "f3" << endl;
}
int main()
{
Context c1{ f1 };
Context c2{ f2, 1 };
Context c3{ f3, 1, 2 };
}