为什么以下代码打印“0”作为输出?
#include <functional>
#include <iostream>
int main()
{
typedef void (*fp_t)();
fp_t fp = nullptr;
std::function<void()> f = fp;
std::cout << (f == nullptr) << '\n';
}
我用gcc 4.7.2和MSVC-11.0测试了它。
我认为它应该打印“1”,因为标准中引用了以下内容:
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 后置条件:
!*this
如果符合以下任何条件: -f
是NULL
功能指针。 -f
是指向成员的NULL
指针。 -F
是一个实例 函数类模板和!f
答案 0 :(得分:15)
我认为这是一个错误。根据C ++ 11标准的第20.8.11.2.6 / 1段:
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 退货:
!f
。
因此,当且仅当(f == nullptr)
评估为true
时,!f
才会评估为true
。然后,第20.8.11.2.1 / 8段规定:
template<class F> function(F f); template <class F, class A> function(allocator_arg_t, const A& a, F f);
[...]
8 后置条件:
!*this
如果符合以下任何条件:-
f
是一个NULL函数指针。[...]
由于fp
是一个空函数指针,上面的段落应该保证在从f
初始化fp
后,表达式!f
计算为true
。这反过来意味着与nullptr
的比较应该返回true
(通过§20.8.11.2.6/ 1)。
这反过来意味着这是一个错误。
答案 1 :(得分:4)
不是答案,但有些细节(gcc)太大而无法发表评论:
使用
检查功能的有效性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; }
可能
template<typename _Tp>
static bool
_M_not_empty_function(const _Tp*& __fp)
{ return __fp; }
旨在使用功能指针,而不是它。相反,使用的一般情况可能只适用于功能对象。
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);
}
生成
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