变参模板1:入门

题目描述

变参模板是指模板参数不定长的模板。它是 C++ 元编程的重要组成部分,也是许多现代 C++ 标准库设施的构成成分。

在模板形参列表中,可以用 typename... Ts 引入模板形参包 Ts。也就是说,给普通的模板形参的声明前,加上 ...,就可以让这个形参变成“形参包”。“形参包”顾名思义就是任意多个模板形参的集合。

template <typename... Ts>
struct S {};
 
S<> s1; // OK
S<int> s2; // OK
S<int, bool> s3; // OK
S<char, bool, double, long, unsigned> s4; // OK

像这样,模板 S 通过引入形参包 Ts,就能接收任意多个模板实参。

那如何使用模板形参包呢?我们先通过函数形参包这种用法来使用。对于函数变参模板,可以将最后一个函数形参声明为如下形式:

template <typename... Ts>
void f(int a, Ts... args);

这里的 args 就是函数形参包,写成“模板形参包名 + ... + 形参名”。它的含义是:对于模板形参包中的每一个类型,都引入一个形参到函数声明。由于模板形参包的类型个数是任意的,从而这个函数模板 f 也可以接受任意多个实参。(注意第一个参数不是变参,它固定地声明为 int;剩余的部分是可变的。此外,函数形参包只能出现一次,而且是形参列表的结尾。)

f(0);                        // 调用 f<>
f(0, 42);                    // 调用 f<int>
f(0, '@', false, 3.14, 42L); // 调用 f<char, bool, double, long>

进一步,如何使用函数形参包呢?目前我们可以先了解一下 sizeof... 运算符,它返回形参包中的类型/形参个数。比如 sizeof...(args) 在上面三个例子中,分别得到 0、1 和 4。

下面请补充代码,实现 count 函数模板;它输出传入了多少个实参。

关于输入

关于输出

见样例输出

参考答案

#include <iostream>

template <typename... Args>
void count(const Args&... args) {
    std::cout << sizeof...(args) << std::endl;
}

int main() {
    count();
    count(false);
    count("hello", "world");
    count("do not", "dereference", nullptr);
    count(1, '+', 1LL, "=", 2.0);
}