18

为什么下面的代码会打印“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 函数构造/复制/销毁[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如果以下任何一项成立: —fNULL 函数指针。—fNULL指向成员的指针。—F是函数类模板的一个实例,并且!f

4

2 回答 2

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是一个空函数指针,上面的段落应该保证在ffromfp的初始化之后,表达式的!f计算结果为true。这反过来意味着,与的比较nullptr应该返回true(根据 § 20.8.11.2.6/1)。

这反过来意味着,这是一个错误。

于 2013-05-29T21:00:09.247 回答
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
于 2013-05-29T21:16:34.277 回答