在这个问题中,我考虑了_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规范背后的逻辑,我得出结论:
_S_not<__inv_res_t<_Fn _QUALS, _Args...>>
相同的noexcept规范。_S_not<__inv_res_t<_Fn _QUALS, _Args...>>
标记为noexcept取决于是否对std::__invoke(...)
的结果施加否定。从我的角度来看,此noexcept规范不涉及包裹在not_fn
中的可调用对象在传递给{{ 1}}函数调用运算符。换句话说,不会检查函数调用操作符中的not_fn
本身是否会抛出。
在此实施过程中我会错过任何事情吗?
cppreference.com中的实现具有更简单的noexcept规范。但是,由于known issue,此实现不适用于最新的g ++。
答案 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中修复。