Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.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++ 编译器错误?g++;允许可变大小的静态数组,除非函数已模板化_C++_Templates_Gcc_Dynamic Arrays - Fatal编程技术网

C++ 编译器错误?g++;允许可变大小的静态数组,除非函数已模板化

C++ 编译器错误?g++;允许可变大小的静态数组,除非函数已模板化,c++,templates,gcc,dynamic-arrays,C++,Templates,Gcc,Dynamic Arrays,下面的代码演示了GCC4.6.2的一个行为,我对此无法解释。第一个函数声明vec_t类型的静态数组,其中vec_t是unsigned char的typedef别名。第二个函数相同,只是vect_t的类型是一个模板参数。第二个函数编译失败,诊断为“错误:'bitVec'的存储大小不是常量” 换句话说,如果用整型表达式初始化nbits,则nbits在bitVec的定义中被视为常量。如果使用浮点表达式初始化nbits,编译器将不再将其视为bitVec维度表达式中的常量,编译将失败 我在C++中调用“编

下面的代码演示了GCC4.6.2的一个行为,我对此无法解释。第一个函数声明vec_t类型的静态数组,其中vec_t是unsigned char的typedef别名。第二个函数相同,只是vect_t的类型是一个模板参数。第二个函数编译失败,诊断为“错误:'bitVec'的存储大小不是常量”

换句话说,如果用整型表达式初始化
nbits
,则
nbits
bitVec
的定义中被视为常量。如果使用浮点表达式初始化
nbits
,编译器将不再将其视为
bitVec
维度表达式中的常量,编译将失败


<>我在C++中调用“编译器错误”比在C中要舒服得多,但是我想不出任何其他原因,上述4种情况在语义上是不一样的。还有人愿意发表意见吗?

答案肯定是,在生成错误的编译阶段,数组索引的存储大小不是恒定的——即,它位于模板扩展的上游。动态数组不是C++ 98/03的一部分,它们是GCC扩展(C,最初是C)。所以这个错误实际上是正确的,即使实现看起来很奇怪。大概GCC会为模板化数组找到一条符合标准的路径,在需要时支持它们,否则会抛出错误,但静态类型的数组会找到“C”路径,从而自动获取GCC扩展。

在GCC 4.7.0上使用
-ansi
编译代码后,我能够重现此警告:

warning: ISO C++ forbids variable length array 'bitVec' [-Wvla]
此警告针对的是两个
bitVec
,而不仅仅是模板函数中的一个。然后我意识到行
nbits=1e7
正在将一个
双精度
赋值给一个
无符号整数
。我认为正因为如此,出于某种原因,
nbits
不是一个常量表达式。代码为非模板版本编译的原因是gcc的可变长度数组扩展。另外,由于某些原因,您的gcc版本不允许在函数模板中使用可变长度数组。修复代码更改
1e7
10000000

编辑


我问有关规则的问题。答案是,在C++03中,代码无效,但在C++11中,代码没有问题。

您能否发布导致编译器错误的确切代码?我似乎无法复制它。这正是上面的代码。编译器是GCC4.6.2,选项是“-O0-g3-c”。在旧的GCC4.3.4上,这段代码很有趣。我一字不差地复制了您的代码,并在4.6.2中重现了错误。也许这是一个相对较新的“功能”:)感谢您的检查。很抱歉,我以前没有意识到,但是您想用
nbits=1e7?如果您试图将一个十六进制值赋给一个无符号int,那么这将不起作用(我认为这也是问题所在)。代码实际上没有变量数组,因此错误是错误的。数组的大小在编译时是已知的,应该由一致的编译器来处理。这不仅仅是运行时可变性的问题。我相信(但我懒得去检查),C++03特别在数组大小的初始值设定项中不允许使用模板参数(正是因为在正确的时间进行扩展时存在鸡和蛋的问题)。毫无疑问,会有更了解规范的人来纠正我。很有趣。这(混乱)是有效的:
template void a(){typedef T vec_T;static vec_T bitVec[sizeof(vec_T)*8]}
它并没有失去它的
const
属性,而是(隐含的)
constepr
属性。@moingduck:这是真的(已更正)。然而,我仍然想知道为什么会是这样。
1e7
0x1e7
是非常不同的数字<代码>10000000
将是一个更好的替代品。如上所述,1e7(10000000)是预期的。这似乎是问题的症结所在。IANAL,但我的理解是,
inti=123.4
将浮点常量转换为int,并使用结果初始化
i
。但是,将“
nbits
”初始值设定项从
1e7
更改为
10000000
,甚至
(std::size_t)1e7
可以消除错误。@JohnA:请参阅我答案中的链接。在C++03中,
inti=123.4
是无效的,但在C++11中,规则发生了变化,这是正常的。
const std::size_t       nbits = 1e7;              // Error
const std::size_t       nbits = (std::size_t)1e7; // Okay
const std::size_t       nbits = 10000000.0;       // Error
const std::size_t       nbits = 10000000;         // Okay
warning: ISO C++ forbids variable length array 'bitVec' [-Wvla]