[C++ Practice Road] New Features of C++11--Part 2

I. Introduction

Long time no see, everyone. Today we will continue to learn the new features of c++11.

2. Wrapper

Let's look at a piece of code first:

#include <iostream>

using namespace std;

class sub
{
    
    
public:
	int operator()(int x, int y)
	{
    
    
		return x - y;
	}
};

int add(int x, int y)
{
    
    
	return x + y;
}

int main()
{
    
    
	//函数指针:		1+2=3
	int(*fp)(int, int);
	fp = add;
	cout << fp(1, 2) << endl;

	//仿函数:			4-2=2
	sub s;
	cout << s(4,2) << endl;

	//lambda表达式:	3*3=9
	auto mul = [](int a, int b) -> int {
    
    
		return a * b;
	};
	cout << mul(3, 3) << endl;

	
	return 0;
}

In this code, I use function pointers, functors, and lambda expressions to represent addition, subtraction, and multiplication operations. We know that there are many ways to express in C++, such as function pointers, functors, and lambda expressions. And using functions, why bother to create a wrapper? The following is my personal understanding:

2.1 The wrapper unifies the interface

If I want to store the above three operations in a map, you will find that there are many difficulties. First of all, the type of function pointer is extremely complicated. Moreover, the three operations are implemented in different ways, which cannot be unified or It is guaranteed that new methods will not be used in the future, and the wrapper can receive function pointers, functors, and lambda expressions at the same time, and the call can be unified.

Reference Code:

#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;

class sub
{
    
    
public:
	int operator()(int x, int y)
	{
    
    
		return x - y;
	}
};

int add(int x, int y)
{
    
    
	return x + y;
}

int main()
{
    
    
	map<string, function<int(int, int)>> opration_map;
	opration_map =
	{
    
    
		{
    
    "+",add},
		{
    
    "-",sub()},
		{
    
    "*",[](int x,int y)->int {
    
    return x * y;} }
	};
	cout << opration_map["+"](2, 2) << endl; //4
	cout << opration_map["-"](2, 2) << endl; //0
	cout << opration_map["*"](2, 2) << endl; //4
}

2.2 Use the idea of ​​packaging to design packaging functions

With the idea of ​​packaging, we can design a wrapper function that can uniformly manage and call functions with inconsistent parameters and different names. Of course, we can also use similar ideas to design corresponding wrapper classes.


#include <iostream>
#include <functional>

void internet_service(string ip,int port) 
{
    
    
    std::cout << "启动网络服务" << std::endl;
    std::cout << "ip为:"  << ip <<std::endl;
    std::cout << "端口号为:" << port <<std::endl;
}

void process_service(int id) {
    
    
    std::cout << "启动进程" << std::endl;
    std::cout << "进程id:" << id <<std::endl;
}

// 统一接口的包装器函数
template<typename Func, typename... Args>
void execute(Func func, Args... args) 
{
    
    
    cout << "正在统一记录日志" << endl;
    func(args...); // 调用原始函数
    cout << "正在进行统一清理工作" << endl;
}

int main() 
{
    
    
    // 统一调用不同类型的函数
    execute(internet_service, "127.0.0.1",8080); 
    execute(process_service,114514);

    return 0;
}

Three, binding (bind)

3.1 Adjust the order of parameters

Use bind to adjust the parameter order of the function, examples are as follows:

void Print(int x,int y)
{
    
    
	cout << "第一个参数:" << x << endl;
	cout << "第二个参数:" << y << endl;
}

int main()
{
    
    
	bind(Print, placeholders::_1, placeholders::_2)(1, 2);
	bind(Print, placeholders::_2, placeholders::_1)(1, 2);

	return 0;
}

3.2 Adjust the number of parameters

We know that the function in the class will take a parameter by default: this pointer, which will bring a lot of trouble to our wrapper, because we have to solve the problem of type inconsistency, and it happens that bind can help us solve this problem:

class sub
{
    
    
public:
	int func(int x, int y)
	{
    
    
		return x - y;
	}
};

int main()
{
    
    
	sub s;
	function<int(sub,int, int)> fsub1 = &sub::func;
	function<int(int, int)> fsub2 = bind(&sub::func, sub(), placeholders::_1, placeholders::_2);
	function<int(int, int)> fsub3 = bind(&sub::func, &s, placeholders::_1, placeholders::_2);

	cout << fsub1(sub(), 2, 1) << endl;
	cout << fsub2(2, 1) << endl;
	cout << fsub3(2, 1) << endl;
	return 0;
}

You can see that bind writes the first parameter to death to reduce the number of parameters that we actually need to pass. You can see that using bind, whether it is an anonymous object or an instance pointer, can be successfully bound, but the first one we are calling Sometimes only objects of the class can be passed, so the second method is recommended.

Four. Conclusion

At this point, the relevant explanations about the new features of c++11 have come to an end. The interval between the two articles is long, mainly because the course design is done in the middle, but fortunately, the course design scored 95 points, which is not a waste of time , we will continue to update the relevant knowledge of c++, Linux and MySQL, and see you in the next issue!

Guess you like

Origin blog.csdn.net/m0_73209194/article/details/131038799