可变参数模板上下文中“…”标记的规则是什么?
在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)...
使用Args
和args
但只有一个...
标记。 此外, 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)...);
用Ts
和vs
lockingfunction扩展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。
- C ++:macros可以将“abc”扩展为“a”,“b”,“c”吗?
- 有没有std :: shared_ptr的非primefaces等价物? 为什么在<内存>中没有一个?
- constexpr超载
- 为什么MSVC ++ 11拒绝函数的constexpr限定?
- 对n个第一个元素已经sorting的向量进行sorting?
- 使用C ++ 11随机库生成随机数
- 理解C ++ 11中的std :: atomic :: compare_exchange_weak()
- C + + 11:std ::线程池?
- 为什么std :: vector和std :: array的C ++ initializer_list行为不同?