It’s a bit more complicated. In C++03 and C++11, &var
is a constant expression if var
is a local static / class static or namespace scope variable. This is called an address constant expression. Initializing a class static or namespace scope pointer variable with that constant expression is guaranteed to be done before any code is run (static initialization phase), because of it being a constant expression.
However only since C++11, a constexpr pointer variable that stores the address &var
can also be used as an address constant expression and only since C++11, you can dereference an address constant expression (actually, you can dereference even more – even local array element addresses, but let’s keep it ontopic) and if it refers to a constant integral variable initialized prior to the dereference or a constexpr variable, you again get a constant expression (depending on the type and value category, the kind of constant expression may vary). As such, the following is valid C++11:
int const x = 42;
constexpr int const *px = &x;
// both the value of "px" and the value of "*px" are prvalue constant expressions
int array[*px];
int main() { return sizeof(array); }
If so, why can’t a pointer be a constant expression? If not, why don’t the above programs compile?
This is a known limitation in the Standard’s wording – it currently only allows other template parameters as arguments or & object
, for a template parameter of pointer type. Even though the compiler should be capable of doing much more.