The program is ill-formed and msvc is wrong in not giving a diagnostic(this has been fixed in latest version of msvc). This is because i
is not an statically allocated object and so its address is not constant. Basically, since we can initialize a constexpr
pointer only from either the nullptr
literal or literal 0
or from an address of an object that has fixed address and in your example, i
is not an object that has a fixed address so that &i
is not a constant expression.
This can be seen from expr.const#11 which states:
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
- if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a non-immediate function, or a null pointer value,
An entity is a permitted result of a constant expression if it is an object with static storage duration that either is not a temporary object or is a temporary object whose value satisfies the above constraints, or if it is a non-immediate function.
(emphasis mine)
This means that there are two ways to solve the problem. First is that you can add static
infront of i
to make it a local static. The second is to move the definition of i
to global scope outside the main function. In both cases(shown below), i
will then have static storage duration so that &i
will now be a constant expression according to the above quoted statement.
Method 1
int main()
{
//-vvvvvv------------->static added here so that i now has static storage duration
static int i = 0;
constexpr int *ptr= &i; //works now
}
Method 2
int i = 0; //make i global so that i now has static storage duration
int main()
{
constexpr int *ptr= &i; //works now
}
Here is the msvc bug report:
MSVC compiles invalid constexpr int*ptr= &i
where i is a local nonstatic object