可变参数模板上下文中“…”标记的规则是什么?

在C ++ 11中有像这样的可变参数模板:

template< class T, class... Args > unique_ptr<T> make_unique( Args&&... args ) { return unique_ptr<T>(new T(std::forward<Args>(args)...)); } 

这里有一些好奇心:expression式std::forward<Args>(args)...使用Argsargs但只有一个...标记。 此外, std::forward是一个非variables模板函数,只需要一个模板参数和一个参数。 这个(粗略的)是什么语法规则? 怎么可以推广?

另外:在函数实现中,省略号( ... )在感兴趣的expression式的末尾。 是否有一个原因,在模板参数列表和参数列表省略号在中间?

在可变参数模板的上下文中,如果模板参数包出现在expression式的右侧(暂时调用这个expression式),则使用省略号...来解压缩参数包。 规则是,重复左侧的任何模式 – 解包的模式(现在称为expression式 )用逗号分隔。

这可以通过一些例子来得到最好的理解。 假设你有这个函数模板:

 template<typename ...T> void f(T ... args) { g( args... ); //pattern = args h( x(args)... ); //pattern = x(args) m( y(args...) ); //pattern = args (as argument to y()) n( z<T>(args)... ); //pattern = z<T>(args) } 

现在,如果我把这个函数传递给{int, char, short} ,那么每个函数调用都被展开为:

 g( arg0, arg1, arg2 ); h( x(arg0), x(arg1), x(arg2) ); m( y(arg0, arg1, arg2) ); n( z<int>(arg0), z<char>(arg1), z<short>(arg2) ); 

在您发布的代码中, std::forward遵循n()函数调用所示的第四个模式。

注意上面的x(args)...y(args...)之间的区别!


你可以使用...来初始化一个数组,也可以这样:

 struct data_info { boost::any data; std::size_t type_size; }; std::vector<data_info> v{{args, sizeof(T)}...}; //pattern = {args, sizeof(T)} 

这是扩展到这个:

 std::vector<data_info> v { {arg0, sizeof(int)}, {arg1, sizeof(char)}, {arg2, sizeof(short)} }; 

我只是意识到一个模式甚至可以包括像public这样的访问说明符,如下例所示:

 template<typename ... Mixins> struct mixture : public Mixins ... //pattern = public Mixins { //code }; 

在这个例子中,模式被扩展为:

 struct mixture__instantiated : public Mixin0, public Mixin1, .. public MixinN 

也就是说, mixture从所有基类公开派生出来。

希望有所帮助。

以下是来自Andrei Alexandrescu在2012年GoingNative上的“Variadic模板是有趣的”的演讲。我可以推荐它用于可变参数模板的一个很好的介绍。


可变数据包可以做两件事。 可以应用sizeof...(vs)来获取元素的数量并展开它。

扩展规则

 Use Expansion Ts... T1, ..., Tn Ts&&... T1&&, ..., Tn&& x<Ts,Y>::z... x<T1,Y>::z, ..., x<Tn,Y>::z x<Ts&,Us>... x<T1&,U1>, ..., x<Tn&,Un> func(5,vs)... func(5,v1), ..., func(5,vn) 

扩张向内进展。 当在锁步中扩展两个列表时,它们必须具有相同的大小。

更多例子:

 gun(A<Ts...>::hun(vs)...); 

展开A的模板参数列表中的所有Ts ,然后函数hun与所有vs进行扩展。

 gun(A<Ts...>::hun(vs...)); 

展开A的模板参数列表中的所有Ts和所有vs作为hun的函数参数。

 gun(A<Ts>::hun(vs)...); 

Tsvslockingfunction扩展function。

注意:

Ts不是一个types, vs不是一个价值! 它们是types/值列表的别名。 这两个列表都可能是空的。 双方只服从具体的行动。 所以以下是不可能的:

 typedef Ts MyList; // error! Ts var; // error! auto copy = vs; // error! 

扩展轨迹

函数参数

 template <typename... Ts> void fun(Ts... vs) 

初始化程序列表

 any a[] = { vs... }; 

基本说明符

 template <typename... Ts> struct C : Ts... {}; template <typename... Ts> struct D : Box<Ts>... { /**/ }; 

成员初始化列表

 // Inside struct D template <typename... Us> D(Us... vs) : Box<Ts>(vs)... {} 

临时参数列表

 std::map<Ts...> m; 

只有在参数可能匹配时才会编译。

捕获列表

 template <class... Ts> void fun(Ts... vs) { auto g = [&vs...] { return gun(vs...); } g(); } 

属性列表

 struct [[ Ts... ]] IAmFromTheFuture {}; 

这是在规范中,但是没有属性可以表示为一种types。