std::not_fn

来自cppreference.com
< cpp‎ | utility‎ | functional
 
 
 
函数对象
函数调用
(C++17)(C++23)
恒等函数对象
(C++20)
旧式绑定器与适配器
(C++17 前*)
(C++17 前*)
(C++17 前*)
(C++17 前*)
(C++17 前*)(C++17 前*)(C++17 前*)(C++17 前*)
(C++20 前*)
(C++20 前*)
(C++17 前*)(C++17 前*)
(C++17 前*)(C++17 前*)

(C++17 前*)
(C++17 前*)(C++17 前*)(C++17 前*)(C++17 前*)
(C++20 前*)
(C++20 前*)
 
在标头 <functional> 定义
template<class F >
/* 未指定 */ not_fn( F&& f );
(1) (C++17 起)
(C++20 起为 constexpr)
template<auto ConstFn >
constexpr/* 未指定 */ not_fn()noexcept;
(2) (C++26 起)
1) 创建转发调用包装器,返回其所保有的可调用对象的逻辑非。
2) 创建转发调用包装器,返回静态确定的可调用目标的逻辑非。若 ConstFn 为空指针或空成员指针则程序非良构。

目录

[编辑]参数

f - 构造包装器所保有的可调用(Callable) 对象的来源对象
类型要求
-
std::decay_t<F> 必须满足可调用(Callable) 可移动构造(MoveConstructible)
-
要求 std::is_constructible_v<std::decay_t<F>, F>true

[编辑]返回值

1) 未指定类型 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 起)
1) 构造函数从 std::forward<F>(f) 直接非列表初始化成员对象(类型是 std::decay_t<F>)。抛出所选构造函数所抛的任何异常。
2) 因为要求 std::decay_t<F>可移动构造(MoveConstructible) ,所以返回的调用包装器始终可移动构造(MoveConstructible) ,并且在 std::decay_t<F>可复制构造(CopyConstructible) 时也可复制构造(CopyConstructible)

显式预置的函数定义使得返回类型不可赋值。

(C++20 前)

这些构造函数是否显式预置,以及返回类型是否可赋值是未指定的。

(C++20 起)

成员函数 operator()

(1)
template<class... Args>

auto operator()( Args&&... args)&
-> decltype(!std::declval<
    std::invoke_result_t<std::decay_t<F>&, Args...>>());
template<class... Args>
auto operator()( Args&&... args)const&
-> decltype(!std::declval<

    std::invoke_result_t<std::decay_t<F>const&, Args...>>());
(C++17 起)
(C++20 前)
template<class... Args>

constexprauto operator()( Args&&... args)&
    noexcept(/* 见下文 */)
-> decltype(!std::invoke(
    std::declval<std::decay_t<F>&>(), std::declval<Args>()...));
template<class... Args>
constexprauto operator()( Args&&... args)const&
    noexcept(/* 见下文 */)
-> decltype(!std::invoke(

    std::declval<std::decay_t<F>const&>(), std::declval<Args>()...));
(C++20 起)
(2)
template<class... Args>

auto operator()( Args&&... args)&&
-> decltype(!std::declval<
    std::invoke_result_t<std::decay_t<F>, Args...>>());
template<class... Args>
auto operator()( Args&&... args)const&&
-> decltype(!std::declval<

    std::invoke_result_t<std::decay_t<F>const, Args...>>());
(C++17 起)
(C++20 前)
template<class... Args>

constexprauto operator()( Args&&... args)&&
    noexcept(/* 见下文 */)
-> decltype(!std::invoke(
    std::declval<std::decay_t<F>>(), std::declval<Args>()...));
template<class... Args>
constexprauto operator()( Args&&... args)const&&
    noexcept(/* 见下文 */)
-> decltype(!std::invoke(

    std::declval<std::decay_t<F>const>(), std::declval<Args>()...));
(C++20 起)

fdstd::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 前)
1)表达式等价!std::invoke(fd, std::forward<Args>(args)...)
2)表达式等价!std::invoke(std::move(fd), std::forward<Args>(args)...)

在调用结果时,若向原先选择的 operator() 重载的返回类型中的代换失败,则调用非良构,这亦能为代换失败

(C++20 起)
2) 以下类型的值。

std::not_fn无状态返回类型

返回类型是可复制构造(CopyConstructible) 的无状态类。返回类型是否可赋值是未指定的。

成员函数 operator()

template<class... Args>

constexprauto operator()( Args&&... args)const
    noexcept(/* 见下文 */)

-> decltype(!std::invoke(ConstFn, std::declval<Args>()...));
(C++26 起)

表达式等价!std::invoke(ConstFn, std::forward<Args>(args)...)

[编辑]异常

1) 不抛出异常,除非 fd 的构造抛出异常。

[编辑]可能的实现

(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::not1std::not2

功能特性测试标准功能特性
__cpp_lib_not_fn201603L(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 对象
(函数模板)[编辑]
close