🥬可变参数模板
2022-6-15
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
可变参数模板(variadic template)是新加的一种函数模板或类模板,这种模板可以接收可变数量的模板参数。这种可变参数被称为参数包(parameter pack)。语言允许两种参数包:模板参数包(template parameter pack)表示 0 或多个模板参数,以及函数参数包(function parameter pack)表示 0 个或多个函数参数。
 
语言使用省略号(ellipsis)来表示模板或函数参数包。对于模板参数列表,class... 或 typename... 表示接下的参数表示一系列 0 个或多个类型;省略号后的名字表示其参数包的任何类型的名字。在函数参数列表中,如果一个参数的类型是一个模板参数包,那么它就是一个函数参数包。如:
将 foo 声明为一个可变函数,其中一个类型参数是 T,以及一个模板参数包是 Args,这个参数包表示 0 个或多个额外的类型参数。函数参数列表则有一个参数,其类型是 const T&,以及一个函数参数包 rest,这个参数包表示 0 个或多个函数参数。
与之前一样,编译器从函数实参中推断模板参数类型。对于可变模板,编译器还会推断参数包中的数量,如:
编译器将会实例化 4 个不同的 foo 实例:
 
sizeof... 操作符
当希望知道参数包中有多少个元素时,可以用sizeof...操作符,与sizeof一样,其返回一个常量表达式并且不会对其实参进行求值:
 

写可变参数函数模板

在前面用过 initializer_list 来定义函数可以接收不定数目的实参,但是这种实参必须是相同的类型,或者类型可以转为相同的类型。不定参数函数被用于及不知道实参的数目也不知道实参的类型。
不定参数函数将总是递归的,第一个调用处理包中的第一个实参,并以后面的实参调用其自身:
参数包可以是一个空包。
 

包扩展(Pack Expansion)

除了获取包的大小,另外一件可以做的事是对参数进行展开。当展开包时,可以提供一个模式(pattern)给它使用在每个展开的元素上。展开一个包将使得所有元素称为连续的逗号分隔的列表,并且将模式运用于每个元素上。使用省略号来进行包扩展。如 print 函数就有两个扩展。
第一个扩展将模板参数包进行扩展并产生了 print 的函数参数列表,第二个扩展发生在函数体内调用 print 处,这次将产生一个调用 print 的函数实参列表。
Args 的扩展运用 const Args& 模式给每个 Args 模板参数包中的元素,扩展的结果是一个逗号分隔的 0 个或多个参数类型,每个的类型都是 const T & 。
 
 
函数参数包扩展可以运用更为复杂的模式,如:
此调用 print 将运用模式 debug_rep(rest) ,将对函数参数包 rest 的每个元素调用 debug_rep 扩展的结果将是逗号分隔的一列 debug_rep 函数调用。
 

转发参数包(Forwarding Parameter Packs)

在新标准下,可以将 forward 与可变参数模板一起使用从而让函数在不改变其实参的任何类型信息的情况下转发给其它函数:
其中 std::forwad<Args>(args)... 将同时扩展模板参数包 Args 和函数参数包 args 。如:svec.emplace_back(10, 'c') 将被扩展为 std::forward<int>(10), std::forward<char>(c)
实践中绝大多数的可变参数参数都将其参数转发给其它函数,就如 emplace_back 函数一样。
 
 
 
  • C++
  • 重载与模板模板特例化
    目录