Sample code:
struct S
{
static const int a = 0;
};
int const *b = &S::a;
My understanding of the intent of the ODR is that S::a
should be odr-used here, because its address is taken.
My question is: Where and how does the Standard specify that S::a
is odr-used in this code?
My research so far: The only relevant part of the C++14 standard seems to be [basic.def.odr]/3:
A variable
x
whose name appears as a potentially-evaluated expressionex
is odr-used byex
unless applying the lvalue-to-rvalue conversion tox
yields a constant expression that does not invoke any non-trivial functions and, ifx
is an object,ex
is an element of the set of potential results of an expressione
, where either the lvalue-to-rvalue conversion is applied toe
, ore
is a discarded-value expression.
However I don't see how S::a
fits into this. The definition of name ([basic]/4) excludes qualified-ids, so x
can't refer to S::a
here. I don't see any other text in the standard supporting the use of name to mean anything other than the definition from [basic]/4.
Maybe x
means a
; however a
never appears as an expression, let alone a potentially-evaluated one: the a
in S::a
is an identifier, not an expression. (A qualified-id is a nested-name-specifier followed by an identifier, or some other things not relevant here).
I also don't understand why two different placeholders x
and ex
are used in this sentence. Saying "A appears as B" says to me that A and B are lexically identical but seeing A in the context of B has some extra meaning. At first I thought this might mean x
is a more abstract way of talking about a variable (e.g. meaning the variable that is identified by S::a
) and ex
is an expression denoting that variable. However the quote goes on to say "Applying the lvalue-to-rvalue conversion to x
", therefore x
is actually an expression after all; so I don't see what the difference is between x
and ex
.
Further, I am not sure what "an expression e
" refers to exactly. I guess it is an existential taken over all expressions in the program such that ex
is a subexpression of e
.
This sloppy drafting seems to have been fixed in the C++23 draft by P1787R6.
[basic.def.odr]/5:
A variable is named by an expression if the expression is an id-expression that denotes it. A variable
x
that is named by a potentially-evaluated expression E is odr-used by E unless [...]
S::a
is an id-expression and it names the variable in question.