变长模板参数
template <typename T, typename... Args>
inline unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T(forward<Args>(args)...));
}
-
typename... Args声明了一系列的类型。 -
Args&&... args声明了一系列的形参 args,其类型是 Args&&。 -
forward<Args>(args)...会在编译时实际逐项展开 Args 和 args ,参数有多少项,展开后就是多少项。make_unique<vector<int>>(100, 1) 展开后: inline unique_ptr<vector<int>> make_unique(int&& arg1, int&& arg2) { return unique_ptr<vector<int>>(new vector<int>(forward<int>(arg1), forward<int>(arg2))); }
sizeof... 运算符
template <typename ...Args>
void foo(Args ...args)
{
cout << sizeof...(args) << endl;
}
foo(1, 3.14, "hello", "world"); // 输出 4
应用
- 用于在递归的模板中表达通用的情况(另外会有至少一个模板特化来表达边界情况)
- 用于在通用工具模板中转发参数到另外一个函数
编译器递归
也可以使用可变模板来实现编译器递归:
template <typename T>
constexpr auto sum(T x)
{
return x;
}
template <typename T1, typename T2, typename... Args>
constexpr auto sum(T1 x, T2 y, Args... args)
{
return sum(x + y, args...);
}
int main()
{
auto result = sum(1, 2, 3.5, 10);
// sum(1 + 2, 3.5, 10)
// sum(3 + 3.5, 10)
// sum(6.5 + 10)
// 16.5
}
转发用法
利用std::forward来传递参数的类型信息,一般具有固定格式:
template <typename T, typename... Args>
void func(Args&&... args)
{
work(std::forward<Args>(args)...);
}
例如:make_unique:
template <typename T, typename... Args>
inline unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T(forward<Args>(args)...);
}