progress

I'd rather be anything but ordinary

0%

C++ variadic template

C++ variadic template is a template with at least one parameter pack,A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates).

以上为C++ variadic template的定义,在现代C++中模板被大量使用,今天学习下C++中的variadic template.
首先给出一个运用variadic template的例子,但是它并不能编译。

template<typename T>
static void bar(T t) {}

template<typename... Args>
static void foo2(Args... args)
{
(bar(args)...);
}

不能编译的原因,也很简单,涉及到Pack expansion,查文档知expansin location 如下:

Depending on where the expansion takes place, the resulting comma-separated list is a different kind of list: function parameter list, member initializer list, attribute list, etc.

以上并不符合任意条件。
我们需要将其改为如下形式:

template <typename T> void bar(T t) { std::cout << t << " "; }
void foo() {}
template <typename T, typename... Args> void foo(T t, Args... args) {
bar(t);
foo(args...);
}

使用递归来使Pack expansion执行。上述代码是对的,但是需要refinement,我们需要运用现代C++的特性使其变得更有效率。

template <typename T> void bar(T&& t) { std::cout << t << " "; }
void foo() {}
template <typename T, typename... Args> void foo(T&& t, Args&&... args) {
bar(forward<T>(t));
foo(forward<Args>(args)...);
}

关于为什么要添加forward&&符号,我会另写一篇来介绍forwardmove.
为了简洁,我们可以用到其他可以Pack expansion的情况,Braced init lists。
实现如下:

template <typename... Ts> void f(Ts... args) {
int dummy[]={(bar(std::forward<Ts>(args)), 0)...};
}

dummy通过Braced init({})变为Braced init lists,expansion发生。