This code fails to build in VC2013: (EDIT: I'm not asking why it fails to build)
#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; } With error:
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap(283): error C2064: term does not evaluate to a function taking 0 arguments 1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(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.0\vc\include\functional(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.0\vc\include\functional(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.0\vc\include\functional(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.0\vc\include\functional(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.0\vc\include\functional(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.0\vc\include\functional(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.0\vc\include\functional(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.0\vc\include\functional(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.0\vc\include\functional(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:\work\teststdfunction\teststdfunction.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:\work\teststdfunction\teststdfunction.cpp(16) : see reference to function template instantiation 'std::function<void (void)>::function<int>(_Fx &&)' being compiled 1> with 1> [ 1> _Fx=int 1> ] (Note the '_Fx=int' at the last two reported errors).
I can live with that, as changing MyStruct rc(NULL) to MyStruct rc(nullptr) solves the error. Two things however remain a mystery:
1) Removing the const qualifier from MyStruct ctor (MyStruct( std::function<void()>& func) gives a very, very different error:
1>f:\work\main\dev\common\teststdfunction\teststdfunction\teststdfunction.cpp(16): error C2664: 'MyStruct::MyStruct(const MyStruct &)' : cannot convert argument 1 from 'int' to 'std::function &'
Which makes more sense than the original error, and now fixing NULL to nullptr doesn't solve it. Why does int (or nullptr) refuse to cast to std::function<>& but agree to cast to a const std::function<>& ?
2) The original code compiles and works as expected in VS2010. Is it an obscure VS2010 library bug?
EDIT: As far as the const/non const question goes, I now think the casting involved and potential type mismatch are probably a red herring. The argument passed - either NULL or nullptr - is a literal and thus a const. It just cannot bind to a non const reference. For example:
const int& a = 8; // Ok int& b = 9; // error C2440: 'initializing' : cannot convert from 'int' to 'int &' Does that sound right? Am I still missing something?
nullptris a value of typenullptr_twhich is what the constructor ofstd::functionaccepts.NULLis not necessarily defined asnullptrand may be a different value. Usenullptrnot `NULL.