DR 712 was responsible for the change in the wording of [basic.def.odr]/2 in C++11 to the current wording today, in [basic.def.odr]2 and 3. But I'm still trying to understand the reason for the change, as stated in the DR, as follows:
712. Are integer constant operands of a conditional-expression “used?”
In describing static data members initialized inside the class definition, 9.2.3.2 [class.static.data] paragraph 3 says,
The member shall still be defined in a namespace scope if it is used in the program...
The definition of “used” is in 3.2 [basic.def.odr] paragraph 1:
An object or non-overloaded function whose name appears as a potentially-evaluated
expression is used unless it is an object that satisfies the requirements for appearing in a constant expression (5.20 [expr.const]) and the lvalue-to-rvalue conversion (4.1 [conv.lval])
is immediately applied.Now consider the following example:
struct S { static const int a = 1; static const int b = 2; }; int f(bool x) { return x ? S::a : S::b; }
According to the current wording of the Standard, this example requires that
S::a
andS::b
be defined in a namespace scope. The reason for this is that, according to 5.16 [expr.cond] paragraph 4, the result of this conditional-expression is an lvalue and the lvalue-to-rvalue conversion is applied to that, not directly to the object, so this fails the “immediately applied” requirement. This is surprising and unfortunate, since only the values and not the addresses of the static data members are used. (This problem also applies to the proposed resolution of issue 696.)
Well, if the "immediately applied requirement fails, then the expressions S::a
and S::b
in the conditional expression are not used (odr-used), and so, the respective static members of struct S
will not need to be defined in namespace scope. But this is exactly the opposite of what the DR is saying. What am I missing???
I think you're missing the point of the used
definition:
it is used UNLESS ( (const) AND (immediately applied) )
So, if "immediately applied" is false, then the UNLESS is false, and thus it is used.
An object or non-overloaded function whose name appears as a potentially-evaluated expression is used unless[...]
Well, S::a
and S::b
appear in a potentially-evaluated expression within f
.
So they are used, unless either of the following exceptions apply.
[...] it is an object that satisfies the requirements for appearing in a constant expression (5.20 [expr.const]) and the lvalue-to-rvalue conversion (4.1 [conv.lval]) is immediately applied.
Well, it is an object that satisfied the requirement for appearing in a constant expression. So it passes that test.
But the lvalue-to-rvalue conversion is not immediately applied.
So it fails that test.
As this entire section is under "unless", the failure means that the previous case applies; the object is considered "used".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With