Подтвердить что ты не робот

Вектор 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 года, не поддерживает равномерный синтаксис инициализации в стандартной библиотеке.

4b9b3361

Ответ 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++.