可变参数模板 Variadic Templates

从 C++11 开始,模板可以有任意个模板参数,也即所谓的可变参数模板。

可变参数模板

可变参数模板的例子

定义一个函数 print() 如下,用于接收不同类型的不同参数。

#include <iostream>

void print ()
{
   
}

template<typename T, typename... Types>
void print (T firstArg, Types... args)
{
   
  std::cout << firstArg << '\n'; // print first argument
  print(args...); // call print() for remaining arguments
}

typename... Args 被称为模板参数包(template parameter pack),Args... args 被称为函数参数包(function parameter pack)。模板函数 void print (T firstArg, Types... args) 首先打印第一个参数,然后递归调用自己打印剩余参数。为了结束递归,需要提供一个非模板类型重载函数,用于处理最后的空参数包。

为了更直观地感受可变参数模板地递归处理过程,可以在以上 print 中插入 __PRETTY_FUNCTION__,打印出函数的调用。

#include <iostream>

void print ()
{
   
  std::cout << __PRETTY_FUNCTION__ << "\n";
}

template<typename T, typename... Types>
void print (T firstArg, Types... args)
{
   
  std::cout << firstArg << '\n'; // print first argument
  std::cout << __PRETTY_FUNCTION__ << "\n";
  print(args...); // call print() for remaining arguments
}

当发生 print (7.5, "hello", 5) 调用时,输出如下:

7.5
void print(T, Types ...) [with T = double; Types = {
   const char*, int}]
hello
void print(T, Types ...) [with T = const char*; Types = {
   int}]
5
void print(T, Types ...) [with T = int; Types = {
   }]
void print()

重载可变和非可变参数模板

也可以实现上述例子如下:

#include <iostream>
template<typename T>
void print (T arg)
{
   
  std::cout << arg << '\n'; // print passed argument
}
template<typename T, typename... Types>
void print (T firstArg, Types... args)
{
   
  print(firstArg); // call print() for the first argument
  print(args...);  // call print() for remaining arguments
}

两个 ptint 的区别在于拖尾参数包,没有拖尾参数包的函数会被更优先匹配。

sizeof… 操作符

C++ 引入操作 sizeof... 用于计算可变参数包中元素的个数。

template<typename T, typename... Types>
void print (T firstArg, Types... args)
{
   
  std::cout << sizeof...(Types) << '\n';  // print number of remaining types
  std::cout << sizeof...(args) << '\n';   // print number of remaining args
  ...
}

添加以上两次 sizeof... 的调用,可以打印每次调用 print 时模板参数包和函数参数包元素的个数。

你可能会认为,借助 sizeof... ,可以省去一个空参数的 print

template<typename T, typename... Types>
void print (T firstArg, Types... args)
{
   
  std::cout << firstArg << '\n';
  if (sizeof...(args) > 0) {
    // error if sizeof...(args)==0
    print(args...);          // and no print() for no arguments declared
  }
}

但是,上面的代码无法工作。模板代码的实例是编译期决定的,而实例化的代码是否被执行是运行期决定的。也即 if 语句在编译期会生成,由于没有空参数的 print() 而导致编译失败。

在 C++17 开始支持编译期的 if 语句:

template<typename T, typename... Types>
void print 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值