Bruno Martinez
Bruno Martinez

Reputation: 2956

Why aren't fields from constant POD object constants themselves?

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

Answers (2)

Ryan Haining
Ryan Haining

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

Jerry Coffin
Jerry Coffin

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

Related Questions