Why can't a constant pointer be a constant expression?
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.
It's still not allowed in C++0x. temp.arg.nontype
requires:
A template-argument for a non-type, non-template template-parameter shall be one of:
- for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
- the name of a non-type template-parameter; or
- a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as
&
id-expression
, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or- a constant expression that evaluates to a null pointer value (4.10); or
- a constant expression that evaluates to a null member pointer value (4.11); or
- a pointer to member expressed as described in 5.3.1.
original answer:
- In C++03, only integral expressions can be constant expressions.
- Because the standard says so (naturally).
- In C++0x, n3290 includes examples using
constexpr
on a pointer. So what you are trying should now be possible, although you must now use theconstexpr
keyword instead of top-levelconst
.
There's also a gcc bug involved, g++ rejects the standard draft's own examples of valid constexpr
usage.