在有了参数模板的基础后让咱们一同看一下可变参数模板究竟是什么?他怎么运用?

一、界说

可变参数模板是指一个参数数量不确定模板函数模板类,能够承受恣意数量恣意类型的参数,并对它们进行处理。

二、运用方法

在C++11中,引入了可变参数模板的概念,运用“…”表示参数包。可变参数模板有两种运用方法:函数模板和类模板。

2.1 函数模板

下面以函数模板为例,详细说明可变参数模板的运用。

事例一

界说一个可变参数模板函数:

template<typename T, typename... Args>
void print(T t, Args... args) {
    std::cout << t << std::endl;
    print(args...);
}

该函数的作用是,传入恣意数量的参数,并逐一打印出来。这里运用了递归调用的方法,每次打印出第一个参数后,将剩下参数经过参数包打开的方法递归调用print函数。其间第二个参数就是一个可变参数。

调用该函数的示例代码:

print("Hello", "world", "!");
print(1, 2, 3, 4, 5);

输出成果为:

Hello
world
!
1
2
3
4
5

在调用函数时,不需求指定参数数量,能够传入恣意数量的参数,这些参数会被打包进一个参数包中,经过参数包打开的方法进行处理。

需求留意的是,在可变参数模板中,必须至少有一个参数,否则将导致编译错误。此外,需求留意参数包打开的方法和递归调用的方法,以防止出现无限递归的状况。

事例二

更直观一点

#include <iostream>
#include <string>
template<typename... Args>
void print(Args... args)
{
    ((std::cout << args), ...);
}
int main()
{
    print(1, 2, "Hello", 'c', 3.14);
    return 0;
}
  • Args 是一个可变参数模板的名字,表示一个typename类型参数包。
  • args 是一个变量,表示一个函数参数包,它包含了所有的函数实参,它的类型就是 Args,这里是一个类型参数包打开成的详细类型。
  • 这个函数承受恣意数量和类型的参数,然后将它们打印到操控台上。
  • 咱们能够用逗号表达式折叠表达式来打开参数包并进行操作。在上面的比如中,咱们首要运用逗号表达式将所有参数打印到操控台上,然后运用折叠表达式将参数包打开并传递给逗号表达式。

这里先弥补说一下逗号表达式折叠表达式

2.1.1 逗号表达式

逗号表达式是一种运算符,运用逗号离隔的多个表达式被顺序求值,整个逗号表达式的值是最后一个表达式的值。

int a = 10, b = 20, c = 30;
int result = (a++, b++, c++); // 逗号表达式,返回c的值

上述代码中,逗号表达式的作用是依次执行a++,b++,c++三个操作,然后返回c的值,即30。

2.1.2 折叠表达式

折叠表达式是C++17引入的一种表达式,用于简化运用可变参数模板时的代码。在运用折叠表达式时,需求编译器支持C++17标准。折叠表达式运用一种特别的语法,将参数包打开并进行运算。折叠表达式语法如下:

( pack op ... )
( ... op pack )
( init op ... op pack )
( pack op ... op init )

详细内容可参看C++17语法之折叠表达式

2.2 类模板

当咱们需求界说一个承受恣意数量、恣意类型参数的类时,能够运用可变参数模板。

类模板中的可变参数模板语法与函数模板中的相似,只是在类名前面运用<typename...><class...>来界说可变参数,如下所示:

template <typename... Args>
class MyList {
   public:
    void addElement(Args... args) {
        // 完成增加元素的代码
    }
};

上述代码中,MyList 是一个类模板,运用了可变参数模板。addElement函数承受恣意数量、恣意类型的参数,能够用来增加元素。

运用这个类模板的示例代码如下:

MyList<int, float, double> myList;
myList.addElement(1);
myList.addElement(2.3f);
myList.addElement(4.5, 6.7, 8.9);

在这个示例中,咱们运用MyList类模板创建了一个myList目标,并运用addElement函数增加了不同类型和数量的元素。

需求留意的是,在模板类中运用可变参数模板时,类的成员函数也必须运用可变参数模板,以便正确处理不同数量和类型的参数。