vso*_*tco 6 c++ templates variadic-templates c++11
通常用于执行可变参数扩展的一个技巧是使用未组合的数组typedef与逗号运算符组合,如下所示:
#include <iostream>
template<typename... Ts>
void expander(Ts&&... ts)
{
using expand = int[];
(void)expand{0, (std::forward<Ts>(ts)(), 0)...};
}
void f()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main()
{
expander(f, f);
}
Run Code Online (Sandbox Code Playgroud)
我们可以在不引入typedef的情况下这样做吗?如果我直接尝试
(void)int[]{0, (std::forward<Ts>(ts)(), 0)...};
Run Code Online (Sandbox Code Playgroud)
gcc/clang吐了出来
错误:'int'之前的预期primary-expression
如果我尝试括号,代码编译但我相信它是非标准的:
警告:ISO C++禁止复合文字[-Wpedantic]
在这个表达中
(void)int[]{0, (std::forward<Ts>(ts)(), 0)...};
Run Code Online (Sandbox Code Playgroud)
您正在尝试使用功能表示法转换来创建临时数组.这是行不通的,因为该语言只允许函数表示法与simple-type-specifier或typename-specifier一起使用.
类似地,一个简单型说明符或类型名称说明符后跟一个支撑-INIT列表创建具有指定的指定类型的直接清单初始化(8.5.4)的一个临时对象支撑-INIT列表,其值是临时对象作为prvalue.
如果你在[dcl.type.simple]下查找simple-type-specifier的定义,它不包含带数组括号的任何东西.事实上,它甚至不包含任何超过一个单词的内容.这就是为什么写作是有效的,但事实并非如此.int(1)signed int(1)
因此,使用C++ 11/14,您需要一个typedef或声明一个数组变量.但是,使用C++ 1z编译器,您可以使用折叠表达式并避免两者
template<typename... Ts>
void expander(Ts&&... ts)
{
(void(std::forward<Ts>(ts)()), ...);
}
Run Code Online (Sandbox Code Playgroud)
我们可以在不引入typedef的情况下这样做吗?
没有typedef,但有一个变量
template<typename... Ts>
void expander(Ts&&... ts)
{
int dummy[] = {0, (std::forward<Ts>(ts)(), void(), 0)...};
static_cast<void>(dummy); // Avoid warning for unused variable
}
Run Code Online (Sandbox Code Playgroud)