下面的代码演示了我无法解释的 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>();
}
在我看来,使用参数 <unsigned char> 实例化模板应该会导致编译器生成与第一个函数相同的代码。任何人都可以提供任何见解,为什么这似乎不是这种情况?
[附录:第二个函数将使用“-std=c++0x”或“-std=gnu++0x”编译,但我仍然想了解在早期的语言定义下它是如何/是否是错误的。]
ETA:
如果 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
换句话说,似乎 ifnbits
用整数类型的表达式初始化,然后nbits
在 的定义中被视为常量bitVec
。如果nbits
改为使用浮点表达式初始化,编译器不再将其视为 的 维度表达式中的常量bitVec
,并且编译失败。
我在 C++ 中调用“编译器错误”比在 C 中要舒服得多,但我想不出任何其他原因使上述 4 种情况在语义上不完全相同。还有人愿意发表意见吗?