The std::thread constructor should handle the arguments that you give it a little differently than most forwarding functions.
The reason for this is related to questions about when the thread actually starts. If the part of the function call that actually created the function argument starts long after the thread object is created (which is completely legal behavior), then the object that needs to be transferred from may be destroyed long ago.
Just consider the modified version of your code:
std::thread some_func() { Pointertest pointertest; thread test(foo,std::move(pointertest)); return test; }
This is absolutely true (the thread will be removed from the function). However, there is a big problem. foo may not have been called yet. And since foo takes its parameter by reference, it now has a reference to the destroyed stack variable.
This is bad. But even if foo took its parameter by value, it will not change anything. Since the actual movement to this parameter does not occur until some indefinite time after the start of the flow. Trying to pass to a parameter will still use the rvalue reference for the destroyed stack variable. Which is bad again.
Consequently, the std::thread constructor does something else. It copies / moves the arguments you pass to internal memory (this is done in the current thread). He then uses these values as arguments to actually call the function (this is done in a new thread).
According to the standard, a thread constructor should treat the transfer of these internal variables to your functions as temporary. The standard states the state INVOKE (DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) , where the DECAY_COPY material occurs in the original stream, and the INVOKE part in a new thread.
So, it seems that your thread implementation does not allow forwarding parameters that are not copied correctly. You should be able to pass in a type that cannot be copied; arguments must be MoveConstructible .
Thus, this will be a mistake in your implementation.