将 NULL/nullptr 转换为 std::function<>& 时失败
Failure when casting NULL/nullptr to std::function<>&
这段代码在VC2013中无法构建:(编辑:我不是在问为什么它无法构建(
#include <functional>
struct MyStruct
{
std::function<void()> m_Func;
MyStruct( const std::function<void()>& func) : m_Func(func) {}
};
int main()
{
MyStruct rc( NULL );
return 0;
}
有错误:
1>c:program files (x86)microsoft visual studio 12.0vcincludexrefwrap(283): error C2064: term does not evaluate to a function taking 0 arguments
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<int,false>::_ApplyX<_Rx,>(void)' being compiled
1> with
1> [
1> _Ret=void
1> , _Rx=void
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<int,false>::_ApplyX<_Rx,>(void)' being compiled
1> with
1> [
1> _Ret=void
1> , _Rx=void
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(226) : while compiling class template member function 'void std::_Func_impl<_MyWrapper,_Alloc,_Ret,>::_Do_call(void)'
1> with
1> [
1> _Alloc=std::allocator<std::_Func_class<void,>>
1> , _Ret=void
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(495) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,>' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_Func_class<void,>>
1> , _Ret=void
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Ty=int
1> , _Alloc=std::allocator<std::_Func_class<void,>>
1> , _Fty=int
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Ty=int
1> , _Alloc=std::allocator<std::_Func_class<void,>>
1> , _Fty=int
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,>>>(_Fty &&,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Ty=int
1> , _Fty=int
1> , _Alloc=std::allocator<std::_Func_class<void,>>
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,>>>(_Fty &&,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Ty=int
1> , _Fty=int
1> , _Alloc=std::allocator<std::_Func_class<void,>>
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<_Ty>(_Fty &&)' being compiled
1> with
1> [
1> _Ret=void
1> , _Ty=int
1> , _Fty=int
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludefunctional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<_Ty>(_Fty &&)' being compiled
1> with
1> [
1> _Ret=void
1> , _Ty=int
1> , _Fty=int
1> ]
1> f:workteststdfunctionteststdfunction.cpp(16) : see reference to function template instantiation 'std::function<void (void)>::function<int>(_Fx &&)' being compiled
1> with
1> [
1> _Fx=int
1> ]
1> f:workteststdfunctionteststdfunction.cpp(16) : see reference to function template instantiation 'std::function<void (void)>::function<int>(_Fx &&)' being compiled
1> with
1> [
1> _Fx=int
1> ]
(请注意最后两个报告错误的"_Fx=int"(。
我可以忍受这一点,因为将MyStruct rc(NULL)
更改为MyStruct rc(nullptr)
可以解决错误。 然而,有两件事仍然是个谜:
1(从MyStruct ctor中删除常量限定符(MyStruct( std::function<void()>& func)
会给出一个非常非常不同的错误:
1>f:\work\main\dev\common\teststdfunction\teststdfunction\teststdfunction.cpp(16(: 错误 C2664: 'MyStruct::MyStruct(const MyStruct &(' : 无法转换 参数 1 从 'int' 到 'std::function &'
这比原始错误更有意义,现在将 NULL 修复为 nullptr 并不能解决它。 为什么int(或nullptr(拒绝投射到std::function<>&
而是同意投射到const std::function<>&
?
2(原始代码在VS2010中按预期编译和工作。 这是一个晦涩难懂的VS2010库错误吗?
编辑:就 const/non const 问题而言,我现在认为所涉及的演员阵容和潜在的类型不匹配可能是一个红鲱鱼。 传递的参数 - NULL 或 nullptr - 是一个文字,因此是一个常量。它只是无法绑定到非常量引用。 例如:
const int& a = 8; // Ok
int& b = 9; // error C2440: 'initializing' : cannot convert from 'int' to 'int &'
听起来对吗? 我还缺少什么吗?
这里的特殊性与构造函数模板约束和其他隐式转换有关。
nullptr
工作的原因是因为std::function
有一个特定的构造函数来获取它。此构造函数将始终是该参数的最佳匹配项,因为函数模板在其他条件相同的情况下被列为较低的优先级。
通常,0
会隐式转换为nullptr
这很好。问题在于它也可以传递给从函数对象构造的不受约束的函数模板构造函数。这不需要隐式转换,因此所有都不相等,因此首选此构造函数 - 这会导致您看到int
不是有效函数对象的错误。
libstdc++ 和 libc++ 并非不表现出这种行为,因为它们已经实现了针对此问题的 C++14 修复程序,这限制了构造函数。C++11 没有,因此这种行为非常符合 C++11 实现。
这种问题就是为什么NULL
是你不应该使用的可怕东西。事实上,VS2010团队不得不在最后一刻匆匆nullptr
作为附加功能,因为NULL
与C++,有史以来,尤其是C++11中的所有其他功能的交互都非常糟糕。
对于const
与非const
参考文献,其他答案已经充分解释了这个问题。
当使用std::function
时,您可以找到其他 WTF,而没有 C++14 中附带的受约束的构造函数修复 - 这不是唯一的一个。长话短说,这是 C++11 标准中的缺陷,而不是 VS 中的缺陷。VS2010编译它可能是一个编译器重载解析错误。
将T
转换为U&
是行不通的,这是故意的。您可以投射到U const&
.原因是对临时 U 对象的更改不会传播回 T 值。
VS2010在这方面有点错误,并且确实允许演员阵容(但使用适当的设置,会警告它(
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如果我std::dynamic_pointer_cast并且底层dynamic_cast的结果为null,那么返回的sh
- 如何在 c++ 中'NULL'字符串
- c++使用foreach使数组为null
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 当使用通配符和null指针调用函数时,对输出的说明
- <<操作员在下面的行中工作
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 如何在映射中返回null
- 为什么返回 NULL 不会破坏函数?
- 构造函数中的 QQuickItem 父项 null
- 检查字符串是否"null" C++
- fopen 在 gdb 中返回 NULL
- what(): basic_string::_M_construct null not valid
- 在这个函数中是有缺陷的,因为取消引用 null 是无效的,所以我想更改代码
- 为什么在排序链表上的这种合并实现总是将两个列表都设置为 NULL,而只有一个应该设置一个列表?
- 为什么要从main()返回NULL?
- 为什么 nlohmann/json 序列化 "null" 而不是在 double 上"0"?
- 当目标指针不是基类的类型时,为什么允许dynamic_cast为多态类生成 null 指针?