I'm kind of new to std::async and I have problems understanding how it works. I saw example of how to pass member funcion to std::async somewhere on the web but it seems not to compile. Whats the problem here? How can it be done without lambda?
class Test {
std::future<void> f;
void test() {}
void runTest() {
// ERROR no instance overloaded matches argument list
f = std::async(std::launch::async, &Test::test, this);
// OK...
f = std::async(std::launch::async, [this] {test();});
}
void testRes() {
f.get();
}
};
You should be able to use std::bind to create a callable function object:
f = std::async(std::launch::async, std::bind(&Test::test, this));
In your example &Test::test is not a function that takes one parameter of type Test, as it would be expected by std::async. Instead it is member function, which must be called differently.
Related
First of all, I'm beginner in C++ so I don't know if the way I'm doing this is right or can cause some problem.
So, I'm trying to pass a generic callback to a function and then call member functions from different objects inside that callback. In this case, I'm creating a closure with a lambda function to capture the objects and then inside the lambda I'm calling they member functions.
Well, for example, the code is something like this:
// ...
void functionWithCallback(std::function<void()> callback)
{
// Do some stuff ...
callback();
}
int main()
{
SomeClass some_object = SomeClass();
AnotherClass another_object = AnotherClass();
std::function<void()> callback = [&some_object, &another_object]() {
some_object.someFunction();
another_object.anotherFunction();
};
functionWithCallback(callback);
}
My question is: is this a correct way or can it cause some problems or unexpected behaviors? Is there any more elegant way to do this?
So I'm currently working on an input manager for a C++ game. I was thinking about doing it as a map<char, list<Listener::method>>, so that when I register a button pressed, I call all the methods registered for the specific key.
Problem is, done like that I have to specify the instance which I want to call the method from. Is there a way to hold inside a variable not only the method but the caller instance?
Something like:
class Foo
{
public:
Foo ();
~Foo ();
void DoSomething();
};
Foo fooObject;
void(Foo::*fPtr)(void) = &fooObject::DoSomething;
(*fPtr)();
And that would call fooObject's DoSomething()
Is it possible?
If not, could someone point me to a Event-Listener pattern? Doesnt have to be overcomplicated or threadsafe. Just the basic structure.
The problem with member function pointers is you need an instance of the class to call them on. You can't achieve this with just a pointer because the pointer only points to the function, and not the additional object you need to pass to the function (remember all member functions have an implicit first parameter that takes the class type).
You can use a std::function to have a function object that holds the object to call and the function to call on it. If you have
std::function<void()> func = [&](){ return fooObject.DoSomething(); }; // Bind with a reference. Use this if the object will live as long as the function to save on a copy
std::function<void()> func = [=](){ return fooObject.DoSomething(); }; // Bind with a copy. Use this if the function will outlive the object
then when you call func using func() it will run the body of he lambda which calls DoSomething on fooObject.
You can also use std::bind to bind a member function pointer to a object to call it on but lambdas are generally preferred as the syntax is easy to use.
Is there a way to hold inside a variable not only the method but the caller instance?
Yes, you can bind method and object together.
Since C++11 you have bind utility.
A minimal example from your concept:
struct Foo {
void foo();
};
void bar() {
// your map
std::map<char, std::function<void()>> actions;
// Bind method and object together inside fn
Foo foo;
auto fn = std::bind(&Foo::foo, &foo);
// Insert fn into map
actions.emplace('f', fn);
// call fn from map! Be careful about object lifetime
actions['f']();
}
Godbolt code
Be careful because the "bind object" (fn in my example) will just store a reference to the object foo. Therefore, if you invoke fn after the object foo has been destroyed you will get an undefined behaviour.
In case you want to take care about object lifetime, you can copy it with a lambda function. For example:
auto fn = [foo]() { foo.foo(); }
Or use a custom structure and store a copied object inside.
There is no such thing as a "method from a specific instance".
You can hold a pointer to a member function of a class. Such pointers are not bound to any specific object.
You can use that function pointer on any object of the class.
Given
class Foo
{
public:
Foo ();
~Foo ();
void DoSomething();
};
Any class can hold a pointer to the DoSomething member function (you're calling it a method).
void(Foo::*fPtr)(void) = &Foo::DoSomething;
You would need an object to be able to call the member function. The calling syntax is a bit obtuse but here it is.
Foo foo = <some function call>;
(foo.*fPtr)();
You could use the bind-functionality to get function object having function parameteras already bound to arguments. By that, you can bind the object reference, which is implicitly the first parameter in any non-static member function, to the respective object for which you'd like to have the callback:
class Foo
{
public:
int x;
Foo (int _x) : x(_x) {} ;
void doSomething() { cout << x << endl; }
};
int main() {
Foo fooObject1(1);
Foo fooObject2(2);
std::function<void ()> fx1 = std::bind(&Foo::doSomething,&fooObject1);
std::function<void ()> fx2 = std::bind(&Foo::doSomething,&fooObject2);
std::vector<std::function<void ()>> callbacks;
callbacks.push_back(fx1);
callbacks.push_back(fx2);
for (auto f : callbacks) {
f();
}
}
Output:
1
2
I successfully implemented my own thread_pool class where I can submit lambdas that can return any value but can only take zero arguments. I would like to improve it, such that it can work like std::async, where one can call it as follows: std::async(my_function, arg_1, arg_2, ..., arg_n). As I have it right now it looks as follows:
template<typename T>
auto enqueue_task(T&& task) -> std::future<decltype(task())>
{
auto wrapper = std::make_shared<std::packaged_task<decltype(task())()>>(std::forward<T>(task));
{
//some mutex
std::unique_lock<std::mutex> mutex(mutex_);
//The task is added to a queue of std::function<void()>
tasks_.emplace([=] {(*wrapper)(); });
}
has_work_.notify_one();
return wrapper->get_future();
}
My ideal solution would be such, that I can pass arguments to functinons in my thread_pool like such:
pool.enqueue_task(my_function, arg_1, arg_2, ..., arg_n)
where arg_1, ..., arg_n are the arguments of my_func
For this I sucessfully create a function which can take a variadic amount of arguments, but I have not managed to save this function int my std::function queue. I read on this link:
Passing a variadic function as argument how to achieve my goal by using std::bind. Yet I have not managed to achieve my goal. Here is how I understood it, what turned out not to work:
//some function with variadic arguments
template <typename... Args>
void test1(Args&&... args)
{
}
void test2(int a)
{
}
//main method
std::function<void()> a = std::bind(test2, 2) //works
std::function<void()> b = std::bind(test1<int>, 1) //does not work
std::bind will pass argument as lvalue. From cppreference:
the ordinary stored argument arg is passed to the invokable object as lvalue argument
When you specify test1<int>, the function becomes void test1(int&&), which cannot accept lvalue.
So I have done some research, and have found you can create a boost::thread object and have it start with a non-static class function by using "this" and boost::bind etc. It really doesn't make much sense to me and all the examples I could find had the boost::thread object launched within the same class as the function it was starting with so this could be used. I however, am launching the thread in a different class so I'm afraid by using "this", I will be saying the "this" is from the class I am creating the thread from, rather than the one the function is in (I'm probably wrong, I need to learn more about this "this" guy). Here is an example of my source I am having the problem with.
ANNGUI.h
class ANNGUI
{
private:
boost::thread *GUIThread;
Main *GUIMain;
public:
// Creates the entire GUI and all sub-parts.
int CreateGUI();
}
ANNGUI.cpp
int ANNGUI::CreateGUI()
{
GUIMain = new Main();
GUIThread = new boost::thread(GUIMain->MainThreadFunc);
};
This isn't all the source, but I think my problem is in here somewhere, I know I have to deal with the "this" somehow, but I'm unsure how. I Could use a static function, but I didn't really want to make my variables static either.
Thanks.
Also, Is there any very good resource for using any boost libraries? Their web site documentation seems good, but over my head.
The this keyword is used with boost::bind when the function object you're creating is bound to a object member function. Member functions can't exist apart from instances, so when creating a functor object out of a member function with boost::bind, you need a pointer to an instance. That's exactly what the this keyword actually is. If you use the this keyword within a member function of a class, what you get is a pointer to the current instance of that class.
If you were to call bind from outside a class member function, you might say something like:
int main()
{
Foo f;
boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, &f));
}
Here, we're using Foo::some_function as our thread function. But we can't use this because we're calling bind from main. But the same thing could be achieved using this if we called bind from within a member function of Foo, like so:
void Foo::func1()
{
boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, this));
}
If a member function is static, or is simply a regular (non-member) function, then you don't need an instance pointer at all. You would just do:
boost::thread* thr = new boost::thread(some_regular_function);
As others mentioned, when you want to call an object method in a new thread, you have to supply the address of that object. But you don't need to call boost::bind, you can use the overloaded boost::thread constructor like this:
GUIThread = new boost::thread(&Main::MainThreadFunc, GUIMain);
If the method is in the same class you use this to get the address of the current instance, e.g.:
t = new boost::thread(&myclass::compute, this);
If the method has parameters, you can specify them after the second argument, e.g.:
t = new boost::thread(&myclass::compute, this, p1, p2);
boost::bind is your friend (it can sometimes have a rough way of showing it though)!
use GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain));
and then make your MainThreadFunc a regular member. That means that you can use the instance variables directly like you would normally do.
Something like this:
class GUIMain {
public:
GUIMain() : m_Member(42) {}
void MainThreadFunc() {
// use all members as you would normally do
std::cout << m_Member << std::endl;
}
private:
int m_Member;
};
In cases like this it is useful to think of non-static member functions as free functions that take the this as first parameter, for example in your case void MainThreadFunc(Main* this).
boost::thread accepts a nullary functor, so you have to pass it a nullary functor which contains a reference to the instance GUIMain and calls GUIMain->MainThreadFunc which, seen as I explained above, would be something like MainThreadFunc(GUIMain).
Boost (and now also C++ with TR1) provides helpers to create such functors, namely boost::bind (or alternatively boost::lambda::bind). The expression boost::bind(f, arg1, arg2, ...) means "return a nullary functor which calls f(arg1, arg2, ...)".
That said, you can use the following expression to create the thread:
GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain))
If your object is a functor, i.e. has an operator(), you can pass an instance of it to boost::thread. The operator() does not need to be static. For example:
#include <boost/thread.hpp>
struct th {
void operator()();
};
void th::operator()()
{
for (;;) {
// stuff
}
}
int main()
{
th t;
boost::thread my_thread( t ); // takes a copy of t !
my_thread.join(); // blocks
return 0;
}
I want to do something like this:
class A {
public:
void a_start () {
// somewhere in A: my_b = new B();
std::thread t(my_b->b_start); // won't compile
}
private:
B* my_b;
};
class B {
public:
void b_start();
};
But it won't compile. I tried to look at http://accu.org/index.php/journals/1584 but it did not mention the case where the member function lies in a new-ed object. What is the correct syntax?
There are lots of ways to accomplish this, such as using std::bind or using a trampoline member function, but I'd probably just use a lambda, like this:
std::thread t([&](){my_b->b_start();});
A pointer to a member function is not the same thing as a function. You can't pass one to std::thread. What you can do is declare a function that takes my_b as an argument and calls b_start on it, then pass the function and my_b to std::thread. Or, this being C++11, you can probably use a lambda:
void a_start() {
std::thread t([](B* b){b->b_start();}, my_b);
}
(Note: I haven't tried compiling this myself).