命名空间
变体
操作

std::mem_fn

来自 cppreference.com
< cpp‎ | utility‎ | functional
 
 
工具库
语言支持
类型支持 (基本类型,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++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 M, class T >
/* unspecified */ mem_fn( M T::* pm ) noexcept;
(自 C++11 起)
(自 C++20 起为 constexpr)

函数模板 std::mem_fn 为成员指针生成包装器对象,这些包装器对象可以存储、复制和调用 成员指针。调用 std::mem_fn 时,可以使用对象的引用和指针(包括智能指针)。

内容

[编辑] 参数

pm - 将被包装的成员指针

[编辑] 返回值

std::mem_fn 返回一个调用包装器 fn,其类型未指定,具有以下成员

std::mem_fn 返回类型

成员类型

类型 定义
result_type(在 C++17 中已弃用) 如果 pm 是成员函数指针,则为 pm 的返回类型,对于成员对象指针则未定义
argument_type(在 C++17 中已弃用) 如果 pm 是不带参数的成员函数指针,则为 T*,可能是 cv 限定的
first_argument_type(在 C++17 中已弃用) 如果 pm 是带一个参数的成员函数指针,则为 T*
second_argument_type(在 C++17 中已弃用) 如果 pm 是带一个类型为 T1 的参数的成员函数指针,则为 T1
(直到 C++20)

成员函数

template< class... Args >

/* see below */ operator()(Args&&... args) /* cvref-qualifiers */

    noexcept(/* see below */);
(自 C++20 起为 constexpr)

表达式 fn(args) 等效于 INVOKE(pmd, args),其中 pmdfn 所持有的 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 起).

中的每个参数 args 都被完美转发,就像使用 std::forward<Args>(args)... 一样。

[编辑] 示例

使用 std::mem_fn 存储并执行成员函数和成员对象

#include <functional>
#include <iostream>
#include <memory>
 
struct Foo
{
    void display_greeting()
    {
        std::cout << "Hello, world.\n";
    }
 
    void display_number(int i)
    {
        std::cout << "number: " << 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 required
    {
        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';
}

输出

Hello, world.
number: 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++ 标准。

DR 应用于 发布的行为 正确行为
LWG 2048 C++11 提供了不必要的重载 已移除
LWG 2489 C++11 noexcept 不需要 需要

[编辑] 另请参阅

(C++11)
任何可复制的可调用对象的复制包装器
(类模板) [编辑]
任何在给定调用签名中支持限定符的可调用对象的移动包装器
(类模板) [编辑]
(C++11)
将一个或多个参数绑定到函数对象
(函数模板) [编辑]