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

标签 c++ templates gcc dynamic-arrays

下面的代码演示了我无法解释的 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的定义中被当作一个常量比特 vector 。如果 nbits 改为使用浮点表达式进行初始化,则编译器不再将其视为 bitVec 维度表达式中的常量,并且编译失败。

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

最佳答案

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

warning: ISO C++ forbids variable length array 'bitVec' [-Wvla]

此警告出现在 both bitVec 中,而不仅仅是模板函数中的那个。然后我意识到 nbits = 1e7; 行正在将 double 分配给 unsigned int。我认为正因为如此,由于某种原因导致 nbits 不是常量表达式。您的代码为非模板版本编译的原因是因为 gcc 的可变长度数组扩展。此外,出于某种原因,您的 gcc 版本不允许在函数模板中使用可变长度数组。要修复您的代码,请将 1e7; 更改为 10000000

编辑

我问了another question关于规则。答案是在C++03中代码无效,但在C++11中没问题。

关于c++ - 编译器错误? g++ 允许可变大小的静态数组,除非函数是模板化的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10923615/

相关文章:

C++ 用其他类型的值替换成员变量

c - 如何使用 TDM64-GCC 工具链执行标准 GCC "configure"脚本?

c++ - 如何在 vs 和 gcc 中使用 pack

C++ 错误 : expected primary-expression before ‘int’

c++ - 为字典 cpp 创建一个 []= 运算符

c++ - 动态构建模板参数包

c - AVR GCC 中 _SFR_IO_ADDR() 结果的大小

c - 为什么要区分 .rel.text 和 .rel.data 部分?

c++ - 死亡测试时错误的函数调用评估

c++ - 如果一个数字小于 "Max"数组中的相应数字,如何将其添加到数组中?