About binding a const reference to a sub-object of a temporary

This is covered by CWG 1651:

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. 12.2 [class.temporary] should be
revised to ensure that it does.

The status quo is that only prvalues are treated as referring to temporaries – thus [class.temporary]/5 (“The second context is when a reference is bound to a temporary.”) is not considered applicable. Clang and GCC have not actually implemented issue 616’s resolution, though. center().x is treated as a prvalue by both. My best guess:

  • GCC simply didn’t react to any DRs yet, at all. It doesn’t extend lifetime when using scalar subobjects, because those are not covered by [dcl.init.ref]/(5.2.1.1). So the complete temporary object doesn’t need to live on (see aschelper’s answer), and it doesn’t, because the reference doesn’t bind directly. If the subobject is of class or array type, the reference binds directly, and GCC extends the temporary’s lifetime. This has been noted in DR 60297.

  • Clang recognizes member access and implemented the “new” lifetime extension rules already – it even handles casts. Technically speaking, this is not consistent with the way it handles value categories. However, it is more sensible and will be the correct behavior once the aforementioned DR is resolved.

I’d therefore say that GCC is correct by current wording, but current wording is defective and vague, and Clang already implemented the pending resolution to DR 1651, which is N3918. This paper covers the example very clearly:

If E1 is a temporary expression and E2 does not designate a
bit-field, then E1.E2 is a temporary expression.

center() is a temporary expression as per the paper’s wording for [expr.call]/11. Thus its modified wording in the aforementioned [class.temporary] /5 applies:

The second context is when a reference does not bind directly (8.5.3
dcl.init.ref) or is initialized with a temporary expression (clause 5). The corresponding temporary
object (if any) persists for the lifetime of the reference
except: […inapplicable exceptions…]

Voilà, we have lifetime extension. Note that “the corresponding temporary object” is not clear enough, one of the reasons for the proposal’s deferment; it will assuredly be adopted once it gets revised.


is an xvalue (but not a bit-field), class prvalue, array prvalue or function lvalue and “cv1 T1” is reference-compatible with “cv2 T2”, or […]

Indeed, GCC respects this fully and will extend lifetime if the subobject has array type.

Leave a Comment