std::mem_fn
来自cppreference.com
| 在标头 <functional> 定义
|
||
| |
(C++11 起) (C++20 起为 constexpr) |
|
函数模板 std::mem_fn 生成成员指针的包装器对象,它可以存储、复制及调用成员指针。指向对象的引用和指针(包括智能指针)都可以在调用 std::mem_fn 时使用。
参数
| pm | - | 要包装的成员指针 |
返回值
std::mem_fn 返回未指定类型的调用包装器 fn,该类型拥有下列成员:
std::mem_fn 返回类型
成员类型
|
(C++20 前) |
成员函数
(C++20 起为 constexpr) |
||
表达式 fn(args) 等价于 INVOKE(pmd, args),其中 pmd 是 fn 持有的可调用 (Callable) 对象,它具有 M T::* 类型并以 pm 直接非列表初始化。
从而 operator() 的返回类型是 std::result_of<decltype(pm)(Args&&...)>::type,或等价地为 std::invoke_result_t<decltype(pm), Args&&...>,而 noexcept 说明符中的值等于 std::is_nothrow_invocable_v<decltype(pm), Args&&...>)(C++17 起)。
如同用 std::forward<Args>(args)... 完美转发 args 中的每个实参。
示例
用 std::mem_fn 来存储并执行成员函数和成员对象:
运行此代码
#include <functional>
#include <iostream>
#include <memory>
struct Foo
{
void display_greeting()
{
std::cout << "你好。\n";
}
void display_number(int i)
{
std::cout << "数字:" << i << '\n';
}
int add_xy(int x, int y)
{
return data + x + y;
}
template<typename... Args> int add_many(Args... args)
{
return data + (args + ...);
}
auto add_them(auto... args) // 需要 C++20
{
return data + (args + ...);
}
int data = 7;
};
int main()
{
auto f = Foo{};
auto greet = std::mem_fn(&Foo::display_greeting);
greet(f);
auto print_num = std::mem_fn(&Foo::display_number);
print_num(f, 42);
auto access_data = std::mem_fn(&Foo::data);
std::cout << "data:" << access_data(f) << '\n';
auto add_xy = std::mem_fn(&Foo::add_xy);
std::cout << "add_xy:" << add_xy(f, 1, 2) << '\n';
// 用于智能指针
auto u = std::make_unique<Foo>();
std::cout << "access_data(u):" << access_data(u) << '\n';
std::cout << "add_xy(u, 1, 2):" << add_xy(u, 1, 2) << '\n';
// 用于带形参包的成员函数模板
auto add_many = std::mem_fn(&Foo::add_many<short, int, long>);
std::cout << "add_many(u, ...):" << add_many(u, 1, 2, 3) << '\n';
auto add_them = std::mem_fn(&Foo::add_them<short, int, float, double>);
std::cout << "add_them(u, ...):" << add_them(u, 5, 7, 10.0f, 13.0) << '\n';
}
输出:
你好。
数字:42
data:7
add_xy:10
access_data(u):7
add_xy(u, 1, 2):10
add_many(u, ...):13
add_them(u, ...):42
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
|---|---|---|---|
| LWG 2048 | C++11 | 提供了不需要的重载 | 已移除 |
| LWG 2489 | C++11 | 未要求 noexcept
|
要求 |
参阅
(C++11) |
任意可复制构造的可调用对象的可复制包装 (类模板) |
(C++23) |
任意可调用对象的仅移动包装,支持给定调用签名中的限定符 (类模板) |
(C++11) |
绑定一或多个实参到函数对象 (函数模板) |