std::not_fn
在标头 <functional> 定义 | ||
template<class F > /* 未指定 */ not_fn( F&& f ); | (1) | (C++17 起) (C++20 起为 constexpr ) |
template<auto ConstFn > constexpr/* 未指定 */ not_fn()noexcept; | (2) | (C++26 起) |
ConstFn
为空指针或空成员指针则程序非良构。目录 |
[编辑]参数
f | - | 构造包装器所保有的可调用(Callable) 对象的来源对象 |
类型要求 | ||
-std::decay_t<F> 必须满足可调用(Callable) 和可移动构造(MoveConstructible) 。 | ||
-要求 std::is_constructible_v<std::decay_t<F>, F> 是 true |
[编辑]返回值
T
的函数对象。它拥有下列成员。 std::not_fn返回类型
成员对象
std::not_fn
的返回类型保有一个 std::decay_t<F> 类型的成员对象。
构造函数
explicit T( F&& f ); | (1) | (C++17 起) (C++20 起为 constexpr )(仅用于阐述*) |
T( T&& f )=default; T(const T& f )=default; | (2) | (C++17 起) |
显式预置的函数定义使得返回类型不可赋值。 | (C++20 前) |
这些构造函数是否显式预置,以及返回类型是否可赋值是未指定的。 | (C++20 起) |
成员函数 operator()
(1) | ||
template<class... Args> auto operator()( Args&&... args)& | (C++17 起) (C++20 前) | |
template<class... Args> constexprauto operator()( Args&&... args)& | (C++20 起) | |
(2) | ||
template<class... Args> auto operator()( Args&&... args)&& | (C++17 起) (C++20 前) | |
template<class... Args> constexprauto operator()( Args&&... args)&& | (C++20 起) | |
令 fd 为 std::decay_t<F> 类型的成员对象。
1) 等价于 return!std::invoke(fd, std::forward<Args>(args)...); 2) 等价于 return!std::invoke(std::move(fd), std::forward<Args>(args)...); 在调用结果时,若向原先选择的 operator() 重载的返回类型中的代换失败,则可能选择另一个重载。 | (C++17 起) (C++20 前) |
在调用结果时,若向原先选择的 operator() 重载的返回类型中的代换失败,则调用非良构,这亦能为代换失败。 | (C++20 起) |
std::not_fn无状态返回类型
返回类型是可复制构造(CopyConstructible) 的无状态类。返回类型是否可赋值是未指定的。
成员函数 operator()
template<class... Args> constexprauto operator()( Args&&... args)const | (C++26 起) | |
表达式等价于 !std::invoke(ConstFn, std::forward<Args>(args)...)。
[编辑]异常
[编辑]可能的实现
(1) not_fn |
---|
namespace detail {template<class V, class F, class... Args>constexprbool negate_invocable_impl =false;template<class F, class... Args>constexprbool negate_invocable_impl<std::void_t<decltype(!std::invoke(std::declval<F>(), std::declval<Args>()...))>, F, Args...>=true; template<class F, class... Args>constexprbool negate_invocable_v = negate_invocable_impl<void, F, Args...>; template<class F>struct not_fn_t { F f; template<class... Args, std::enable_if_t<negate_invocable_v<F&, Args...>, int>=0>constexpr decltype(auto) operator()(Args&&... args)&noexcept(noexcept(!std::invoke(f, std::forward<Args>(args)...))){return!std::invoke(f, std::forward<Args>(args)...);} template<class... Args, std::enable_if_t<negate_invocable_v<const F&, Args...>, int>=0>constexpr decltype(auto) operator()(Args&&... args)const&noexcept(noexcept(!std::invoke(f, std::forward<Args>(args)...))){return!std::invoke(f, std::forward<Args>(args)...);} template<class... Args, std::enable_if_t<negate_invocable_v<F, Args...>, int>=0>constexpr decltype(auto) operator()(Args&&... args)&&noexcept(noexcept(!std::invoke(std::move(f), std::forward<Args>(args)...))){return!std::invoke(std::move(f), std::forward<Args>(args)...);} template<class... Args, std::enable_if_t<negate_invocable_v<const F, Args...>, int>=0>constexpr decltype(auto) operator()(Args&&... args)const&&noexcept(noexcept(!std::invoke(std::move(f), std::forward<Args>(args)...))){return!std::invoke(std::move(f), std::forward<Args>(args)...);} // C++20 起需要被弃用的重载以阻止不等价但良构的重载得到选择。 template<class... Args, std::enable_if_t<!negate_invocable_v<F&, Args...>, int>=0>void operator()(Args&&...)&= delete; template<class... Args, std::enable_if_t<!negate_invocable_v<const F&, Args...>, int>=0>void operator()(Args&&...)const&= delete; template<class... Args, std::enable_if_t<!negate_invocable_v<F, Args...>, int>=0>void operator()(Args&&...)&&= delete; template<class... Args, std::enable_if_t<!negate_invocable_v<const F, Args...>, int>=0>void operator()(Args&&...)const&&= delete;};} template<class F>constexpr detail::not_fn_t<std::decay_t<F>> not_fn(F&& f){return{std::forward<F>(f)};} |
(2) not_fn |
namespace detail {template<auto ConstFn>struct stateless_not_fn {template<class... Args>constexprauto operator()(Args&&... args)constnoexcept(noexcept(!std::invoke(ConstFn, std::forward<Args>(args)...)))-> decltype(!std::invoke(ConstFn, std::forward<Args>(args)...)){return!std::invoke(ConstFn, std::forward<Args>(args)...);}};} template<auto ConstFn>constexpr detail::stateless_not_fn<ConstFn> not_fn()noexcept{ifconstexpr(std::is_pointer_v<decltype(ConstFn)>||std::is_member_pointer_v<decltype(ConstFn)>) static_assert(ConstFn != nullptr); return{};} |
[编辑]注解
std::not_fn
的目的是取代 C++03 时代的取反器 std::not1 和 std::not2。
功能特性测试宏 | 值 | 标准 | 功能特性 |
---|---|---|---|
__cpp_lib_not_fn | 201603L | (C++17) | std::not_fn() |
202306L | (C++26) | 允许将可调用对象作为常量模板实参传递给 std::not_fn |
[编辑]示例
#include <cassert>#include <functional> bool is_same(int a, int b)noexcept{return a == b;} struct S {int val;bool is_same(int arg)constnoexcept{return val == arg;}}; int main(){// 用于自由函数:auto is_differ = std::not_fn(is_same);assert(is_differ(8, 8)==false);// 等价于:!is_same(8, 8) == falseassert(is_differ(6, 9)==true);// 等价于:!is_same(8, 0) == true // 用于成员函数:auto member_differ = std::not_fn(&S::is_same);assert(member_differ(S{3}, 3)==false);// 等价于:S tmp{6}; !tmp.is_same(6) == false // 保持 noexcept 说明: static_assert(noexcept(is_differ)==noexcept(is_same)); static_assert(noexcept(member_differ)==noexcept(&S::is_same)); // 用于函数对象:auto same =[](int a, int b){return a == b;};auto differ = std::not_fn(same);assert(differ(1, 2)==true);// 等价于:!same(1, 2) == trueassert(differ(2, 2)==false);// 等价于:!same(2, 2) == false #if __cpp_lib_not_fn >= 202306Lauto is_differ_cpp26 = std::not_fn<is_same>();assert(is_differ_cpp26(8, 8)==false);assert(is_differ_cpp26(6, 9)==true); auto member_differ_cpp26 = std::not_fn<&S::is_same>();assert(member_differ_cpp26(S{3}, 3)==false); auto differ_cpp26 = std::not_fn<same>(); static_assert(differ_cpp26(1, 2)==true); static_assert(differ_cpp26(2, 2)==false);#endif}
[编辑]参阅
(C++17 弃用)(C++20 移除) | 构造定制的 std::unary_negate 对象 (函数模板) |
(C++17 弃用)(C++20 移除) | 构造定制的 std::binary_negate 对象 (函数模板) |