Title
constexpr structured bindings with prvalues from tuples
Status
ready
Section
9.7 [dcl.struct.bind]
Submitter
Barry Revzin

Created on 2025-11-14.00:00:00 last changed 1 week ago

Messages

Date: 2026-03-27.13:08:23

Proposed resolution (approved by CWG 2026-03-27):

Change in 9.7 [dcl.struct.bind] paragraph 7 as follows:

... Given the type Ti designated by std::tuple_element<i, E>::type and the type Ui designated by either Ti & or Ti && where Ui is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise, defined as Ti if the initializer is a prvalue, as "lvalue reference to Ti" if the initializer is an lvalue, or as "rvalue reference to Ti" otherwise, variables are introduced with unique names ri as follows:
  S Ui ri = initializer ;
Date: 2026-03-27.09:41:47

(From submission #807.)

In the tuple case, e.get<i>() or get<i>(e) is used, but the case that those function calls return a prvalue is not properly handled for constexpr. For example, P1789R3 (Library Support for Expansion Statements) added constexpr T get(integer_sequence<...>).

Specific example:

  constexpr auto [...Is] = std::make_index_sequence<2>();

decomposes into:

  constexpr auto e = std::integer_sequence<size_t, 0, 1>();
  constexpr size_t&& Is#0 = 0;   // temporary is mutable
  constexpr size_t&& Is#1 = 1;

Structured bindings for prvalues should use a non-reference type.

History
Date User Action Args
2026-03-27 13:08:23adminsetstatus: open -> ready
2025-11-23 22:29:16adminsetmessages: + msg8419
2025-11-14 00:00:00admincreate