web-dev-qa-db-ja.com

std :: threadsのベクトル

C++ 11

_std::thread_ sのvectorを作成しようとしています。次の3つのポイントの組み合わせは私ができると言います。

1.) http://en.cppreference.com/w/cpp/thread/thread/thread によると、threadのデフォルトコンストラクターは

スレッドを表さないスレッドオブジェクト。

2.) http://en.cppreference.com/w/cpp/thread/thread/operator%3D によると、threadの_operator=_

移動セマンティクスを使用して、[スレッド右辺値参照であるパラメーター]の状態を[呼び出し元スレッド]に割り当てます。

3.) http://en.cppreference.com/w/cpp/container/vector/vector によると、サイズ型変数のみをベクトルコンストラクターに渡すと構築されます

[指定された数]の値が初期化された(クラスの場合はデフォルトで構築された)インスタンスを持つコンテナー。コピーは作成されません。

だから、私はこれをしました:

_#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
_

次に、同じWebページでコンパイラメニューを切り替えて、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);

割り当て。

ただし、Web参照によると、スレッドはスレッド右辺値参照を移動することによってのみ割り当てることができます。一時的なスレッドオブジェクトをjoin()またはdetach()する方法は考えられません。

それで、clangの出力が正しい場合、threadの_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 && ...)[with _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}

2012年11月のCTPコンパイラの時点でVC11は、標準ライブラリで統一された初期化構文をサポートしていないため、問題が発生します。

14
CodeBricks

あなたの最初の例は正しいです。 libstdc ++でclangを使用する場合、例外のスローは既知の bug です。これを解決するには、libc ++(c ++ライブラリのllvmバージョン)をインストールする必要があります。以下のlibc ++を使用したコンパイルの例を参照してください

#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++も必要なのですか。

7
awesoon