Skip to content

CWG3149 [stmt.expand] Not handling rvalues in destructuring expansion statement #835

Description

@brevzin

Full name of submitter (unless configured in github; will be published with the issue): Liu Yanzuo

Reference (section label):[stmt.expand]

Link to reflector thread (if any): https://lists.isocpp.org/std-discussion/2026/01/3275.php

Issue description:

Right now, the wording for a destructuring expansion statement says that we create a possibly-constexpr structured binding declaration

auto&& [u_0, u_1, ..., u_N-1] = expansion_initializer;

And then each statement of the expansion statement is:

for_range_declaration = u_i;

As worded, u_i is always an lvalue. Which means that in an example like this:

auto f() -> std::tuple<int, int&, int&&>;

auto g() -> void {
  template for (auto&& elem : f()) {
    ;
  }
}

decltype(elem) is int& on each iteration. But the intent was that we would get int&& on the first and third iteration. This was never quite translated properly to the wording.

Suggested resolution: Something to the effect of:

for-range-declaration = ui get-expri;

Where get-expri is ui if either decltype(ui) is an lvalue reference type or expansion-initializer is an lvalue. Otherwise, std::move(ui).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions