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>();
}
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: 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:
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
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.
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?