std::bind_front, std::bind_back
在标头 <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_front
和 bind_back
为 f
生成转发调用包装。调用此包装等价于绑定(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 则程序为非良构:
- std::is_constructible_v<std::decay_t<F>, F>
- std::is_move_constructible_v<std::decay_t<F>>
- (std::is_constructible_v<std::decay_t<Args>, Args> && ...)
- (std::is_move_constructible_v<std::decay_t<Args>> && ...)
参数
f | - | 将绑定某些参数到的可调用 (Callable) 对象(函数对象、指向函数指针、到函数的引用、指向成员函数指针或指向数据成员指针) |
args | - | 参数列表,绑定(1)首,或者(2)尾, sizeof...(Args) 个参数到 f
|
类型要求 | ||
-std::decay_t<F> 与 std::decay_t<Args>... 中的每个类型 必须符合可移动构造 (MoveConstructible) 的要求。
|
返回值
未指定的 T
类型函数对象,除了二次以相同参数调用 std::bind_front
或 std::bind_back
返回的类型相同。
返回的对象(调用包装)有下列属性:
部分绑定 返回类型
令 部分绑定
表示 std::bind_front
或 std::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_ptr 与 std::unique_ptr )。
复制或移动给 std::bind_front
或 std::bind_back
的参数,而决不按引用传递,除非用 std::ref 或 std::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) |
从成员指针创建出函数对象 (函数模板) |