【发布时间】:2012-06-06 23:14:54
【问题描述】:
下面的代码演示了我无法解释的 gcc 4.6.2 的行为。第一个函数声明了一个 vec_t 类型的静态数组,其中 vec_t 是 unsigned char 的 typedef 别名。第二个函数是相同的,只是 vect_t 的类型是一个模板参数。第二个函数编译失败,诊断为“错误:‘bitVec’的存储大小不是常数”。
#include <limits>
void bitvec_func()
{
const std::size_t nbits = 1e7;
typedef unsigned char vec_t;
const std::size_t WLEN = std::numeric_limits<vec_t>::digits;
const std::size_t VSIZ = nbits/WLEN+1;
static vec_t bitVec[nbits/VSIZ]; // Compiles fine
}
template <typename T>
void bitvec_func()
{
const std::size_t nbits = 1e7;
typedef T vec_t;
const std::size_t WLEN = std::numeric_limits<vec_t>::digits;
const std::size_t VSIZ = nbits/WLEN+1;
static vec_t bitVec[nbits/VSIZ]; // "error: storage size of ‘bitVec’ isn’t constant"
}
void flarf()
{
bitvec_func();
bitvec_func<unsigned char>();
}
在我看来,使用参数
[附录:第二个函数将使用“-std=c++0x”或“-std=gnu++0x”编译,但我仍然想了解如何/如果在早期的语言定义下是错误的。]
预计到达时间:
如果 nbits 的初始值设定项改变,第二个函数将编译:
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
换句话说,如果nbits 是用整数类型的表达式初始化的,那么nbits 在bitVec 的定义中被视为常量。如果 nbits 改为使用浮点表达式初始化,则编译器不再将其视为 bitVec 维度的表达式中的常量,并且编译失败。
在 C++ 中调用“编译器错误”比在 C 中要舒服得多,但我想不出任何其他原因使上述 4 种情况在语义上不完全相同。还有人愿意发表意见吗?
【问题讨论】:
-
您能否发布导致编译器错误的确切代码?我似乎无法重现它。
-
这就是上面的确切代码。编译器是 gcc 4.6.2,选项是“-O0 -g3 -c”。
-
在较旧的 gcc 4.3.4 上,此代码 compiled fine.
-
有趣。我逐字复制了您的代码并在 4.6.2 上重现了该错误。也许这是一个相对较新的“功能” :) 感谢您的检查。
-
对不起,我之前没有意识到,但你想用
nbits = 1e7;做什么?如果您尝试将十六进制值分配给无符号整数,那将不起作用(另外,我认为这是问题所在)。
标签: c++ templates gcc dynamic-arrays