C++11
I am trying to make a vector
of std::thread
s. The combination of the following three points says I can.
1.) According to http://en.cppreference.com/w/cpp/thread/thread/thread,
thread
’s default constructor creates a
thread object which does not represent a thread.
2.) According to http://en.cppreference.com/w/cpp/thread/thread/operator%3D, thread
’s operator=
Assigns the state of [the parameter, which is a thread rvalue reference] to [the calling thread] using move semantics.
3.) According to http://en.cppreference.com/w/cpp/container/vector/vector, passing only a size type variable to a vector constructor will construct
the container with [the specified number of] value-initialized (default constructed, for classes) instances of T. No copies are made.
So, I did this:
#include <iostream>
#include <thread>
#include <vector>
void foo()
{
std::cout << "Hello\n";
return;
}
int main()
{
std::vector<std::thread> vecThread(1);
vecThread.at(0) = std::thread(foo);
vecThread.at(0).join();
return 0;
}
This runs as expected in VC11 and g++ 4.8.0 (online compiler here) as seen in the following:
Console Output:
Hello
Then I tried it in clang 3.2, by toggling the compiler menu on the same webpage, which gives:
stderr:
pure virtual method called
terminate called without an active exception
When a thread object—that represents a thread—goes out of scope before being join()
ed or detach()
ed, the program will be forced to terminate. I have join()
ed vecThread.at(0)
, so the only thing left in question is the temporary thread
std::thread(foo);
in the
vecThread.at(0) = std::thread(foo);
assignment.
However, according to the web reference, threads can only be assigned by moving a thread rvalue reference. I cannot think of any way to join()
or detach()
a temporary thread object.
So if clang’s output is correct, then what is the use of thread
’s operator=
? Or is this a clang compiler bug?
In g++ 4.8.0, changing the line
vecThread.at(0) = std::thread(foo)
to
vecThread.at(0) = std::thread{foo}
(replacing parentheses with braces) still gives the expected Hello
output.
However, changing the line to vecThread.at(0) = {foo}
makes it complain:
g++ 4.8.0's complaint on braces:
error: converting to 'std::thread' from initializer list would use explicit constructor 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(); _Args = {}]' vecThread.at(0) = {foo};
which is too advanced—I don’t know what it means.
Making the same change in clang gives the even more advanced:
clang 3.2's complaint on braces:
error: no viable overloaded '='
vecThread.at(0) = {foo};
...
note: candidate function not viable: cannot convert initializer list
argument to 'const std::thread'
thread& operator=(const thread&) = delete;
...
note: candidate function not viable: cannot convert initializer list
argument to 'std::thread'
thread& operator=(thread&& __t) noexcept
and I don’t know what that means either.
I cannot use VC11 to corroborate the above
vecThread.at(0) = {foo}
problems because VC11, as of the November 2012 CTP compiler, does not support uniform initialization syntax on the Standard Library.
Changing contents of vector of thread vecOfThreads[1] = std::move(th4); //Destructor of already existing thread object will call terminate vecOfThreads[1] = std::move(th4); //Destructor of already existing thread object will call terminate vecOfThreads[1] = std::move(th4);
1) std::vector is a sequence container that encapsulates dynamic size arrays. 2) std::pmr::vector is an alias template that uses a polymorphic allocator. The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets to regular pointers to elements.
The C++11 standard does not expect to be able to safely call non const functions simultaneously. Therefore all classes available from the standard, e.g. std::vector<>, can safely be accessed from multiple threads in the same manner.
std::thread::operator= thread objects cannot be copied (2).
Your first example is correct. Throwing an exception is a known bug, when you using clang with libstdc++. To solve it, you have to install libc++(llvm version of c++ library). See an example of compiling with libc++ below
#include <thread>
int main()
{
std::thread t([] () {});
t.join();
return 0;
}
$ clang++ -std=c++11 -stdlib=libc++ main.cpp -o main -lc++ -lsupc++ -lpthread
P.S. See here, why is the flag -lsupc++
required too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With