C++: Expression must have a constant value when declaring array inside function

There is a misconception here with what const means, probably because it’s a little confusing that this works:

const int SIZE = 20;
int array[SIZE];

but this doesn’t:

void foo(const int SIZE) {
    int array[SIZE];
    // ...
}

const int SIZE = 20;
foo(SIZE);

The issue is that the array size in an array declaration must be a core constant expression. Simplified, that means an expression that’s evaluatable at compile time to be a constant. That is true in the first case (you can see that SIZE is the integral constant 20) but that is not true in the second case. There, the SIZE function parameter is just const – in the sense that it is nonmodifiable – and not a core constant expression. You can see the difference in that I can call foo() with something that is clearly unknowable until runtime:

int x;
if (std::cin >> x) {
    foo(x);
}

In order to pass an argument into foo, and have that argument be used as an array bound, it is not enough to have it be const – the actual integral value must be encoded into the type (unless you call foo() as constexpr which I’m assuming is not the case here). In which case, you’d have to do something like:

template <int SIZE>
void foo() { ... }

const int SIZE = 20;
foo<SIZE>();

or:

template <int SIZE>
void foo(std::integral_constant<int, SIZE > ) { ... }

const int SIZE = 20;
foo(std::integral_constant<int, SIZE>{} );

or simply have SIZE be a global constant or otherwise accessible to foo() in a way that doesn’t have to do with its arguments.


Or, there’s always the simple option: use std::vector:

void foo(const int SIZE) {
    std::vector<int> v(SIZE);
    ...
}

Leave a Comment