2013-01-06 5 views
23

私は原子メンバ変数を持つクラスを持っている:C++ 11:アブソリュート<bool>メンバーの書き込みコンストラクタを書き込みますか?

struct Foo 
{ 
    std::atomic<bool> bar; 
    /* ... lots of other stuff, not relevant here ... */ 
    Foo() 
    : bar(false) 
    {} 

    /* Trivial implementation fails in gcc 4.7 with: 
    * error: use of deleted function ‘std::atomic<bool>::atomic(const td::atomic<bool>&)’ 
    */ 
    Foo(Foo&& other) 
    : bar(other.bar) 
    {} 
}; 

Foo f; 
Foo f2(std::move(f)); // use the move 

がどのようにコンストラクタを見て移動すべきですか?

のgcc 4.7(other.bar周りstd::move()を追加するような)私の試みのいずれかを好きではないとネットが

答えて

14

あなたがotherを移動しているので、誰もがアクセスしないだろう...ここに、驚くほど静かです。だから、そのbarから読むことは、それが原子であるかどうかにかかわらず安全です。

atomic<T>には、デフォルトの()の2つのコンストラクタと、(T)という2つのコンストラクタしかありません。だから、あなたのコードはコンパイルする必要があります。そうでない場合は、static_cast other.barTの場合は、(T)コンストラクタの使用を強制しますか?

: bar(static_cast<bool>(other.bar))

またはそれに等しい、おそらくあまり醜いある:

: bar(other.bar.load())

+1

おかげで、 'バー(other.bar.loadは())'今コンパイルしています適切なソリューションです! – Chris

+7

_So、あなたのコードはコンパイルする必要があります。いいえ、 'atomic 'には削除されたコピーコンストラクタがあり、オーバーロードの解決は 'atomic(T)'コンストラクタではありません。キャストまたはロードが必要です。 –

+0

@Jonathan大丈夫ですが、私はコピーコンストラクタが削除され、 '演算子T 'があることを知っているとき、コンパイラは次のコンストラクタ(T)を続けると思っていました。これは、 '(T)'のアトミックコンストラクタが 'constexpr'なので、' explicit'コンストラクタと同様に動作し、暗黙のコンバートは明示的(またはこの場合は 'constexpr')でなければなりませんか? –

22

std::atomicits copy constructor is deletedなしムーブコンストラクタが定義されているので、コピー可能又は移動可能ではありません。明示的に別の値をロードし、gustafの答えで指摘されているように新しい値を構築する必要があります。

std::atomicはなぜ移動できないのですか?これは同期プリミティブであるため、すべてのスレッドは同じデータ(つまり同じアドレス)上で同期しなければならない。アトミックな値をコピー(または移動)するときは、何らかの通信プロトコルを使用する必要があります。あなたの例のように(単純にロードして新しいアトミックを初期化するために)使用することは簡単かもしれませんが、一般的にはC++ 11が考えることを強く推奨しています。それ以外の場合、コードは正常に見えますが、いくつかの微妙な同期の問題があります。

+1

私は実際に原子を持つことが問題になるかもしれない状況を把握しようとしています複数のスレッドがあると自動的に移動します。手動でstd :: move()を使って強制的に強制することも別のことです。いずれにしても、私は、原子の移動が問題になる場所を示す例が必要です。あなたは他の 'std'コンテナを動かすことができ、あなたは同期の世話をすることが期待されます。 –

+1

もし 'atomic'が明示的に' std :: move() 'を呼び出すことによってトリガされなければならないムーブコンストラクタを持っていれば、それは悪い考えであるかどうか知りたいです。私は期待していただろう。しかし、私は、C++の専門家が標準に関する決定が目的を持っているのか、間違っているのかを判断するには遠すぎます。 – Chris

+1

rvalueが明示的な 'std :: move'または暗黙的にrvalue(関数の戻り値など)です。私は設計上の決定にも熟練していませんが、参照カウントされたリソースは、ムーブコンストラクターが問題につながる可能性のある例だと思います。私は自分の答えを編集し、 "同期の問題"について書いたときに覚えていた例を含めます。 –

1

atomic<bool>のテンプレートのインスタンス化は、本質的に次のようになります。あなたはそれをコピーしようとするので、

struct atomic<bool> 
{ 
    atomic<bool>(bool); 
    atomic<bool>(const atomic<bool>&) = delete; 
    operator bool() const; 
} 

atomic<bool> a = ...; 
atomic<bool> b(a); 

削除コピーコンストラクタが選ばれたと、コンパイルエラーが発生しています。

あなたが明示的に operator bool() --> atomic<bool>(bool)通過するBOOLにキャストする必要が

...

atomic<bool> a = ...; 
atomic<bool> b(bool(a)); 
+1

static_cast (ソリューションの最後のコード行を参照)を使用する方が安全ですか? –

関連する問題