std::mem_fn

来自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)
mem_fn
(C++11)
部分函数应用
(C++11)
(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 M, class T >
/* 未指定 */ mem_fn(M T::* pm) noexcept;
(C++11 起)
(C++20 前)
template< class M, class T >
constexpr /* 未指定 */ mem_fn(M T::* pm) noexcept;
(C++20 起)

函数模板 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>

/* 见下文 */ operator()(Args&&... args) /* cv引用限定符 */

    noexcept(/* 见下文 */);
(C++20 前)
template<class... Args>

constexpr /* 见下文 */ operator()(Args&&... args) /* cv引用限定符 */

    noexcept(/* 见下文 */);
(C++20 起)

表达式 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 起)

如同用 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)
    {
        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++11)
绑定一或多个实参到函数对象
(函数模板)