std::atomic_bool
を使用したいのは、異なるスレッドからアクセスされることになっているブール値が必要だからです。
これはstatic
メンバー変数です。問題は、false
を最初の状態として初期化することです。通常、私はそのようにします:std::atomic_bool World::mStopEvent = false;
しかし、問題はfalse
をコンストラクターとして受け取らないことです。では、このような変数をどのように初期化するのでしょうか? VS 2012を使用しています。
これは Visual Studio 2012の既知の問題(VC11) です。既存のConnectアイテムに投票する必要があります。Microsoftが修正を延期しているため、より多くの人々に影響があることを知っているためです。
こんにちは、
このバグを報告していただきありがとうございます。私はMicrosoftのSTLのメンテナーです。このバグはデータベースでアクティブのままですが、VC11 RTM(VS 2012 RTM)では修正されません。すべてのバグは私たちにとって重要ですが、一部のバグは他のバグよりも深刻であり、優先度キューのトップに上がります。
STLのアクティブなConnectのすべてのバグにこの応答をコピーアンドペーストしていますが、次の簡潔なコメントが特にバグに適用されます。
- ええ、
atomic_bool
、atomic_int
などにこれらのコンストラクターがありません(atomic<bool>
、atomic<int>
などにはそれらがあります)。 29.5 [atomics.types.generic]/7は、「表145に指定されているように、atomicの整数の特殊化に対応する名前付き型と、指定されたatomic_bool
に対応する名前付き型atomic<bool>
各名前付き型は、対応する特殊化のtypedef
または対応する特殊化の基本クラスのいずれかです。基本クラスの場合、対応する特殊化と同じメンバー関数をサポートします。 typedef(1つの型は常に2つの型よりも常に単純です)を使用したいのですが、他の問題が発生するかどうかを確認する必要があります。このバグを解決できるとは約束できませんが、できるだけ早く解決したいと考えています(そして、それが起こったら別の応答を送信します)-最初の機会は「帯域外」ですハーブサッターがGoingNative 2012カンファレンスで発表したVC11とVC12の間のリリース。
注:Connectはコメントについて通知しません。さらに質問がある場合は、私にメールしてください。
Stephan T. Lavavejシニア開発者-Visual C++ライブラリ[email protected]
基本的に、今のところstd::atomic<T>
を使用する必要があります。
これを試して:
atomic_bool my_bool = ATOMIC_VAR_INIT(false);
問題:
_std::atomic_bool
_はコピー構築できないため、copy-initializationは使用できません。
_std::atomic_bool World::mStopEvent = false; // ERROR!
_
実際、上記は次と同等です。
_std::atomic_bool World::mStopEvent = std::atomic_bool(false); // ERROR!
_
ただし、direct-initializationを使用できます。
_std::atomic_bool World::mStopEvent(false);
_
必要に応じて、括弧の代わりに中括弧を使用することもできます。
_std::atomic_bool World::mStopEvent{false};
_
バグ:
どのコンパイラを選択してもコピーの初期化は違法ですが、VC11に同梱されている標準ライブラリの実装にはバグがあり、直接初期化も実行できないようです。
それでは、このような変数をどのように初期化するのでしょうか?
回避策:
可能な回避策として、アトミックブールフラグの値を設定および返す静的ゲッター/セッターラッパーのペアを提供できます。スレッドセーフな方法で望ましい初期値(これはある種の遅延初期化と考えることができます):
_#include <atomic>
#include <mutex>
struct World
{
static bool is_stop_event_set()
{
std::call_once(mStopEventInitFlag, [] () { mStopEvent = false; });
return mStopEvent;
}
static void set_stop_event(bool value)
{
std::call_once(mStopEventInitFlag, [value] () { mStopEvent = value; });
mStopEvent = value;
}
static std::atomic_bool mStopEvent;
static std::once_flag mStopEventInitFlag;
};
std::atomic_bool World::mStopEvent;
std::once_flag World::mStopEventInitFlag;
_
mStopEvent
に直接アクセスする代わりに、その値はis_stop_event_set()
関数を介して読み取られます。
_#include <iostream>
int main()
{
std::cout << World::is_stop_event_set(); // Will return false
}
_
どうですか:
std::atomic_bool World::mStopEvent(false);