std::bind 无法在 MSVC 上使用 std::atomic_bool& 进行编译
std::bind fails to compile with std::atomic_bool& on MSVC
我正在使用 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
是我遗漏了什么还是编译器错误?
bind
总是尝试存储参数的 值 ,从不引用。 atomic
类型无法复制。所以当 bind
尝试复制它们时,它将失败。
这是 reference_wrapper
存在的原因之一:允许在需要值的地方使用对对象的引用。事实上, std::ref
的发明主要是为了处理 bind
.
看,bind
可以存储对参数的引用。但是,存储引用可能非常危险,尤其是对堆栈变量的引用可能会在调用 bind
仿函数之前的某个时间停止存在。因此 bind
迫使您 明确 何时存储引用;它让你使用 ref
.
std::atomic
类型不是 CopyConstructible。您对 std::bind()
的(错误)调用会创建副本。
此外,您似乎误解了引用的工作原理 - auto& ref = b
当然会创建对 b
的引用;但是 ref
本身仍然是一个左值,因此,将它传递给 std::bind()
不会突然改变行为。
最后,考虑到您使用的是 C++11 的原子,这意味着您还可以访问 lambda,这将允许您表达您的代码而不必求助于 std::ref
:
std::function<void()> delegate = [&b] { b = true; };
但是要小心!在任何一种情况下,无论您使用 std::bind
+ std::ref
还是我上面的 lambda 示例,您 必须 确保 b
在您完成之前保持有效delegate
- 使用引用 不会 延长原始对象的生命周期。
我正在使用 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
是我遗漏了什么还是编译器错误?
bind
总是尝试存储参数的 值 ,从不引用。 atomic
类型无法复制。所以当 bind
尝试复制它们时,它将失败。
这是 reference_wrapper
存在的原因之一:允许在需要值的地方使用对对象的引用。事实上, std::ref
的发明主要是为了处理 bind
.
看,bind
可以存储对参数的引用。但是,存储引用可能非常危险,尤其是对堆栈变量的引用可能会在调用 bind
仿函数之前的某个时间停止存在。因此 bind
迫使您 明确 何时存储引用;它让你使用 ref
.
std::atomic
类型不是 CopyConstructible。您对 std::bind()
的(错误)调用会创建副本。
此外,您似乎误解了引用的工作原理 - auto& ref = b
当然会创建对 b
的引用;但是 ref
本身仍然是一个左值,因此,将它传递给 std::bind()
不会突然改变行为。
最后,考虑到您使用的是 C++11 的原子,这意味着您还可以访问 lambda,这将允许您表达您的代码而不必求助于 std::ref
:
std::function<void()> delegate = [&b] { b = true; };
但是要小心!在任何一种情况下,无论您使用 std::bind
+ std::ref
还是我上面的 lambda 示例,您 必须 确保 b
在您完成之前保持有效delegate
- 使用引用 不会 延长原始对象的生命周期。