Need to have this Functor live as long as my thread does, so I've created a shared_ptr to it and trying to pass it to std::thread. I've copied the code and list of errors here.
struct Functor
{
std::string greeting;
explicit Functor(std::string _greeting="Hello!"): greeting { _greeting } {}
void operator()()
{
std::cout << greeting << "\n";
}
};
auto main() ->int
{
std::shared_ptr<Functor> fp = std::make_shared<Functor> ();
std::thread t(&fp);
t.join();
return 0;
}
List of errors:
Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' std_threads C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr\xthread 240
Error C2672 'std::invoke': no matching overloaded function found std_threads C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr\xthread 240
I'm new to c++11 and concurrency. Please help me understand the following
1>does a std::thread always invoke the operator() inside an object when passed by value ? If so, why it has been defined so.
2>how to ensure that a resource given to a thread stays around as long as the thread does?
3>is the Functor written here, a function object ?
4>What have I done here in this code ?!
1>does a std::thread always invoke the operator() inside an object when passed by value ? If so, why it has been defined so.
std::thread
invokes std::invoke
. From cppreference, if the first argument is neither a pointer to member function
nor a pointer to data member
; it is treated as a function object.
So, fp() will be called.
INVOKE(f, t1, t2, ..., tN) is equivalent to f(t1, t2, ..., tN) (that is, f is a FunctionObject)
So you can basically do std::thread t{*fp}
2>how to ensure that a resource given to a thread stays around as long as the thread does?
You can have shared_ptr
to provide ownership of a shared object. Or you can just manually do it by ensuring the resource passed is in scope. The mileage varies.
3>is the Functor written here, a function object ?
Yes. A FunctionObject type is the type of an object that can be used on the left of the function call operator. However fp
is not. But *fp
is.
4>What have I done here in this code ?!
You can make it work by explicitly passing Functor::operator()
with argument fp.get()
. Ofcourse a simple way is to just pass *fp