函数对象

来自cppreference.com
< cpp‎ | utility


 
 
工具库
语言支持
类型支持(基本类型、RTTI)
库功能特性测试宏 (C++20)
动态内存管理
程序工具
协程支持 (C++20)
变参数函数
调试支持
(C++26)
三路比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
初等字符串转换
(C++17)
(C++17)

 
函数对象
函数调用
(C++17)(C++23)
恒等函数对象
(C++20)
通透运算符包装器
(C++14)
(C++14)
(C++14)
(C++14)  
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)

旧式绑定器与适配器
(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 前*)
 

任何定义了函数调用运算符的对象都是函数对象。C++ 支持创建、操作新的函数对象,同时也提供了许多内置的函数对象。

函数调用

仅用于阐述的 INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N) 操作定义如下:

令类型 Objstd::remove_cv<std::remove_reference<decltype(arg_0)>::type>::type

  • 如果 f 是类 C成员函数指针,那么 INVOKE(f, obj, arg_1, arg_2, ..., arg_N) 等价于:
  • (obj.*f)(arg_1, arg_2, ..., arg_N)(在对象上调用成员函数)。
  • (obj.get().*f)(arg_1, arg_2, ..., arg_N)(在被特殊引用的对象上调用成员函数)。
  • 否则
  • ((*obj).*f)(arg_1, arg_2, ..., arg_N)(在解引用的对象上调用成员函数)。
  • 否则,如果 N == 1 并且 f 是类 C数据成员指针,那么 INVOKE(mptr, obj) 等价于:
  • obj.*mptr(访问对象的数据成员)。
  • obj.get().*mptr(访问被特殊引用的对象的数据成员)。
  • 否则
  • (*obj).*mptr(解引用的对象的数据成员)。
  • 否则
  • INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N) 等价于 f(arg_0, arg_1, arg_2, ..., arg_N)(调用可调用物)。


仅用于阐述的 INVOKE<R>(f, arg_0, arg_1, arg_2, ..., arg_N) 操作的定义如下:

  • 如果 R 是(可能有 cv 限定的)void
  • static_cast<void>(INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N))
  • 否则
  • 隐式转换到 RINVOKE(f, arg_0, arg_1, arg_2, ..., arg_N)

令类型 Actualdecltype(INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N))

  • INVOKE<R>(f, arg_0, arg_1, arg_2, ..., arg_N) 非良构。
(C++23 起)
(C++11 起)


std::invoke / std::invoke_r (C++23 起) 可以按 INVOKE / INVOKE<R> (C++23 起) 的规则以给定实参调用任何可调用 (Callable) 对象。

(C++17)(C++23)
以给定实参和可能指定的返回类型 (C++23 起)调用任意可调用 (Callable) 对象
(函数模板)

函数包装器

这些包装器类提供存储任意函数对象的支持。

(C++11)
任意可复制构造的可调用对象的可复制包装
(类模板)
任意可调用对象的仅移动包装,支持给定调用签名中的限定符
(类模板)
任意可复制构造的可调用对象的可复制包装,支持给定调用签名中的限定符
(类模板)
任意可调用对象的无所有权包装
(类模板)
调用空的 std::function 时抛出的异常
(类)
(C++11)
从成员指针创建出函数对象
(函数模板)

恒等

std::identity 是恒等函数对象:它不修改地返回实参。

(C++20)
返回其未修改的实参的函数对象
(类)

部分函数应用

std::bind_frontstd::bind 提供部分函数应用的支持,即绑定实参到函数以创建新函数。

(C++20)(C++23)
按顺序绑定一定数量的实参到函数对象
(函数模板)
(C++11)
绑定一或多个实参到函数对象
(函数模板)
指示对象为 std::bind 表达式,或能被用作这种表达式
(类模板)
表明一个对象是标准占位符,或者可以用作标准占位符
(类模板)
在命名空间 std::placeholders 定义
用作 std::bind 表达式中的未绑定实参的占位符
(常量)

取反器

std::not_fn 创建对传递给它的可调用对象的结果取反的函数对象。

(C++17)
创建返回其保有的函数对象的结果之补的函数对象
(函数模板)

搜索器

提供实现数种字符串搜索算法的搜索器。它们能直接使用或用于 std::search

标准 C++ 库搜索算法实现
(类模板)
Boyer-Moore 搜索算法实现
(类模板)
Boyer-Moore-Horspool 搜索算法实现
(类模板)

引用包装器

引用包装器允许在可复制的函数对象中存储引用实参:

可复制构造 (CopyConstructible) 可复制赋值 (CopyAssignable) 的引用包装器
(类模板)
(C++11)(C++11)
创建具有从其实参推导的类型的 std::reference_wrapper
(函数模板)
获取包装于 std::reference_wrapper 的引用类型
(类模板)

透明函数对象

关联容器无序关联容器 (C++20 起)提供了异质查找和擦除 (C++23 起)操作,但是它们只有在提供的函数对象类型 T 透明 时才会启用:有限定标识符 T::is_transparent 合法,并且指代一个类型。

标准库中的所有透明函数对象类型都会定义一个嵌套类型 is_transparent。不过用户定义的透明函数对象类型并不需要直接提供 is_transparent 为其嵌套类型:只要 T::is_transparent 满足上述透明要求,它也可以在基类中定义。

(C++14 起)

运算符函数对象

C++ 针对常用的算术和逻辑运算定义了以下函数对象。

各个 void 特化会根据它们的实参来推导形参类型和返回类型,它们都是透明的。

(C++14 起)
算术运算
实现 x + y 的函数对象
(类模板)
实现 x + y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x - y 的函数对象
(类模板)
实现 x - y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x * y 的函数对象
(类模板)
实现 x * y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x / y 的函数对象
(类模板)
进行 x / y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x % y 的函数对象
(类模板)
实现 x % y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 -x 的函数对象
(类模板)
实现 -x 的函数对象,推导形参类型和返回类型
(类模板特化)
比较
实现 x == y 的函数对象
(类模板)
实现 x == y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x != y 的函数对象
(类模板)
实现 x != y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x > y 的函数对象
(类模板)
实现 x > y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x < y 的函数对象
(类模板)
实现 x < y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x >= y 的函数对象
(类模板)
实现 x >= y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x <= y 的函数对象
(类模板)
实现 x <= y 的函数对象,推导形参类型和返回类型
(类模板特化)
逻辑运算
实现 x && y 的函数对象
(类模板)
实现 x && y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x || y 的函数对象
(类模板)
实现 x || y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 !x 的函数对象
(类模板)
实现 !x 的函数对象,推导形参类型和返回类型
(类模板特化)
位运算
实现 x & y 的函数对象
(类模板)
实现 x & y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x | y 的函数对象
(类模板)
实现 x | y 的函数对象,推导形参类型和返回类型
(类模板特化)
实现 x ^ y 的函数对象
(类模板)
实现 x ^ y 的函数对象,推导形参类型和返回类型
(类模板特化)
(C++14)
实现 ~x 的函数对象
(类模板)
实现 ~x 的函数对象,推导形参类型和返回类型
(类模板特化)


受约束的比较函数对象

以下比较函数对象受约束

  • 相等性运算符(ranges::equal_toranges::not_equal_to)要求实参类型满足 equality_comparable_with
  • 关系运算符(ranges::lessranges::greaterranges::less_equalranges::greater_equal)要求实参类型满足 totally_ordered_with
  • 三路比较运算符(compare_three_way)要求实参类型满足 three_way_comparable_with

这些函数对象都是透明的。

实现 x == y 的受约束函数对象
(类)
实现 x != y 的受约束函数对象
(类)
实现 x < y 的受约束函数对象
(类)
实现 x > y 的受约束函数对象
(类)
实现 x <= y 的受约束函数对象
(类)
实现 x >= y 的受约束函数对象
(类)
实现 x <=> y 的受约束函数对象
(类)
(C++20 起)


辅助项

以下仅用于阐释的各项由标准库中的一些组件所用,但它们并不属于标准库接口。

template< class Fn, class... Args >

concept /*callable*/ =
    requires (Fn&& fn, Args&&... args) {
        std::forward<Fn>(fn)(std::forward<Args>(args)...);

    };
(1) (仅用于阐述*)
template< class Fn, class... Args >

concept /*nothrow-callable*/ =
    /*callable*/<Fn, Args...> &&
    requires (Fn&& fn, Args&&... args) {
        { std::forward<Fn>(fn)(std::forward<Args>(args)...) } noexcept;

    };
(2) (仅用于阐述*)
template< class Fn, class... Args >
using /*call-result-t*/ = decltype(std::declval<Fn>()(std::declval<Args>()...));
(3) (仅用于阐述*)
template< const auto& T >
using /*decayed-typeof*/ = decltype(auto(T));
(4) (仅用于阐述*)
(C++26 起)


旧式绑定器与适配器

早期提供功能支持的一些工具都已经被弃用和移除:

基类
(C++11 中弃用)(C++17 中移除)
与适配器兼容的一元函数基类
(类模板)
(C++11 中弃用)(C++17 中移除)
与适配器兼容的二元函数基类
(类模板)
绑定器
(C++11 中弃用)(C++17 中移除)
持有一个二元函数和它的实参之一的函数对象
(类模板)
(C++11 中弃用)(C++17 中移除)
将一个实参绑定到二元函数
(函数模板)
函数适配器
(C++11 中弃用)(C++17 中移除)
适配器兼容的包装器,用于包装一元函数的指针
(类模板)
(C++11 中弃用)(C++17 中移除)
适配器兼容的包装器,用于包装二元函数的指针
(类模板)
(deprecated in C++11)(C++17 中移除)
从函数指针创建与适配器兼容的函数对象包装器
(函数模板)
(C++11 中弃用)(C++17 中移除)
指向零元或一元成员函数指针的包装器,可以一个对象指针调用
(类模板)
(C++11 中弃用)(C++17 中移除)
从成员函数指针创建包装器,可以一个对象指针调用
(函数模板)
指向零元或一元成员函数指针的包装器,可以一个对象引用调用
(类模板)
(C++11 中弃用)(C++17 中移除)
从成员函数指针创建包装器,能以一个对象引用调用
(函数模板)
(C++17 中弃用)(C++20 中移除)
包装器函数对象,返回所持有的一元谓词的补
(类模板)
(C++17 中弃用)(C++20 中移除)
包装器函数对象,返回所持有的二元谓词的补
(类模板)
(C++17 中弃用)(C++20 中移除)
构造定制的 std::unary_negate 对象
(函数模板)
(C++17 中弃用)(C++20 中移除)
构造定制的 std::binary_negate 对象
(函数模板)
(C++20 前)

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
LWG 185 C++98 使用函数对象就会增加程序效率 移除该断言
LWG 660 C++98 缺失了执行逐位操作的函数对象 已补充
LWG 2149 C++98 接受一个或两个实参的函数对象需要提供嵌套类型以表示实参和结果类型 不需要
LWG 2219 C++11 INVOKE 没有正确处理 std::reference_wrapper 能正确处理
LWG 2420 C++11 INVOKE<R>Rvoid 时不会丢弃返回值 此时会丢弃返回值
LWG 2926
(P0604R0)
C++11 带有返回类型 RINVOKE 操作的形式是
INVOKE(f, t1, t2, ..., tN, R)
改成
INVOKE<R>(f, t1, t2, ..., tN)
LWG 3655 C++11 由于 LWG 问题 2219 的解决方案,INVOKE 没有正确处理联合体 能正确处理