Reputation: 2956
I want to specialize a template for a certain GUID, which is a 16 byte struct. The GUID object has internal linkage, so I can't use the address of the object itself, but I thought I could use the contents of the object, since the object was a constant. But this doesn't work, as illustrated by this example code:
struct S
{
int const i;
};
S const s = { 42 };
char arr[s.i];
Why isn't s.i a constant if s is? Any workaround?
Upvotes: 3
Views: 182
Reputation: 36882
The initialization of the struct s
can happen at run time. However, the size of an array must be known at compile time. The compiler won't (for sure) know that the value of s.i
is known at compile time, so it just sees you're using a variable for something you shouldn't be. The issue isn't with constness, it's an issue of when the size of the array is needed.
You may be misunderstanding what const
means. It only means that after the variable is initialized, it is never changed. For example this is legal:
void func(int x){
const int i = x*5; //can't be known at compile-time, but still const
//int array[i]; //<-- this would be illegal even though i is const
}
int main(){
int i;
std::cin >> i;
func(i);
return 0;
}
To get around this limitation, in C++11 you can mark it as constexpr
to indicate that the value can be determined at compile time. This seems to be what you want.
struct S
{
int const i;
};
int main(){
constexpr S const s = { 42 };
char arr[s.i];
return 0;
}
compile with:
$ c++ -std=c++11 -pedantic file.cpp
in C99, what you're doing is legal, the size of an array does not need to be known at compile time.
struct S
{
int const i;
};
int main(){
struct S const s = { 42 };
char arr[s.i];
return 0;
}
compile with:
$ cc -std=c99 -pedantic file.c
Upvotes: 7
Reputation: 490408
At least most of the time, const
really means something much closer to "read-only" than to "constant". In C89/90, essentially all it means is "read-only". C++ adds some circumstances in which it can be constant, but it still doesn't even close to all the time (and, unfortunately, keeping track of exactly what it means when is non-trivial).
Fortunately, the "workaround" is to write your code the way you almost certainly should in any case:
std::vector<char> arr(s.i);
Bottom line: most use of a built-in array in C++ should be considered suspect. The fact that you can initialize a vector from a non-constant expression is only one of many advantages.
Upvotes: 2