Core issue 1651

131 views
Skip to first unread message

Columbo

unread,
Mar 13, 2016, 8:10:15 PM3/13/16
to ISO C++ Standard - Discussion
The resolution of issues 616 and 1213, making the result of a member access or subscript expression applied to a prvalue an xvalue, means that binding a reference to such a subobject of a temporary does not extend the temporary's lifetime.

Why is that? Is a reference only said to "bind to a temporary" if its initializer is a prvalue? Or can a temporary (or its subobject) only be designated as such if done via a prvalue? The latter is vaguely implied by the definition of rvalues in [basic.lval]/(1.4).

David Krauss

unread,
Mar 14, 2016, 12:51:18 AM3/14/16
to std-dis...@isocpp.org

On 2016–03–14, at 8:10 AM, Columbo <r....@gmx.net> wrote:

The resolution of issues 616 and 1213, making the result of a member access or subscript expression applied to a prvalue an xvalue, means that binding a reference to such a subobject of a temporary does not extend the temporary's lifetime.

Why is that? Is a reference only said to "bind to a temporary" if its initializer is a prvalue? Or can a temporary (or its subobject) only be designated as such if done via a prvalue? The latter is vaguely implied by the definition of rvalues in [basic.lval]/(1.4).

Yes, it’s ambiguous. The normative text provides no way to determine whether a value refers to a temporary, so the prevailing interpretation is to use prvalue category as a proxy for temporary-ness.

Johannes Schaub

unread,
Mar 14, 2016, 3:40:32 AM3/14/16
to std-dis...@isocpp.org

Yes, this was one of the reasons why I suggested the notion of temporary expression. In this case the member access expression would be a temporary expression, with the temporary object of the object expression as its temporary object. T().a.b for instance (for nonreference members) has a single temporary object and three temporary expressions T(), T().a and T().a.b . Notice that the latter two expressions refer to non temporary objects. Currently the Standard has an ugly workaround special case for that (without checking now, I do believe however that the special case would still work if the member access expression is made an xvalue).

David Krauss

unread,
Mar 14, 2016, 6:26:49 AM3/14/16
to std-dis...@isocpp.org
On 2016–03–14, at 3:40 PM, 'Johannes Schaub' via ISO C++ Standard - Discussion <std-dis...@isocpp.org> wrote:

Yes, this was one of the reasons why I suggested the notion of temporary expression. In this case the member access expression would be a temporary expression, with the temporary object of the object expression as its temporary object.


Right. Unfortunately, temporary expressions do not map 1:1 to temporary objects. Rather than label expressions as either “temporary expressions” or “not-temporary-expressions,” it’s more general to define a set of inner prvalues reachable from any given expression. See my proposals N4221 and P0066 for more depth.

Johannes Schaub

unread,
Mar 14, 2016, 12:43:04 PM3/14/16
to std-dis...@isocpp.org

Thanks, I will look into your proposals when I get some time. However, the purpose of the temporary expression notion is not to have an 1:1 mapping with temporary objects. Its more of a n:1 mapping from expressions to temporary objects. For a symbolic execution of a conditional expression, you can also have a set of possible temporary objects belonging to temporary conditional expression. This is nothing special about temporary expressions though and this fact doesn't need to be modeled afaics.

Richard Smith

unread,
Mar 14, 2016, 2:10:02 PM3/14/16
to std-dis...@isocpp.org
The "or subobject thereof" makes it clear that the intent is not to
use the prvalue-ness of the expression bound to the reference. In
practice, implementations do lifetime-extend across member access and
some other transformations. Core issue 1299 provides wording
explaining precisely when an expression is a temporary expression, and
which temporary objects are lifetime-extended by a reference binding
of a temporary expression.

David Krauss

unread,
Mar 14, 2016, 8:52:26 PM3/14/16
to std-dis...@isocpp.org

> On 2016–03–15, at 2:09 AM, Richard Smith <ric...@metafoo.co.uk> wrote:
>
> On Sun, Mar 13, 2016 at 9:51 PM, David Krauss <pot...@gmail.com> wrote:
>>
>> Yes, it’s ambiguous. The normative text provides no way to determine whether
>> a value refers to a temporary, so the prevailing interpretation is to use
>> prvalue category as a proxy for temporary-ness.
>
> The "or subobject thereof" makes it clear that the intent is not to
> use the prvalue-ness of the expression bound to the reference.

At the time “or subobject thereof” was added, prvalues could refer to subobjects.

> In
> practice, implementations do lifetime-extend across member access and
> some other transformations.

… and supporting this sometimes delays implementations from using correct value categories in internal representation. When implementing P0066, I changed a bunch of prvalues to xvalues in Clang’s parser.

> Core issue 1299 provides wording
> explaining precisely when an expression is a temporary expression, and
> which temporary objects are lifetime-extended by a reference binding
> of a temporary expression.

Last I checked, it did assume that there was one temporary per expression, which doesn’t cover aggregate initialization.

Richard Smith

unread,
Mar 14, 2016, 9:31:55 PM3/14/16
to std-dis...@isocpp.org
If an aggregate has a reference member, a temporary bound to that
member is extended to the lifetime of *that* reference (which may in
turn have its lifetime extended by a surrounding reference).
Reply all
Reply to author
Forward
0 new messages