Variadic Templates

C++11 – Variadic Template Function

Variadic模版允许函数采用任意类型的可变数量参数,考虑这样的一个例子,假设我们创建一个函数log(),它接受任意类型的可变数量参数,并在控制台上打印。

1
2
3
4
5
6
7
8
log(1,4.3, "Hello");

log('a', "test", 78L, 5);

class Student;
Student obj;

log(3, obj);

对于可变类型的参数,我们一般考虑的是创建模版函数,如:

1
2
3
4
5
template<typename T>
void log(T obj)
{
std::cout<<obj;
}

但以上做法只能接受一个参数。

Vardiac Template Function: Creating function that accepts variable number of arguments of ant type

使用vardiac template,我们可以定义这样的一个函数,接收不定数量的参数:

1
2
template<typename T, typename ... Args>
void log(T first, Args ... args);

上述函数可以接收多个参数,**Args…代表了模版参数的可变数目。

声明一个vardiac template函数是容易的,但其内部具体定义会有点tricky。由于我们无法直接访问到被传递进去的可变数目的参数。我们需要使用c++的类型推导机制和递归来实现。

1
2
3
4
5
6
7
8
9
template<typename T, typename ... Args>
void log(T first, Args ... args) {

// Print the First Element
std::cout<<first<<" , ";

// Forward the remaining arguments
log(args ...);
}

现在假设我们通过这种方式调用log函数:

1
log(2, 3.4, "aaa");

居于模版的类型推导,编译器回创建这样的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void log(int first, double b, const char * c)
{
std::cout<<first<<" , ";
log(b, c);
}

void log(double first, const char * c)
{
std::cout<<first<<" , ";
log(c);
}

void log(const char * first)
{
std::cout<<first<<" , ";
log();
}

为了log函数能够在无参数的状态下返回,我们另外定义一个函数:

1
2
3
4
5
// Function that accepts no parameter
// It is to break the recursion chain of vardiac template function
void log()
{
}