I'm using a recent github draft based on N4296. The actual C++14 International Standard does not contain this example, nor the numbering of bullet points. The specification relevant here is effectively the same.
We decompose the expression in the initializer: b ? (1, S::x) : f(S::x)
The expression (1, S::x)
is an lvalue of type int const
.
The expression f(S::x)
is a postfix-expression, an lvalue of type int const
.
Hence the expression b ? (1, S::x) : f(S::x)
is an lvalue of type int const
. It therefore fulfils [basic.def.odr]p2.5, and the set of potential results is the union of the sets of potential results of the sub-expressions (1, S::x)
and f(S::x)
.
For the first sub-expression (1, S::x)
, we strip the parentheses via p2.4. The result 1, S::x
is a comma expression. We apply p2.6 and get S::x
. Now, p2.1 applies and tells us that this first occurrence is part of the set of potential results of the initializer.
For the second sub-expression f(S::x)
, only p2.7 applies. Its set of potential results is empty, so it doesn't add anything to the set of potential results of the initializer.
As for the odr-use of S::x
, [basic.def.odr]p3
A variable x
whose name appears as a potentially-evaluated expression
ex
is odr-used by ex
unless applying the lvalue-to-rvalue conversion
to x
yields a constant expression that does not invoke
any non-trivial functions and, if x
is an object, ex
is an element of
the set of potential results of an expression e
, where either the
lvalue-to-rvalue conversion is applied to e
, or e
is a
discarded-value expression.
Let's split this into steps: The occurrence of a variable x
in an expression ex
constitutes an odr-use unless:
- Either
ex
is not potentially evaluated, or
- All of the following must be fulfilled:
- "applying the lvalue-to-rvalue conversion to
x
yields a constant expression that does not invoke any non-trivial functions" and
- "
ex
is an element of the set of potential results of an expression e
" and either of the following holds:
- "either the lvalue-to-rvalue conversion is applied to
e
"
- "or
e
is a discarded-value expression"
Note that point 2 means "is an element of the set of potential results of ANY expression e
[where e
fulfils certain requirements]", rather than "all expressions e
it is part of". Further discussion can be found on the std-discussion mailing list.
Applying the steps to the second occurrence of `S::x`
It is part of the expressions S::x
, f(S::x)
, b ? (1, S::x) : f(S::x)
.
- False (since all of these expressions are potentially evaluated), or
- All of the following must be fulfilled:
- True (since applying the l-t-r conversion to
S::x
yields a constant expression that does not invoke any functions) and
- The only expression where the second occurrence of
S::x
is an element of the set of potential results is S::x
itself. It is not part of the potential results of f(S::x)
. Either of the following must hold:
- either false (since the lvalue-to-rvalue conversion is not applied when binding
S::x
to the function parameter of f
)
- or false (since
S::x
is not a discarded-value expression)
The exception does not apply, S::x
is odr-used via its second occurrence.
Applying the steps to the first occurrence of `S::x`
It is part of the expressions S::x
, 1, S::x
, (1, S::x)
, b ? (1, S::x) : f(S::x)
.
- False (since all of these expressions are potentially evaluated), or
- All of the following must be fulfilled:
- True (since applying the l-t-r conversion to
S::x
yields a constant expression that does not invoke any functions) and
- The first occurrence of
S::x
is an element of the set of potential results of all the expressions it is part of within the initializer. Either of the following must hold:
- true - The lvalue-to-rvalue conversion is certainly not applied to the expressions
S::x
, 1, S::x
, (1, S::x)
. It can be argued that it is applied to b ? (1, S::x) : f(S::x)
(see below)
- or false (none of those expressions are discarded-value expressions)
It is unclear whether or not initialization applies the lvalue-to-rvalue conversion. One can argue that the "value of the lvalue-expression" must be read in order to initialize the int
from an expression of type int const
. If we follow this assumption, then the lvalue-to-rvalue conversion is applied to b ? (1, S::x) : f(S::X)
. The first occurrence of S::x
is an element of the set of potential results of that expression (see the first part of this answer). Hence, Bullet point 3.0 of the above applies, and S::x
is not odr-used through the first occurrence.
You can find a lot of information on lvalue-to-rvalue conversion in initializations in the Q&A Does initialization entail lvalue-to-rvalue conversion? Is int x = x;
UB?. The situation might be a bit easier here, since the rhs has type int const
. This might require a qualification conversion, which expects a prvalue operand (this probably invokes the lvalue-to-rvalue conversion implicitly).