函数构造函数和nullptr

std::function constructor and nullptr

本文关键字:nullptr 构造函数 函数      更新时间:2023-10-16

为什么下面的代码输出"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 [function .wrap. function .con]

template<class F> function(F f);
template<class F, class A> function(allocator_arg_t, const A& a, F f);

8 后置条件: !*this:—fNULL函数指针。—f是指向成员的NULL指针。—F为实例函数类模板,!f

我认为这是一个bug。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求值为true时,(f == nullptr)应求值为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是一个空函数指针,上面的段落应该保证从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; }
可能

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