I have been learning about perfect forwarding and the use of && in function templates (see this previous question of mine) and would like to know if my use of Args
The issue is that which overload of MyThreadFunc
is desired is not deducible by the compiler. There are at least two ways to fix it:
Rename one of the function so that it is clearer which one you want.
Use explicit template parameters:
StartDetachedThread<void (CObject&)>(MyThreadFunc, object);
StartDetachedThread<void (CObject&&)>(MyThreadFunc, std::move(object2));
The problem in your code has nothing to do with std::thread
, it is because MyThreadFunc
is ambiguous in this context:
// Which MyThreadFunc should be used?
StartDetachedThread(MyThreadFunc, object);
Regarding your question:
1) I know that arguments passed to the thread constructor are copied first, then passed by reference to the new thread, [...]
In your example, the only copy is the copy of the lambda. The arguments are not copied here, if you want the argument to be copied you should use something like this:
std::thread(std::move(func), std::forward<Args>(args)...).detach();
...where you forward the arguments to std::thread
constructor.
This is safer. — Think about what happens if the function StartDetachedThread
ends while the thread is still running?
If you use this, you need to explicitly tell the compiler you want to call the reference version for object1
by using std::ref
:
CObject object;
StartDetachedThread<void (CObject&)>(MyThreadFunc, std::ref(object)); // std::ref
CObject object2;
StartDetachedThread<void (CObject&&)>(MyThreadFunc, std::move(object2));
2) Is there any value in having
StartDetachedThread(FunctionType&& func, Args&&... args)
- or is the&&
unnecessary forFunctionType
?3) Is there any value whatsoever in using
Args&&
when starting a thread like this, or should I always useArgs
?
Using forwarding references allows you to call StartDetachedThread
without having to move everything. If you use the above way for constructing a std::thread
, then copies will be made for func
and args
anyway.