mar*_*n78 14 c++ templates variadic-templates c++11
不知怎的,我不知道如何扩展可变参数模板参数包.以下代码有什么问题?
#include <iostream>
template <typename T>
struct print_one
{
static void run(const T& t)
{
std::cout << t << ' ';
}
};
template<typename... Args>
void print_all(Args&&... args)
{
// the next line doesn't compile:
print_one<Args>::run(std::forward<Args>(args))...;
}
int main()
{
print_all(1.23, "foo");
}
Run Code Online (Sandbox Code Playgroud)
Clang说,Expression contains unexpanded parameter packs 'Args' and 'args'
.为什么?
eca*_*mur 25
在...
已去函数调用括号内:
print_one<Args>::run(std::forward<Args>(args)...);
Run Code Online (Sandbox Code Playgroud)
显然,这对于只接受单个参数的函数不起作用,因此您需要找到一种方法将调用扩展为函数调用或其他允许的构造:
// constructing a dummy array via uniform initialization
// the extra 0 at the start is to make it work when the pack is empty
int dummy[]{0, (print_one<Args>::run(std::forward<Args>(args)), 0)...};
// or, if your compiler doesn't support uniform initialization
int dummy[] = {0, (print_one<Args>::run(std::forward<Args>(args)), 0)...};
// or, calling a dummy function
template<typename... Args> void dummy(Args...) {}
dummy((print_one<Args>::run(std::forward<Args>(args)), 0)...);
// or, constructing a temporary dummy object
struct dummy { dummy(std::initializer_list<int>) {} };
dummy{(print_one<Args>::run(std::forward<Args>(args)), 0)...};
// or, constructing a temporary initializer list
std::initializer_list<int>{(print_one<Args>::run(std::forward<Args>(args)), 0)...};
Run Code Online (Sandbox Code Playgroud)
请注意使用逗号运算符将void
返回print_one
值转换为适合放在参数列表或初始化表达式中的值.
初始化列表形式比函数调用形式更受欢迎,因为它们(应该是)有序的LTR,函数调用参数不是.
可以发生参数包扩展的表单由14.5.3 [temp.variadic]涵盖:
4 - [...]包扩展可以在以下上下文中发生:
- [...]
您的原始代码是非法的,因为虽然在文本上可能看起来它应该产生一个由多个逗号运算符表达式组成的语句,但这不是14.5.3:4允许的上下文.
该标准规定了允许包扩展的位置:
§14.5.3 [temp.variadic] p4
[...] 包扩展可能发生在以下上下文中:
- 在函数参数包(8.3.5)中;模式是没有省略号的参数声明。
- 在作为包扩展 (14.1) 的模板参数包中:
- 如果模板参数包是一个参数声明;模式是没有省略号的参数声明;
- 如果模板参数包是带有模板参数列表的类型参数;模式是不带省略号的相应类型参数。
- 在初始化列表(8.5)中;该模式是一个初始化子句。
- 在基本说明符列表中(第 10 条);该模式是一个基本说明符。
- 在mem-initializer-list (12.6.2) 中;该模式是一个mem-initializer。
- 在模板参数列表(14.3)中;该模式是一个模板参数。
- 在动态异常规范(15.4) 中;模式是一个type-id。
- 在属性列表(7.6.1)中;模式是一个属性。
- 在对齐说明符(7.6.2) 中;模式是没有省略号的对齐说明符。
- 在捕获列表(5.1.2)中;该模式是一个捕获。
- 在
sizeof...
表达式 (5.3.3) 中;模式是一个标识符。
所以基本上,作为顶级声明,扩展是不允许的。这背后的原因是什么?不知道。很可能他们只选择了分隔逗号 ( ,
) 是语法一部分的上下文;operator,
如果涉及用户定义的类型并遇到麻烦,您可能会选择重载的其他任何地方。
归档时间: |
|
查看次数: |
10832 次 |
最近记录: |