C++ 折叠参数包详解(悄然增强编程效率)

 更新时间:2023年05月22日 15:33:53   作者:热爱编程的小K  
折叠参数就是一个参数包, 代表是多个未知,tuple元组就是一个折叠参数的使用,这篇文章主要介绍了C++ 折叠参数包悄然增强编程效率,需要的朋友可以参考下

前言

本节将为大家带来折叠参数包的详细讲解,折叠参数包为C++模板编程提供了更加灵活和强大的工具,可以提高代码的简洁性和可读性,看完后希望对你有收获

一、介绍

折叠参数就是一个参数包, 代表是多个未知,tuple元组就是一个折叠参数的使用

折叠参数类型:

  • typename ...Args: Args参数包的包名 ,本质是声明一个Args折叠参数类型
  • Args ...arg: 折叠参数包类型的变量
  • ...:理解为多个意思

二、函数模板中使用折叠参数

1、递归方式展开

递归方式的展开是比较好理解的,每一次调用第二个print函数就打印一次data,然后又调用自己,这时候参数包也剥离了一个参数,也就是调用自己会打印下一个data

有的同学看了下面的代码可能会疑惑,为什么会有两个函数,这是因为上面的函数为终止函数,也就是当第二个函数参数包中只有一个参数时调用第一个函数

template <typename _Ty>
void print(_Ty data) 
{
	cout << data << endl;
}
template <typename _Ty,typename ...Args>
void print(_Ty data, Args ...args) 
{
	cout << data << "\t";
	print(args...);
}

2、列表数据展开

这个的难点和重点在于initializer_list<int>{(printData(args), 0)...};,这一行代码用到了列表和逗号表达式的特性,不用说列表的每个值最后都被初始化为0,但是列表的每个值被初始化为0的时候,他们会先执行printData(args(n)),也就是会不断打印,参数包不断展开

template <typename _Ty>
void printData(_Ty data) {
	cout << data << "\t";
}
template <typename ...Args>
void printArgs(Args ...args)
{
	initializer_list<int>{(printData(args), 0)...};
	cout << endl;
}

3、完美转发的方式展开

完美转发一般是用来统一接口,也就是有许多函数,他们的参数数量、类型不同,我们把他们统一为只用函数名就可以调用该函数,且不减少其原功能

这里我们用仿函数接收一下用bind绑定的函数以及参数包,注意这里函数和参数包绑定的时候都用了完美转发

什么是完美转发呐?forword是为了解决在函数模板中,使用右值引用参数(T&&),传递右值进去以后,类型会变为左值的问题。当传入的参数是一个对象时,右值变左值就会出问题,因为左值调用拷贝构造,右值调用移动构造。本来可以用移动构造提高效率,却因为右值变成左值,调用了拷贝构造。所以我们要把它变回去!实参传的是右值,进入函数体还是右值,这就是完美转发

class Test 
{
public:
	void printk() 
	{
		if (func) func();
	}
	template <typename Func,typename ...Args>
	void connect(Func&& f, Args&& ...args)    //右值引用
	{
		func = bind(forward<Func>(f), forward<Args>(args)...);
	}
protected:
	function<void()> func;
};
void sum(int a, int b) 
{
	cout<< a + b;
}
int main() 
{
	Test test;
	test.connect(sum, 1, 2);
	test.printk();
	test.connect([](int a, int b) {cout << endl << a + b; }, 3, 8);
	test.printk();
	return 0;
}

上面的例子中通过connect绑定函数和参数包,实现统一接口的功能,通过printK函数调用

三、类模板中使用折叠参数

1、继承+模板特化的方式展开

类中实现折叠参数,前两个类是必须,对应上面的终止函数,继承的时候要写清楚public Test<Args...>,还有就是第三个类必须要一个无参构造函数,且带参数包的的构造函数初始化时要调用子类的构造函数,还有就是打印的时候要一层一层的,采用继承+模板特化就是一代一代的

template <typename ...Args>
class Test;
template<>
class Test<> {};
template <typename _Ty, typename ...Args>
class Test<_Ty, Args...> :public Test<Args...>
{
public:
	Test() {}
	Test(_Ty data, Args ...args) :data(data), Test<Args...>(args...) {}
	Test<Args...>& getObject() { return *this; }
	_Ty& getData() { return data; }
protected:
	_Ty data;
};
void testOne() 
{
	Test<string, int, double> test("fsdjf", 32, 3.23);
	cout << test.getData() << "\t" << test.getObject().getData() << "\t" << test.getObject().getObject().getData() << endl;
}

2、递归的方式展开

递归这一种就是把自己当对象调用,其它的和上面相同

template <typename ...Args>
class my_tuple;
template<>
class my_tuple<> {};
template <typename _Ty, typename ...Args>
class my_tuple<_Ty, Args...>
{
public:
	my_tuple() {}
	my_tuple(_Ty data, Args ...args) :data(data),args(args...) {}
	_Ty& getData() { return data; }
	my_tuple<Args...>& getObject() { return *this; }
protected:
	_Ty data;
	my_tuple<Args...> args;
};
void testTwo() 
{
	Test<string, int, double> test("fsdjf", 32, 3.23);
	cout << test.getData() << "\t" << test.getObject().getData() << "\t" << test.getObject().getObject().getData() << endl;
}

到此这篇关于C++ 折叠参数包悄然增强编程效率的文章就介绍到这了,更多相关C++ 折叠参数包内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • opencv3/C++ FLANN特征匹配方式

    opencv3/C++ FLANN特征匹配方式

    今天小编就为大家分享一篇opencv3/C++ FLANN特征匹配方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • C++ 构造函数和析构函数示例详解

    C++ 构造函数和析构函数示例详解

    本文详细介绍了C++中的构造函数和析构函数,包括它们的特点、调用时机以及在资源管理中的重要性,同时,通过与Python的对比,展示了如何在Python中模拟C++的构造函数特性,并强调了两种语言在内存管理和资源管理机制上的差异,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • C语言实现C++继承和多态的代码分享

    C语言实现C++继承和多态的代码分享

    本文主要给大家简单讲诉了C和C++的区别以及如何使用C语言模拟实现C++继承和多态,并附上示例代码,是篇相当不错的文章,推荐给喜欢C语言的小伙伴们
    2017-07-07
  • 一盘王者的时间用C语言实现三子棋

    一盘王者的时间用C语言实现三子棋

    相信我们都玩过三子棋,规则很简单,但想用c语言做出这个游戏,事实上也是比较简单的,下面通过c语言进行对五子棋的分析
    2022-02-02
  • 全局变量与局部变量在内存中的区别详细解析

    全局变量与局部变量在内存中的区别详细解析

    以下是对全局变量与局部变量在内存中的区别进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • C和C++中的基本数据类型的大小及表示范围详解

    C和C++中的基本数据类型的大小及表示范围详解

    这篇文章主要介绍了C和C++中的基本数据类型的大小及表示范围详解,基本数据类型有int、long、long long、float、double、char、string,正文有详细介绍,欢迎参考
    2018-01-01
  • 常用的C语言排序算法(两种)

    常用的C语言排序算法(两种)

    本文给大家分享两种常用的C语言排序算法,代码非常简单,感兴趣的朋友可以参考下
    2016-09-09
  • C++实现简单计算器

    C++实现简单计算器

    这篇文章主要为大家详细介绍了C++实现简单计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • 详解C语言之单链表

    详解C语言之单链表

    这篇文章主要为大家介绍了C语言的单链表,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • Visual Studio 2022最新版安装教程(图文详解)

    Visual Studio 2022最新版安装教程(图文详解)

    本文主要介绍了Visual Studio 2022最新版安装教程,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01

最新评论