アトミックメンバー変数を持つクラスがあります:
_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()
を追加するなど)が好きではなく、ネットはここでは驚くほど静かです...
other
を移動しているため、他の誰もアクセスできません。したがって、そのbar
からの読み取りは、アトミックであるかどうかに関係なく安全です。
_atomic<T>
_には2つのコンストラクターしかありません。1つはデフォルトの_()
_で、もう1つは_(T)
_です。したがって、コードはコンパイルする必要があるように見えます。そうでない場合は、static_cast _other.bar
_をT
にキャストし、_(T)
_コンストラクターを使用するように強制するとどうなりますか?
: bar( static_cast< bool >( other.bar ) )
または、これは同等で、おそらく醜いものではありません。
: bar( other.bar.load( ) )
std::atomic
は、コピー可能または移動可能ではありません。これは、 コピーコンストラクターが削除されている であり、移動コンストラクターが定義されていないためです。 gustafの回答で指摘されているように、他の値を明示的にロードし、それを使用して新しい値を作成する必要があります。
なぜstd::atomic
動産ではない?これは同期プリミティブであるため、すべてのスレッドは同じデータ(つまり、同じアドレス)で同期する必要があります。アトミック値をコピー(または移動)するときは、何らかの通信プロトコルを使用する必要があります。あなたの例のように単純かもしれませんが(ロードして新しいアトミックを初期化するために使用するだけです)、一般的に、C++ 11による設計上の決定として考えさせるのは良いことだと思います。そうしないと、コードは正常に見えるかもしれませんが、いくつかの微妙な同期の問題があります。
_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));
_