_Not_fn函数调用运算符的noexcept指定符

时间:2018-10-05 21:01:54

标签: c++ c++17 libstdc++

在这个问题中,我考虑了_Not_fn调用包装程序的libstdc ++ implementation

它定义了函数调用运算符的四个重载,如下所示:

 #define _GLIBCXX_NOT_FN_CALL_OP( _QUALS )                          \
       template<typename... _Args>                                  \
    decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())           \
    operator()(_Args&&... __args) _QUALS                            \
    noexcept(noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())) \
    {                                                               \
      return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn),      \
                            std::forward<_Args>(__args)...);        \
    }
       _GLIBCXX_NOT_FN_CALL_OP( & )
       _GLIBCXX_NOT_FN_CALL_OP( const & )
       _GLIBCXX_NOT_FN_CALL_OP( && )
       _GLIBCXX_NOT_FN_CALL_OP( const && )
 #undef _GLIBCXX_NOT_FN_CALL

不难看出,noexcept规范设置为:

noexcept(noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()))

其中__inv_res_t是别名模板:

template<typename _Fn2, typename... _Args>
using __inv_res_t = typename __invoke_result<_Fn2, _Args...>::type;

_S_not是静态成员函数模板:

template<typename _Tp>
static decltype(!std::declval<_Tp>())
_S_not() noexcept(noexcept(!std::declval<_Tp>()));

现在,按照noexcept规范背后的逻辑,我得出结论:

  1. 从概念上讲,函数调用运算符具有与_S_not<__inv_res_t<_Fn _QUALS, _Args...>>相同的noexcept规范。
  2. _S_not<__inv_res_t<_Fn _QUALS, _Args...>>标记为noexcept取决于是否对std::__invoke(...)的结果施加否定。

从我的角度来看,此noexcept规范不涉及包裹在not_fn中的可调用对象在传递给{{ 1}}函数调用运算符。换句话说,不会检查函数调用操作符中的not_fn本身是否会抛出

在此实施过程中我会错过任何事情吗?

cppreference.com中的实现具有更简单的noexcept规范。但是,由于known issue,此实现不适用于最新的g ++。

1 个答案:

答案 0 :(得分:2)

实际上没有要求if pygame.sprite.spritecollideany(ship, aliens): 传播not_fn。它是在[func.not_fn]中指定的,四个呼叫运算符中的每一个看起来都像这样:

noexcept

template<class... Args> auto operator()(Args&&...) const& -> decltype(!declval<invoke_result_t<const FD&, Args...>>()); 。也就是说,P0356建议添加它,而当前的noexcept说明符没有意义,并且可能由于错误而造成损害,因此提起87538


更新:此问题已在7.4、8.3和9.1中修复。