My practical advice is simply don't copy thread objects. Use pointers or smart pointers if you really need to move about a reference to a thread.
But from the purely academic standpoint your case is rather curious. So let's talk a little bit about it.
If you take a closer look at the assignment operator declaration, you'll see that it accepts non-const reference to its source argument (right-hand side operand). In expression
newthread = std::thread(func, &wib2);
the source operand is rvalue, which makes the assignment invalid. MS compiler applies non-standard extension here, but issues a warning.
The reason for such a design is that std::thread is just an avatar of a kernel mode object, and copying it cannot create a copy of the actual thread. Therefore the assignmnt operation is destructive for the source operand. Its intestines are torn out and placed into the assignee, which now becomes the sole owner of the underlying kernel object.
But your observation is curious from another standpoint. Originally TBB provided class tbb_thread because there was not such class in the standard library. But when C++0x draft had matured enough, we've decided to masquerade TBB specific class as the upcoming standard std::thread one to simplify adoption of the new C++ Standard by our users.
However here a hitch awaited us. C++0x defines assignment operator in the following way:
thread& operator=(thread
&& x);
It uses
rvalue reference! Exactly for the same purpose I mentioned above - to pass ownership of the underlying OS entity to the new instance of the wrapper class. And the problem is that if at some moment in the future you try to compile your working variant with the real standard library, it won't compile! Because in the expression
newthread = thr;
source operand is
lvalue, and lvalue cannot be bound to the rvalue reference.
To make if future proof, you could use move() helper:
tbb::move( newthread, thr );
But note that this move() is TBB specific.