2016-12-31 6 views
1


VC++を使用して(Visual Studio 2015、アップデート3を使用して)プログラムをコンパイルするとコンパイルに失敗します。std :: bindはMSVCのstd :: atomic_bool&でコンパイルできません

基本的には、アトミックブール値への参照をアトミックブール値で取得する関数をバインドしたいと思います。

void stub(std::atomic_bool& b) { 
    b = true; 
} 

int main() { 
    std::atomic_bool b(false); 
    std::function<void()> delegate = std::bind(stub, b); //fails to compile 

    auto& ref = b; 
    std::function<void()> delegate0 = std::bind(stub, ref); //fails to compile 

    std::function<void()> delegate1 = std::bind(stub, std::ref(b)); //compiled 
/*...*/ 
    } 

コンパイラのスタックトレース:コード含む自己

1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility(357): error C2665: 'std::tuple<std::atomic<bool>>::tuple': none of the 2 overloads could convert all the argument types 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\tuple(608): note: could be 'std::tuple<std::atomic<bool>>::tuple(std::tuple<std::atomic<bool>> &&)' 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\tuple(607): note: or  'std::tuple<std::atomic<bool>>::tuple(const std::tuple<std::atomic<bool>> &)' 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility(357): note: while trying to match the argument list '(std::atomic<bool>)' 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(866): note: see reference to function template instantiation 'std::_Compressed_pair<void (__cdecl *)(std::atomic_bool &),std::tuple<std::atomic<bool>>,false>::_Compressed_pair<void(__cdecl &)(std::atomic_bool &),_Cv_TiD&>(std::_One_then_variadic_args_t,_Other1,_Cv_TiD &)' being compiled 
1>   with 
1>   [ 
1>    _Cv_TiD=std::atomic<bool>, 
1>    _Other1=void (__cdecl &)(std::atomic_bool &) 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(864): note: see reference to function template instantiation 'std::_Compressed_pair<void (__cdecl *)(std::atomic_bool &),std::tuple<std::atomic<bool>>,false>::_Compressed_pair<void(__cdecl &)(std::atomic_bool &),_Cv_TiD&>(std::_One_then_variadic_args_t,_Other1,_Cv_TiD &)' being compiled 
1>   with 
1>   [ 
1>    _Cv_TiD=std::atomic<bool>, 
1>    _Other1=void (__cdecl &)(std::atomic_bool &) 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(863): note: while compiling class template member function 'std::_Binder<std::_Unforced,void (__cdecl &)(std::atomic_bool &),std::atomic_bool &>::_Binder(_Fx,std::atomic_bool &)' 
1>   with 
1>   [ 
1>    _Fx=void (__cdecl &)(std::atomic_bool &) 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(890): note: see reference to function template instantiation 'std::_Binder<std::_Unforced,void (__cdecl &)(std::atomic_bool &),std::atomic_bool &>::_Binder(_Fx,std::atomic_bool &)' being compiled 
1>   with 
1>   [ 
1>    _Fx=void (__cdecl &)(std::atomic_bool &) 
1>   ] 
1> c:\visual studio 2015\projects\quantum\quantum\main.cpp(658): note: see reference to class template instantiation 'std::_Binder<std::_Unforced,void (__cdecl &)(std::atomic_bool &),std::atomic_bool &>' being compiled 

は、私は欠場か、それはコンパイラのせいです何かはありますか?

+3

アトミックはコピーできません。だから、 'std :: ref'が必要です。 –

+0

@KerrekSBなぜプログラムがアトミックをコピーしようとしていますか?この関数はパラメータとしての参照を取得し、アトミックは参照として渡され、参照の横にコピーされているものは表示されません –

+0

C++の型とオブジェクトモデルに関する根本的な誤解があるようです。あなたは*決して* "参照をコピーする"。あなたは常に値をコピーします*。値は決して参照ではありません。参照は、値を指定するために使用できる*変数*の一種です。だからあなたが 'ref'と言うとき、それは' std :: atomic_bool'型の値です(そしてそれは 'b'と同じ値になります)。 'std :: ref(b)'(または 'std :: ref(ref)')と言うと、それは 'std :: reference_wrapper '型の値であり、 'std :: bind'それを解釈するためのプロトコルを持っています。 –

答えて

2

bindは常にの値の値を格納しようとします。 atomicタイプはコピーできません。したがって、bindがコピーしようとすると失敗します。

この理由の1つは、reference_wrapperが存在する理由の1つです。値が期待される場所でオブジェクトへの参照を使用できるようにするためです。実際、std::refは、主にbindを処理するために発明されました。

を参照してください。bindにパラメータへの参照が格納されている可能性があります。しかし、参照を格納することは非常に危険です。特に、ファンクタが呼び出される前にいつでも既存のスタック変数を参照することは避けてください。だからbind明示的にになるようにしてください。 refを使用します。

+0

@DavidHaim:参照はオブジェクトではありません。 'bind'は常に値を格納します。それらをコピーするか移動するかは、関数に渡すものによって異なります。しかし、それは値ではなく、参照を格納します。 –

+0

@Nicole Bolas、私はあなたのロジックに必ずしも同意しません。 C++は安全でない言語です。関数からポインタやローカル変数への参照を返すことができます。バインドされた式の中にぶら下がりのポインタを格納することができます。そのコストの参照を無効にすることは無意味です。 –

+0

@DavidHaim: "*私はあなたのロジックに必ずしも同意するわけではありません。*"あなたが望むもの全てに同意するか同意しないのですが、それがBoost(そして標準ライブラリバージョン)がそうした理由です。私はその問題に関する彼らの立場を関連付けるだけです。そして、言語が安全でないという理由だけで、より安全でないものを作成する必要はありません。結局のところC++では '&'や '*'を使う必要があるので、何か危険な状態になっているかどうかを少なくとも知ることができます。デフォルトでは、C++は値を渡したり返したりします。 –

1

std::atomic種類はコピー不可能です。 std::bind()への(エラーが発生した)呼び出しはコピーを作成します。

また、参照の仕組みを誤解しているように見えます。auto& ref = bはもちろんbへの参照を作成します。 refはまだそれ自体の左辺値なので、それをstd::bind()に渡しても突然動作が変わることはありません。

std::function<void()> delegate = [&b] { b = true; }; 

最後に、あなたがC++ 11でアトミックを、使用している考えると、これはあなたにも、あなたがstd::refに頼らずに自分のコードを表現できるようになるラムダへのアクセス権を持っていることを意味しますしかし、注意してください!どちらの場合も、あなたはstd::bind + std::refを使用するかどうか、私のラムダ上記の例では、あなたはあなたがdelegateで行われるまでbが有効なままであることを保証しなければならない -は、元のオブジェクトの生存期間を延長しない基準を取ります。

関連する問題