std::mem_fn

头文件

#include <functional>

函数原型

template< class M, class T > (C++11)
/*unspecified*/ mem_fn(M T::* pm) noexcept; (C++20)

template< class M, class T >
constexpr /*unspecified*/ mem_fn(M T::* pm) noexcept; (C++20)

函数模板 std::mem_fn 生成指向成员指针的包装对象,它可以存储、复制及调用指向成员指针。到对象的引用和指针(含智能指针)可在调用 std::mem_fn 时使用。

参数

pm 指向被包装成员的指针

返回值

std::mem_fn 返回未指定类型的调用包装,该类型拥有下列成员:

若 pm 为指向成员函数的指针,则为 pm 的返回类型,对指向成员对象的指针不定义。

若 pm 是指向无参数成员函数的指针则为 T* ,可有 cv 限定

若 pm 是指向接收一个参数的成员函数的指针则为 T*

若 pm 是指向接收一个 T1 类型参数的成员函数的指针则为 T1

用法

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

输出结果

Hello, world.
number: 42
data: 7

thread和mem_fn的使用

当需要利用类成员函数( MyClass::thread_func )来创建子线程时

#include <iostream>
#include <thread>
 
void fun()
{
    
    
	std::cout << "hello world" << std::endl;
}
 
class cls
{
    
    
public:
	void funcls()
	{
    
    
		std::cout << "cls hello" << std::endl;
	}
};
int main()
{
    
    
	cls m_cls;
	//std::thread t(fun);
	std::thread t(std::mem_fn(&cls::funcls), &m_cls);// 类成员函数需用mem_fn
	if(t.joinable())
		t.join();
	return 0;
}

for_each与mem_fn

#include <functional>
#include <iostream>
#include <algorithm>
#include <vector>

class Age
{
    
    
public:
	Age(int v) : m_age(v)
	{
    
    }

	bool compare(const Age& t) const
	{
    
    
		return m_age < t.m_age;
	}

	void print() const
	{
    
    
		std::cout << m_age << ' ';
	}

	int m_age;
};

bool compare(const Age& t1, const Age& t2)
{
    
    
	return t1.compare(t2);
}

int main(int argc, char* argv[])
{
    
    
	// 以前写法
	{
    
    
		std::vector<Age> ages{
    
     1, 7, 19, 27, 39, 16, 13, 18 };
		std::sort(ages.begin(), ages.end(), [&](const Age& objA, const Age& objB) {
    
    
			return compare(objA, objB);
			});
		for (auto item : ages)
		{
    
    
			item.print();
		}
		std::cout << std::endl;
	}
	// 利用std::mem_fn写法
	{
    
    
		std::vector<Age> ages{
    
     100, 70, 290, 170, 390, 160, 300, 180 };
		std::sort(ages.begin(), ages.end(), std::mem_fn(&Age::compare));
		std::for_each(ages.begin(), ages.end(), std::mem_fn(&Age::print));
		std::cout << std::endl;
	}

	return 0;
}

/* run output:
1 7 13 16 18 19 27 39
70 100 160 170 180 290 300 390
*/

使用场景

不支持的场景
1)不支持全局函数
2)不支持类protected访问权限的成员(函数或数据)
3)不支持类private访问权限的成员(函数或数据)
支持的场景
1)传入类对象
2)传入引用对象
3)传入右值
4)传入对象指针
5)传入智能指针std::shared_ptr
6)传入智能指针std::unique_ptr
7)传入派生类对象
8)带参数的成员函数

#include <functional>
#include <iostream>
 
int Add(int a, int b)
{
    
    
    return a + b;
}
 
class Age
{
    
    
public:
    Age(int default = 12) : m_age(default)
    {
    
    }
 
    bool compare(const Age& t) const
    {
    
    
        return m_age < t.m_age;
    }
 
    void print() const
    {
    
    
        std::cout << m_age << ' ';
    }
 
    int m_age;
 
protected:
    void add(int n)
    {
    
    
        m_age += n;
    }
 
private:
    void sub(int m)
    {
    
    
        m_age -= m;
    }
};
 
class DerivedAge : public Age
{
    
    
public:
    DerivedAge(int default = 22) : Age(default)
    {
    
    }
};
 
int main(int argc, char* argv[])
{
    
    
    // 0.不支持的示例
    {
    
    
        // 1.不支持全局函数
        // auto globalFunc = std::mem_fn(Add); // ERROR: 语法无法通过
        // 2.不支持类protected访问权限的函数
        // auto addFunc = std::mem_fn(&Age::add); // ERROR: 语法无法通过
        // 3.不支持类private访问权限的函数
        // auto subFunc = std::mem_fn(&Age::sub); // ERROR: 语法无法通过
    }
    // 1.成员函数示例
    {
    
    
        auto memFunc = std::mem_fn(&Age::print);
 
        // 方式一:传入类对象
        Age obja{
    
     18 };
        memFunc(obja);
 
        Age& refObj = obja;
        refObj.m_age = 28;
        // 方式二:传入引用对象
        memFunc(refObj);
 
        // 方式三:传入右值
        Age objb{
    
     38 };
        memFunc(std::move(objb));
 
        // 方式四:传入对象指针
        Age objc{
    
     48 };
        memFunc(&objc);
 
        // 方式五:传入智能指针std::shared_ptr
        std::shared_ptr<Age> pAge1 = std::make_shared<Age>(58);
        memFunc(pAge1);
 
        // 方式六:传入智能指针std::unique_ptr
        std::unique_ptr<Age> pAge2 = std::make_unique<Age>(68);
        memFunc(pAge2);
 
        // 方式七:传入派生类对象
        DerivedAge aged{
    
     78 };
        memFunc(aged);
        
        // 方式八:带参数成员函数
        auto memFuncWithParams = std::mem_fn(&Age::compare);
        std::cout << memFuncWithParams(Age{
    
     25 }, Age{
    
     35 }) << std::endl;
    }
 
    std::cout << std::endl;
 
    // 2.成员变量示例
    {
    
    
        auto memData = std::mem_fn(&Age::m_age);
 
        // 方式一:传入类对象
        Age obja{
    
     19 };
        std::cout << memData(obja) << ' ';
 
        Age& refObj = obja;
        refObj.m_age = 29;
        // 方式二:传入引用对象
        std::cout << memData(refObj) << ' ';
 
        // 方式三:传入右值
        Age objb{
    
     39 };
        std::cout << memData(std::move(objb)) << ' ';
 
        // 方式四:传入对象指针
        Age objc{
    
     49 };
        std::cout << memData(&objc) << ' ';
 
        // 方式五:传入智能指针std::shared_ptr
        std::shared_ptr<Age> pAge1 = std::make_shared<Age>(59);
        std::cout << memData(pAge1) << ' ';
 
        // 方式六:传入智能指针std::unique_ptr
        std::unique_ptr<Age> pAge2 = std::make_unique<Age>(69);
        std::cout << memData(pAge2) << ' ';
 
        // 方式七:传入派生类对象
        DerivedAge aged{
    
     79 };
        std::cout << memData(aged) << ' ';
    }
 
    return 0;
}
 
/* run output:
18 28 38 48 58 68 78 1
19 29 39 49 59 69 79
*/

猜你喜欢

转载自blog.csdn.net/qq_36314864/article/details/132086368
std