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

时间:2016-12-31 14:09:43

标签: c++ c++11 stdbind stdatomic


我正在使用VC ++编译我的程序(使用Visual Studio 2015,更新3),并且某些代码段无法编译。

基本上,我想绑定一个函数,该函数使用原子布尔值获取对原子布尔的引用。自包含代码:

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

我有什么想念或编译错误吗?

2 个答案:

答案 0 :(得分:2)

bind总是尝试存储参数的,从不引用。无法复制atomic种类型。因此,当bind尝试复制它们时,它将失败。

这是reference_wrapper存在的原因之一:允许在预期值的位置使用对象的引用。实际上,std::ref的发明主要是为了处理bind

请参阅,bind可能存储了对参数的引用。但是,存储引用可能非常危险,尤其是对堆栈变量的引用,这些变量可能会在调用bind仿函数之前的某个时间停止存在。因此bind强制您在存储引用时显式;它会让你使用ref

答案 1 :(得分:1)

std::atomic类型不是CopyConstructible。您对std::bind()的(错误)调用会创建副本。

此外,您似乎误解了引用的工作原理 - auto& ref = b当然会创建对b的引用;但是ref本身仍然是左值,因此将其传递给std::bind()并不会突然改变行为。

最后,考虑到您使用原子,即C ++ 11,这意味着您还可以访问lambdas,这样您就可以表达代码而无需诉诸std::ref

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

但要注意!在任何一种情况下,无论您使用上面的std::bind + std::ref还是我的lambda示例,必须确保b保持有效,直到您完成{{1 - 使用引用不会扩展原始对象的生命周期。