Ral*_*zky 96 c++ variadic-templates c++11
在C++ 11中有像这样的可变参数模板:
template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
Run Code Online (Sandbox Code Playgroud)
有一些好奇这个问题:表达std::forward<Args>(args)...同时使用Args和args,但只有一个...令牌.此外,std::forward是一个非可变参数模板函数,只接受一个模板参数和一个参数.那个(大致)的语法规则是什么?如何概括?
另外:在函数实现中,省略号(...)位于感兴趣的表达式的末尾.有没有理由在模板参数列表和参数列表中省略号位于中间?
Naw*_*waz 96
在可变参数模板的上下文中,省略号...用于解析模板参数包,如果它出现在表达式的右侧(暂时调用此表达式模式).规则是重复左侧的任何模式... - 解包模式(现在称它们为表达式)用逗号分隔,.
通过一些例子可以最好地理解它.假设你有这个功能模板:
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)
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我将此函数调用T为as {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) );
Run Code Online (Sandbox Code Playgroud)
在您发布的代码中,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)}
Run Code Online (Sandbox Code Playgroud)
这扩展到这个:
std::vector<data_info> v
{
{arg0, sizeof(int)},
{arg1, sizeof(char)},
{arg2, sizeof(short)}
};
Run Code Online (Sandbox Code Playgroud)
我刚刚意识到一个模式甚至可以包含访问说明符public,如下例所示:
template<typename ... Mixins>
struct mixture : public Mixins ... //pattern = public Mixins
{
//code
};
Run Code Online (Sandbox Code Playgroud)
在此示例中,模式扩展为:
struct mixture__instantiated : public Mixin0, public Mixin1, .. public MixinN
Run Code Online (Sandbox Code Playgroud)
也就是说,从所有基类公开mixture派生.
希望有所帮助.
typ*_*232 47
以下内容摘自Andrei Alexandrescu在GoingNative 2012上的演讲"Variadic Templates are Funadic".我可以推荐它,以便对可变参数模板进行详细介绍.
使用可变电池组可以做两件事.可以应用于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)
Run Code Online (Sandbox Code Playgroud)
扩张向内进行.在锁定步骤中扩展两个列表时,它们必须具有相同的大小.
gun(A<Ts...>::hun(vs)...);
Run Code Online (Sandbox Code Playgroud)
Ts在模板参数列表中展开all ,A然后hun使用all扩展函数vs.
gun(A<Ts...>::hun(vs...));
Run Code Online (Sandbox Code Playgroud)
扩展Ts模板参数列表中的Aall和all vs作为函数参数hun.
gun(A<Ts>::hun(vs)...);
Run Code Online (Sandbox Code Playgroud)
hun使用Ts和vs以锁定步骤扩展功能.
Ts不是一种类型,vs也不是一种价值!它们是类型/值列表的别名.任何一个列表都可能是空的.两者都只服从特定的行动.所以以下是不可能的:
typedef Ts MyList; // error!
Ts var; // error!
auto copy = vs; // error!
Run Code Online (Sandbox Code Playgroud)
template <typename... Ts>
void fun(Ts... vs)
Run Code Online (Sandbox Code Playgroud)
any a[] = { vs... };
Run Code Online (Sandbox Code Playgroud)
template <typename... Ts>
struct C : Ts... {};
template <typename... Ts>
struct D : Box<Ts>... { /**/ };
Run Code Online (Sandbox Code Playgroud)
// Inside struct D
template <typename... Us>
D(Us... vs) : Box<Ts>(vs)... {}
Run Code Online (Sandbox Code Playgroud)
std::map<Ts...> m;
Run Code Online (Sandbox Code Playgroud)
只有在参数可能匹配时才会编译.
template <class... Ts> void fun(Ts... vs) {
auto g = [&vs...] { return gun(vs...); }
g();
}
Run Code Online (Sandbox Code Playgroud)
struct [[ Ts... ]] IAmFromTheFuture {};
Run Code Online (Sandbox Code Playgroud)
它在规范中,但没有可以表示为类型的属性.