Reference capture of structured bindings (original) (raw)
Jump to Table of Contents Pop Out Sidebar
P1381R1
Reference capture of structured bindings
Published Proposal, 2019-02-22
This version:
Author:
Audience:
EWG
Project:
ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
Abstract
Analysis of reference capture of structured bindings.
Table of Contents
1. Changes
Revision 1:
- Add proposed wording as reviewed by Core
2. Introduction
In San Diego, EWG decided to allow capture by value for structured bindings. The following polls were taken:
- Capturing structured bindings by value either by default capture or by name capture always copies the value of the structured binding
| SF | F | N | A | SA |
| 12 | 14| 1 | 2 | 3 |
- Capturing structured bindings by value, either by default capture or by named capture, always copies whole/underlying object
| SF | F | N | A | SA |
| 2 | 3 | 5 | 6 | 8 |
- Capturing structured bindings by value by default capture captures the underlying object and by named capture only the named bindings.
| SF | F | N | A | SA |
| 0 | 3 | 3 | 8 | 14 |
The first poll got consensus, thus allowing:
struct Foo { int a; }; void f() { auto[a] = Foo(); auto f1 = [a] { return a; }; // ok, captures 'a' auto f2 = [=] { return a; }; // ok, captures 'a' }
However, there were concerns about capturing structured bindings by reference.
3. Problem
Bit-fields.
struct Foo { int a : 1; }; void f() { auto[a] = Foo(); // 'a' is a bit-field!
auto f1 = [&a] { return a; }; // capturing a bit-field by reference?!?
}
Since EWG agreed on the behavior of by-value capture of structured bindings, it would make sense to allow by-reference capture to behave the same, i.e. that only a reference to the bindings capture are formed and not to the underlying object.
4. What can we do?
Bit-fields have some funny behavior. There isn’t a type for them for example. One important difference is that you can’t take the address of a bit-field, so it follows that a reference to a bit-field is also ill-formed.
struct Foo { int a : 1; }; void f(int&);
int main() { Foo foo; f(foo.a); // ill-formed, reference to bit-field }
As such, I’m proposing that reference capture of a bit-field remains ill-formed. I see no reason why this proposal should change this.
struct Foo { int a : 1; int b; };
int main() { auto[a, b] = Foo();
auto f1 = [&] { return a; }; // still ill-formed with this proposal auto f2 = [&a = a] { return a; }; // always was ill-formed; no change auto f3 = [&a] { return a; }; // still ill-formed with this proposal
auto g1 = [&] { return b; }; // previously ill-formed; well-formed with this proposal auto g2 = [&b = b] { return b; }; // always was well-formed; no change auto g3 = [&b] { return b; }; // previously ill-formed; well-formed with this proposal }
Every other structured binding has a "valid" type (a type which we can reference); bit-fields are the only exception to this rule.
5. Proposed wording
This wording is based on P1091r3.
Change [expr.prim.lambda.capture]p12 (7.5.5.2) as follows:
A bit-field
, a structured binding,or a member of an anonymous union shall not be captured by reference.