Why does the following code prints "0" as the output?
#include <functional>
#include <iostream>
int main()
{
typedef void (*fp_t)();
fp_t fp = nullptr;
std::function<void()> f = fp;
std::cout << (f == nullptr) << '\n';
}
I've tested it both with gcc 4.7.2 and MSVC-11.0.
I think that it's should print "1" because of the following quote from the standard:
ISO/IEC 14882:2011
20.8.11.2.1 function construct/copy/destroy [func.wrap.func.con]
template<class F> function(F f);
template<class F, class A> function(allocator_arg_t, const A& a, F f);
...
8 Postconditions:
!*this
if any of the following hold: —f
is aNULL
function pointer. —f
is aNULL
pointer to member. —F
is an instance of the function class template, and!f
I think this is a bug. Per paragraph 20.8.11.2.6/1 of the C++11 Standard:
template <class R, class... ArgTypes> bool operator==(const function<R(ArgTypes...)>& f, nullptr_t) noexcept; template <class R, class... ArgTypes> bool operator==(nullptr_t, const function<R(ArgTypes...)>& f) noexcept;
1 Returns:
!f
.
Therefore, (f == nullptr)
should evaluate to true
if and only if !f
evaluates to true
. Then, paragraph 20.8.11.2.1/8 specifies:
template<class F> function(F f); template <class F, class A> function(allocator_arg_t, const A& a, F f);
[...]
8 Postconditions:
!*this
if any of the following hold:—
f
is a NULL function pointer.[...]
Since fp
is a null function pointer, the above paragraph should guarantee that after initialization of f
from fp
, the expression !f
evaluates to true
. Which in turn means, that the comparison with nullptr
should return true
(by § 20.8.11.2.6/1).
Which in turns means, that this is a bug.
Not an answer, but some details (gcc) too large for a comment:
Function is checked for validity with
template<typename _Signature>
static bool
_M_not_empty_function(const function<_Signature>& __f)
{ return static_cast<bool>(__f); }
template<typename _Tp>
static bool
_M_not_empty_function(const _Tp*& __fp)
{ return __fp; }
template<typename _Class, typename _Tp>
static bool
_M_not_empty_function(_Tp _Class::* const& __mp)
{ return __mp; }
template<typename _Tp>
static bool
_M_not_empty_function(const _Tp&)
{ return true; }
Probably
template<typename _Tp>
static bool
_M_not_empty_function(const _Tp*& __fp)
{ return __fp; }
is intended to work with functional pointers, buit it doesn't. Instead general case is used that is probably intended for functional objects only.
template<typename _Tp>
static bool
M_not_empty_function(const _Tp*& __fp)
{ return __fp; }
int main()
{
typedef void (*fp_t)();
fp_t fp = nullptr;
return M_not_empty_function(fp);
}
generates
error: no matching function for call to 'M_not_empty_function(void (*&)())'
note: candidate is:
note: template<class _Tp> bool M_not_empty_function(const _Tp*&)
note: template argument deduction/substitution failed:
note: types 'const _Tp' and 'void()' have incompatible cv-qualifiers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With