Вектор std:: threads
С++ 11
Я пытаюсь сделать vector
из std::thread
s. Сочетание следующих трех пунктов говорит, что я могу.
1.) Согласно http://en.cppreference.com/w/cpp/thread/thread/thread, Конструктор thread
по умолчанию создает
объект потока, который не представляет поток.
2.) Согласно http://en.cppreference.com/w/cpp/thread/thread/operator%3D, thread
s operator=
Назначает состояние [параметра, который является ссылкой на rvalue потока] на [вызывающий поток], используя перемещение семантика.
3.) Согласно http://en.cppreference.com/w/cpp/container/vector/vector, проходя только переменная типа размера в векторный конструктор построит
контейнер с [указанным числом] инициализированным значением (построено по умолчанию, для классы) экземпляров T. Копии не копируются.
Итак, я сделал это:
#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;
}
Это выполняется, как ожидалось, в VC11 и g++ 4.8.0 (онлайн-компилятор здесь), как показано ниже:
Консольный выход:
Hello
Затем я попробовал его в clang 3.2, переключив меню компилятора на ту же веб-страницу, которая дает:
stderr:
pure virtual method called
terminate called without an active exception
Когда объект потока, представляющий поток, выходит из области действия до join()
ed или detach()
ed, программа будет принудительно завершена. У меня join()
ed vecThread.at(0)
, поэтому единственное, о чем идет речь, это временный поток
std::thread(foo);
в
vecThread.at(0) = std::thread(foo);
присваивания.
Однако, согласно веб-ссылке, потоки могут быть назначены только путем перемещения ссылки rvalue потока. Я не могу придумать способ join()
или detach()
временного объекта потока.
Итак, если вывод clangs правильный, то в чем смысл thread
s operator=
? Или это ошибка компилятора clang?
В g++ 4.8.0, изменив строку
vecThread.at(0) = std::thread(foo)
к
vecThread.at(0) = std::thread{foo}
(заменяя скобки скобками) все еще дает ожидаемый вывод Hello
.
Однако изменение строки на vecThread.at(0) = {foo}
заставляет жаловаться:
g++ 4.8.0 жалоба на фигурные скобки:
Ошибка: преобразование в 'std:: thread' из списка инициализаторов будет использовать явный конструктор 'std:: thread:: thread (_Callable & &, _Args & &...) [с _Callable = void (&)(); _Args = {}] ' vecThread.at(0) = {foo};
который слишком продвинут - я не знаю, что это значит.
Выполнение тех же изменений в clang дает еще более продвинутый:
clang 3.2 жалоба на фигурные скобки:
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
и я не знаю, что это значит.
Я не могу использовать VC11 для подтверждения вышеперечисленных
vecThread.at(0) = {foo}
поскольку VC11, начиная с компилятора CTP в ноябре 2012 года, не поддерживает равномерный синтаксис инициализации в стандартной библиотеке.
Ответы
Ответ 1
Ваш первый пример правильный. Выбрасывание исключения - это известный bug, когда вы используете clang с libstdС++. Чтобы решить эту проблему, вам нужно установить libС++ (версия llvm библиотеки С++). См. Пример компиляции с libС++ ниже
#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. См. здесь, почему требуется также флаг -lsupc++
.