std::bind_front, std::bind_back

来自cppreference.com
< cpp‎ | utility‎ | functional
 
 
工具库
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(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++11)
(C++11)
部分函数应用
(C++11)
bind_frontbind_back
(C++20)(C++23)
函数调用
(C++17)(C++23)
恒等函数对象
(C++20)
引用包装
(C++11)(C++11)
通透运算符包装
(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++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, class... Args>
constexpr /*unspecified*/ bind_front( F&& f, Args&&... args );
(1) (C++20 起)
template <class F, class... Args>
constexpr /*unspecified*/ bind_back( F&& f, Args&&... args );
(2) (C++23 起)

函数模板 bind_frontbind_backf 生成转发调用包装。调用此包装等价于绑定(1)首,或者(2)尾, sizeof...(Args) 个参数到 args 再调用 f

换言之:

  • std::bind_front(f, bound_args...)(call_args...) 等价于 std::invoke(f, bound_args..., call_args...)
  • std::bind_back(f, bound_args...)(call_args...) 等价于 std::invoke(f, call_args..., bound_args...)

若下列任一为 false 则程序为非良构:

参数

f - 将绑定某些参数到的可调用 (Callable) 对象(函数对象、指向函数指针、到函数的引用、指向成员函数指针或指向数据成员指针)
args - 参数列表,绑定(1)首,或者(2)尾, sizeof...(Args) 个参数到 f
类型要求
-
std::decay_t<F>std::decay_t<Args>... 中的每个类型 必须符合可移动构造 (MoveConstructible) 的要求。

返回值

未指定的 T 类型函数对象,除了二次以相同参数调用 std::bind_frontstd::bind_back 返回的类型相同。

返回的对象(调用包装)有下列属性:

部分绑定 返回类型

部分绑定 表示 std::bind_frontstd::bind_back

成员对象

返回的对象表现为如同它保有从 std::forward<F>(f) 直接非列表初始化的 std::decay_t<F> 类型成员对象 fd ,以及用 std::tuple<std::decay_t<Args>...>(std::forward<Args>(args)...) 构造的 std::tuple 对象 tup (这会解包任何 std::reference_wrapper ),除了返回对象的赋值行为未指定,且名称只为说明。

构造函数

部分绑定 的构造函数表现为其赋值/移动构造函数进行逐成员复制/移动。若其所有成员对象(指定如上)为可复制构造 (CopyConstructible) )则它为 可复制构造 (CopyConstructible) ,否则为可移动构造 (MoveConstructible)

成员函数 operator()

给定从先前调用 部分绑定(f, args...) 获得的对象 G ,在函数调用表达式 g(call_args...) 中调用指代 G 的泛左值 g 时,发生存储对象的调用,如同用:

  • std::invoke(g.fd, std::get<Ns>(g.tup)..., call_args...),如果 部分绑定std::bind_front,或用:
  • std::invoke(g.fd, call_args..., std::get<Ns>(g.tup)...),如果 部分绑定std::bind_back

其中:

  • Ns 是整数包 0, 1, ..., (sizeof...(Args) - 1)
  • g 若在调用表达式中是左值,则在 std::invoke 表达式中是左值,否则是右值。从而 std::move(g)(call_args...) 能移动绑定的参数到调用中,而 g(call_args...) 会复制。

g 拥有 volatile 限定类型则行为未定义。

若其所调用的 std::invoke 表达式为 noexcept 则成员 operator() 为 noexcept (换言之,它保持底层调用运算符的异常说明)。

异常

仅若构造存储的函数对象或任何绑定的参数时抛出才会抛出。

注解

有意令此类函数取代 std::bind 。不同于 std::bind ,它们不支持任意参数重排,而且不特别处理嵌套的 bind 表达式或 std::reference_wrapper 。另一方面,它们注重调用包装对象的值类别,并传播底层调用运算符的异常规定。

std::invoke 中描述,调用指向非静态成员函数指针或指向非静态数据成员指针时,首参数必须是到要访问其成员的对象的引用或指针(可以包含智能指针,如 std::shared_ptrstd::unique_ptr )。

复制或移动给 std::bind_frontstd::bind_back 的参数,而决不按引用传递,除非用 std::refstd::cref 包装它们。

功能特性测试 标准 注释
__cpp_lib_bind_front 201907L (C++20) std::bind_front
__cpp_lib_bind_back 202202L (C++23) std::bind_back

示例

#include <functional>
#include <iostream>
 
int minus(int a, int b){
    return a-b;
}
 
struct S
{
  int val;
  int minus(int arg) const noexcept { return val - arg; }
};
 
int main()
{
    auto fifty_minus = std::bind_front(minus, 50);
    std::cout << fifty_minus (3) << '\n';
 
    auto member_minus = std::bind_front(&S::minus, S{50});
 
 
    std::cout << member_minus (3) << '\n';
 
    // 保持 noexcept 说明!
    static_assert(! noexcept(fifty_minus (3)));
    static_assert(noexcept(member_minus (3)));
 
    // 绑定 lambda
    auto plus = [](int a, int b) { return a+b; };
    auto forty_plus = std::bind_front(plus, 40);
    std::cout << forty_plus(7) << '\n';
 
    #ifdef __cpp_lib_bind_back
    auto madd = [](int a, int b, int c) { return a * b + c; };
    auto mul_plus_seven = std::bind_back(madd, 7);
    std::cout << mul_plus_seven(4, 10) << '\n'; // 等价于 `madd(4, 10, 7)`
    #endif
}

输出:

47
47
47
47

参阅

(C++11)
绑定一或多个实参到函数对象
(函数模板)
(C++11)
从成员指针创建出函数对象
(函数模板)