简体   繁体   English

std :: bind无法在MSVC上使用std :: atomic_bool&进行编译

[英]std::bind fails to compile with std::atomic_bool& on MSVC


I'm using VC++ to compile my program (using Visual Studio 2015, update 3) and some snippet fails to compile. 我正在使用VC ++编译我的程序(使用Visual Studio 2015更新3),并且某些代码段无法编译。

basically, I want to bind a function which gets a reference to atomic boolean with atomic boolean. 基本上,我想绑定一个函数,该函数使用原子布尔来引用原子布尔。 self containing code: 自我包含的代码:

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
/*...*/
    }

the compiler stack trace: 编译器堆栈跟踪:

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

Is there something I miss or it's the compiler fault? 有什么我想念的还是编译器错误?

bind always tries to store values of the parameters, never references. bind总是尝试存储参数的 ,而不是引用。 atomic types cannot be copied. atomic类型无法复制。 So when bind tries to copy them, it will fail. 因此,当bind尝试复制它们时,它将失败。

This is one of the reasons reference_wrapper exists: to allow a reference to an object to be used in a place where a value is expected. 这是reference_wrapper存在的原因之一:允许在期望值的地方使用对对象的引用。 Indeed, std::ref was invented primarily to deal with bind . 确实, std::ref发明主要是为了处理bind

See, bind could have stored references to parameters. 看, bind可能已经存储了对参数的引用。 However, storing references can be very dangerous, especially references to stack variables which may stop existing sometime before the bind functor gets called. 但是,存储引用可能非常危险,尤其是对堆栈变量的引用,这些引用可能在调用bind函子之前的某个时间停止存在。 So bind forces you to be explicit about when you store references; 因此, bind强制您明确存储引用的时间; it makes you use ref . 它使您使用ref

std::atomic types are not CopyConstructible. std::atomic类型不是CopyConstructible。 Your (erroring) invocations to std::bind() would create copies. 您(错误)对std::bind() )的调用将创建副本。

Additionally, you appear to misunderstand how references work - auto& ref = b does of course create a reference to b ; 另外,您似乎误解了引用的工作方式auto& ref = b当然会创建对b的引用; but ref is still an lvalue in its own right and as such, passing it to std::bind() does not suddenly change the behaviour. 但是ref本身仍然是左值,因此将ref传递给std::bind()不会突然改变其行为。

Finally, considering you're using atomics, which is C++11, this means you also have access to lambdas which would allow you to express your code without having to resort to std::ref : 最后,考虑到您使用的是A ++(C ++ 11)原子,这意味着您还可以访问lambda,这将使您无需借助std::ref即可表达代码:

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

Beware however! 但是要当心! In either case, whether you use std::bind + std::ref or my lambda example above, you must ensure that b remains valid until you are done with delegate - taking a reference does not extend the original object's lifetime. 无论哪种情况,无论您使用的是std::bind + std::ref还是上面的lambda示例,您都必须确保b保持有效,直到您完成delegate为止-引用不会延长原始对象的寿命。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM