C++ std::函数构造函数和nullptr

C++ std::函数构造函数和nullptr,c++,c++11,C++,C++11,为什么下面的代码将“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'; } #包括 #包括 int mai

为什么下面的代码将“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';
}
#包括
#包括
int main()
{
typedef void(*fp_t)();
fp_t fp=nullptr;
函数f=fp;

std::cout我认为这是一个bug。根据C++11标准第20.8.11.2.6/1段:

[……]

8后置条件:
!*如果以下任一条件成立,则此

-
f
是一个空函数指针。

[……]

由于
fp
是一个空函数指针,上述段落应保证在从
fp
初始化
f
后,表达式
!f
计算为
true
。这反过来意味着与
nullptr
的比较应返回
true
(根据§20.8.11.2.6/1)


这反过来意味着这是一个bug。

不是答案,而是一些细节(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; }
模板
静态布尔
_M_非空函数(常数函数和函数)
{return static_cast(u f);}
模板
静态布尔
_M_not_empty_函数(常数Tp*&常数fp)
{return\uuu fp;}
模板
静态布尔
_M_not_empty_函数(_Tp_类::*const&u mp)
{return\uump;}
模板
静态布尔
_M_not_empty_函数(const _Tp&)
{返回true;}
大概

template<typename _Tp>
  static bool
  _M_not_empty_function(const _Tp*& __fp)
  { return __fp; }
模板
静态布尔
_M_not_empty_函数(常数Tp*&常数fp)
{return\uuu 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);
}
模板
静态布尔
M_not_empty_函数(常数Tp*&常数fp)
{return\uuu fp;}
int main()
{
typedef void(*fp_t)();
fp_t fp=nullptr;
返回M_not_empty_函数(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
错误:调用'M_not_empty_函数(void(*&))时没有匹配的函数
注:候选人为:
注:模板bool M_not_empty_函数(const _Tp*&)
注意:模板参数扣除/替换失败:
注意:类型“const\u Tp”和“void()”具有不兼容的cv限定符

!*这并不意味着
这==nullptr
是真的。一个使用
运算符bool
,另一个使用
运算符==
。不过,我想说他们应该比较相等。如果
nullptr
的相等值为空,则比较true,并且使用空函数指针初始化它会使其为空。@chris:Acco根据20.8.11.2.6/1,
f==nullptr
返回
!f
。我倾向于认为这是一个bug@AndyProwl,同意。我的第一条评论完全基于调用哪个函数,并且它们不必总是做相同的事情。在
std::function
的情况下,结果是它们做了。这太奇怪了……gcc 4.7.2和nd MSVC-11.0给出了output@NikitaTrophimov:是的,确实很奇怪。FWIW,Clang给出了输出Iexpect@NikitaTrophimov:是,在上下文中转换为
bool
(将调用
std::function
显式运算符bool()
)@NikitaTrophimov:如果从
nullptr
构造,它没有目标,
!f
的计算结果为
true
。@NikitaTrophimov:我不知道为什么会出现错误,我只知道标准非常清楚行为应该是什么(见答案)。感谢您为我调试了它,我会尽快在GCC中修复它:)
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