编译器错误? g ++允许可变大小的静态数组,除非函数是模板化的 [英] Compiler bug? g++ allows variable-size static arrays, unless function is templated

查看:180
本文介绍了编译器错误? g ++允许可变大小的静态数组,除非函数是模板化的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码演示了gcc 4.6.2的行为,我不能解释。第一个函数声明一个类型为vec_t的静态数组,其中vec_t是unsigned char的typedef的别名。第二个函数是相同的,除了vect_t的类型是模板参数。第二个函数无法使用诊断程序进行编译错误:bitVec的存储大小不是常量。

The code below demonstrates a behavior of gcc 4.6.2 that I can't account for. The first function declares a static array of type vec_t, where vec_t is a typedef'd alias for unsigned char. The second function is identical, except that the type of vect_t is a template parameter. The second function fails to compile with diagnostic "error: storage size of ‘bitVec’ isn’t constant".

#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>来实例化模板应该使编译器生成与第一个函数相同的代码。

It seems to me that instantiating the template with argument <unsigned char> should cause the compiler to generate the same code as the first function. Can anyone offer any insight into why this does not seem to be the case?

[Addendum:第二个函数编译时使用-std = c ++ 0x或-std = gnu ++ 0x,但我仍然想了解如何/如果它在前面的语言定义是错误的。]

[Addendum: the second function will compile with "-std=c++0x" or "-std=gnu++0x", but I'd still like to understand how/if it's wrong under the earlier language definitions.]

ETA:

如果nbits的初始化程序更改,则第二个函数将编译:

ETA:
The second function will compile if the initializer for nbits is changed:

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 ,编译失败。

In other words, it seems that if nbits is initialized with an expression of an integral type, then nbits is treated as a constant in the definition of bitVec. If nbits is instead initialized with a floating-point expression, the compiler no longer sees it as constant in the expression for the dimension of bitVec, and the compilation fails.

我不太习惯在C ++中调用编译器错误,而不是在C中,认为上述4种情况在语义上不会相同的任何其他原因。

I'm a lot less comfortable calling "compiler bug" in C++ than I would be in C, but I can't think of any other reason that the above 4 cases would not be semantically identical. Anyone else care to opine?

推荐答案

在使用 -ansi 在gcc 4.7.0,我能够重现此警告:

After compiling your code with -ansi on gcc 4.7.0, I was able to reproduce this warning:

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

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

This warning appeared for both bitVec, not just the one in the template function. I then realized that the line nbits = 1e7; is assigning a double to an unsigned int. I think because of this, for some reason causes nbits to not be a constant expression. The reason your code is compiling for the non-templated version is because of the variable length array extension for gcc. Also, your version of gcc for some reason doesn't allow variable length arrays in function templates. To fix your code change 1e7; to 10000000.

EDIT

我问过。答案是在C ++ 03的代码是无效的,但在C ++ 11它是好的。

I asked another question concerning the rule. The answer is in C++03 the code is invalid, but in C++11 it is okay.

这篇关于编译器错误? g ++允许可变大小的静态数组,除非函数是模板化的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆