P3817 — ref-qualifier

◀ back to the paper

Copy, or move?

The ref-qualifier decides — nothing else

The ref-qualifier decides the type of e

using does not change how e is formed — it is introduced exactly as it is today. So the ref-qualifier still picks its type, and that is what decides whether the assignment copies or moves.

No special-casing is required

This is the reason the proposal needs no rule of its own here: the existing machinery already gives the right answer.

The three cases

auto   [using x, y] = f();   // e owns the object    -> move from e
auto&  [using x, y] = f();   // e is an lvalue ref   -> copy from e
auto&& [using x, y] = f();   // e is either          -> copy or move from e

Why that is the right answer

auto gives e an owned object and makes it an xvalue, so the assignment moves from it. Nothing can be lost: e has no name, and the element moved from is exactly the one that got no binding.

Obj obj;  std::shared_ptr<A> b;   // Obj: int m0, shared_ptr<A> m1, int m2
auto [a, using b, c] = obj;       // e is a copy of obj; obj keeps all three
// a refers to e.m0, e.m1 is nullptr (it moved into b), c refers to e.m2

auto& gives e an lvalue naming an object that outlives the scope, so the assignment copies — a move would gut an object the caller still holds.

auto&& is one or the other, depending on what it bound to.