Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ INTA[]{(函数调用(a1,a2),0)…};(a)项无效;这个语法是什么意思?_C++_Templates_C++11_Variadic Templates_List Initialization - Fatal编程技术网

C++ INTA[]{(函数调用(a1,a2),0)…};(a)项无效;这个语法是什么意思?

C++ INTA[]{(函数调用(a1,a2),0)…};(a)项无效;这个语法是什么意思?,c++,templates,c++11,variadic-templates,list-initialization,C++,Templates,C++11,Variadic Templates,List Initialization,我看到这篇文章建议使用以下语法: template<typename T> void append_to_vector(std::vector<T>& v1, const std::vector<T>& v2) { std::cout << v2[0] << std::endl; for (auto& e : v2) v1.push_back(e); } template<typename T,

我看到这篇文章建议使用以下语法:

template<typename T>
void append_to_vector(std::vector<T>& v1, const std::vector<T>& v2) {
  std::cout << v2[0] << std::endl;
  for (auto& e : v2) v1.push_back(e);
}


template<typename T, typename... A>
std::vector<T> concat_version3(std::vector<T> v1, const A&... vr) {
    int unpack[] { (append_to_vector(v1, vr), 1)... };
    (void(unpack));
    return v1;
}
这似乎是某种动态生成的初始化列表,它也有副作用?我还感到困惑的是,上面的
0
并不重要。我替换了-1和5,这两个值也都很好

有人能告诉我这种技术/语法的名称,以及上面两行中到底发生了什么?如果我错过了相关的SO帖子,我将非常感谢您的指点,并向您道歉

int unpack[] { (append_to_vector(v1, vr), 1)... };
//        ^^ |                          |   ||| |    array of ints
//           ^                          |    |  ^    array initializer
//                                      ^    |       comma operator
//                                          ^^^      pack expansion
这将创建一个
int
s数组,其中包含与参数包
vr
大小相同的元素。数组中的每个元素都是
1
,这是计算两个参数后返回的值。最后一个省略号表示正在执行参数包
vr

因此,如果将函数调用为
concat_version3(v1、v2、v3)
,其中所有参数都是
vector
s,那么上述表达式将导致

int unpack[]{ (append_to_vector(v1, v2), 1), (append_to_vector(v1, v3), 1) };
在带括号的init列表中计算表达式的好处是,计算顺序是固定的,从左到右

§8.5.4/4【dcl初始清单】

在带括号的init列表的初始值设定项列表中,初始值设定项子句,包括由包扩展(14.5.3)产生的任何子句,按照它们出现的顺序进行计算

因此,您可以保证在
v3
之前将
v2
附加到
v1
,这就是您想要的


这只是避免编译器发出未使用的变量警告的一种方法


现在,我将以稍微不同的方式编写
解包
初始化

int unpack[] { 1, (append_to_vector(v1, vr), 1)... };
//             ^^
在原始版本中,如果将函数调用为
concat_version3(v1)
,即使用空参数包,代码将无法编译,因为您将尝试创建一个零大小的数组,添加额外的元素可以修复该问题

此外,如果您在更一般的代码中使用上述表达式,而您不知道
append\u to\u vector
的返回类型是什么,那么您还需要防止它返回的类型可能会重载逗号运算符。那样的话,你会写信的

int unpack[] { 1, (append_to_vector(v1, vr), void(), 1)... };
通过在中间添加
void()
表达式,可以确保未选择重载的逗号运算符,并且始终调用内置的逗号运算符


最后,如果您有一个能够理解的编译器,那么您可以取消整个数组技巧,只需编写

template<typename T, typename... A>
std::vector<T> concat_version3(std::vector<T> v1, const A&... vr)
{
    (void)(((append_to_vector(v1, vr), void()), ...));
    return v1;
}
模板
std::vector concat_version3(std::vector v1,常量A和…vr)
{
(void)((将_附加到_向量(v1,vr),void(),…);
返回v1;
}


注意:
void
cast后的额外括号是由于a而需要的。

此技术实现了为给定的每个变量参数调用函数
append\u to_vector(v1,X)
一次,并依次用每个元素替换
X
。我称之为“虚拟数组逗号运算符黑客”,不知道它是否有正式名称:)非常感谢您提供了这个非常全面的答案。非常感谢。折叠表达式案例可以使用<代码>空格 CAST(以防止重载逗号)。谢谢你,没有考虑这个可能性,不知怎么说,折叠表达式看起来太酷了,不易受到这样的陷阱的影响:现在已经固定了。在另一个帖子里,有人问我为什么不支持这个:<代码> AppDeNotoToV矢(V1,VR)。...;具有相同的效果并丢弃返回值,并且我没有answer@M.M我的猜测是,允许省略号应用于扩展的参数包以外的其他对象,而不使用中间运算符,将导致语法歧义。出于类似的原因,我一直认为折叠表达式需要在其周围加括号。
int unpack[] { 1, (append_to_vector(v1, vr), void(), 1)... };
template<typename T, typename... A>
std::vector<T> concat_version3(std::vector<T> v1, const A&... vr)
{
    (void)(((append_to_vector(v1, vr), void()), ...));
    return v1;
}