目录
1.可变参数模版
1.1.基本概念
可变参数模板是C++11引入的一种特性,它允许函数或类模板接受任意数量的参数。通过使用可变参数模板,我们可以编写更加灵活和通用的代码。可变参数模板使用...表示参数的可变性。我们可以在函数模板或类模板中使用可变参数模板。
我们在命令行参数的学习中,知道参数是通过argv这个指针数组获取的,而对于可变参数模版它的参数是通过函数形参参数包中获取的。而Args对应着很多类型,我们在进行args访问时,会进入对应的...中不断“递归”查找到参数,并进行操作。
解析获取参数数目:
// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{
// sizeof...(args)这个是固定的语法
cout << sizeof...(args) << endl;
}
int main()
{
ShowList(1);
ShowList(1, 2);
ShowList(1, 2, 3);
ShowList(1, 2.2, 'x', 3.3);
return 0;
}
接下来我们来看一下另一个场景:
解析获取参数值
// 当参数列表指向空时,这时进入该重载函数,且当前ShowList函数结束
void _ShowList()
{
cout << endl;
}
// 编译时的递归推演
// 第一个模板参数依次解析获取参数值
template <class T, class ...Args>
void _ShowList(const T& val, Args... args)
{
cout << typeid(val).name() << "-> "<<val<<" ";
_ShowList(args...);
}
template <class ...Args>
void ShowList(Args... args)
{
_ShowList(args...);
}
int main()
{
ShowList(1);
ShowList(1, 2);
ShowList(1, 2, 3);
ShowList(1, 2.2, 'x', 3.3);
return 0;
}
对于这两个场景,我们主要着重于第二部分:
- 对于main函数块中,我们传入的可变参数分别为0,1,2,3,4,这些参数可以等价于Args... args这个对象
- 当我们递归在空数据之前时,我们进入的是进行递归推演,以1,2为例,我们就会进入void _ShowList(const T& val, Args... args)中
- 当数据访问完成时,我们进入void _ShowList(),然后访问到空数据退出当前的语句ShowList(1, 2);然后进入到下一个语句
- 并且这里也能体现可变参数模版的可变性,我们在外部传给_ShowList(args...)的是args...而接收方void _ShowList(const T& val, Args... args),并且可以访问到我们在外部的参数值,不过需要我们在定义一个模版参数来进行解析
这个场景也可以这样子解析参数包!
template <class T>
int PrintArg(T&& t)
{
cout << t << " ";
return 0;
}
//展开函数
template <class ...Args>
void showList(Args&&... args)
{
// 要初始化arr,强行让解析参数包,参数包有一个参数,PrintArg就依次推演生成几个
int arr[] = { PrintArg(args)... };
cout << endl;
}
int main()
{
showList(1);
showList(1, 'a');
showList(1, 'a', std::string("sort"));
return 0;
}
- 外部传入showList的参数有若干个,通过万能引用进入PrintArg
- 以1,'a' 为例,1进去然后打印加载到arr中,'a'也是如此
- 当编译器访问到了空(这里可能应该是编译器通过传入参数数量来判断)然后退出该次解析进而实现解析参数包
1.2.参数包的实际应用
1.2.1.emplace函数的引入
在C++编程中,emplace是C++11中引入的一种用于插入元素到容器中的方法。它可以