c++可变参数模板

可变参数模板

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。

template <class ...Args>
void ShowList(Args... args)
{}

​ 上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的, 只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特 点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变 参数,所以我们的用一些奇招来一一获取参数包的值。

使用递归方式展开参数包

//递归终止函数

template <class T>
void ShowList(const T& t)
{
 cout << t << endl;
}

// 展开函数
template <class T, class ...Args>
void ShowList(T value, Args... args)
{
 cout << value << " ";
 ShowList(args...);
}

int main()
{
 ShowList(1);
 ShowList(1, 'A');
 ShowList(1, 'A', std::string("sort"));
 return 0;
}

  • 这种递归的展开方式就是使用value来获取第一个参数,然后用args存储剩余的参数,如果最后的参数为1就会调用那一个参数的结束递归

逗号表达式展开参数包

​ 这种展开参数包的方式,不需要通过递归终止函数,是直接在expand函数体中展开的, printarg

不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式 实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式。

expand函数中的逗号表达式:(printarg(args), 0),也是按照这个执行顺序,先执行

printarg(args),再得到逗号表达式的结果0。同时还用到了C++11的另外一个特性——初始化列 表,通过初始化列表来初始化一个变长数组, {(printarg(args), 0)…}将会展开成((printarg(arg1),0), (printarg(arg2),0), (printarg(arg3),0), etc… ),最终会创建一个元素值都为0的数组int arr[sizeof…(Args)]。由于是逗号表达式,在创建数组的过程中会先执行逗号表达式前面的部分printarg(args)

打印出参数,也就是说在构造int数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在 数组构造的过程展开参数包

template <class T>

void PrintArg(T t)
{
 cout << t << " ";
}

//展开函数

template <class ...Args>

void ShowList(Args... args)
{
 int arr[] = { (PrintArg(args), 0)... };
 cout << endl;
}

int main()
{
 ShowList(1);
 ShowList(1, 'A');
 ShowList(1, 'A', std::string("sort"));
 return 0;
}

emplace系列接口

  • 下面是一个emplace系列的接口,支持模板的可变参数,并且万能引用,这里高效的地方可以直接使用可变参数进行构造而减少了拷贝构造或者移动构造,可以在一定程度上提高效率
template <class... Args>
void emplace_back (Args&&... args);
int main()
{
 std::list< std::pair<int, char> > mylist;
    
 // emplace_back支持可变参数,拿到构建pair对象的参数后自己去创建对象
 // 那么在这里我们可以看到除了用法上,和push_back没什么太大的区别
  
 //在这里直接使用可变参数构造对象
 mylist.emplace_back(10, 'a');
 mylist.emplace_back(20, 'b');
 mylist.emplace_back(make_pair(30, 'c'));
 mylist.push_back(make_pair(40, 'd'));
 mylist.push_back({ 50, 'e' });
 
 for (auto e : mylist)
 cout << e.first << ":" << e.second << endl;
 return 0;
}
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值