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:

https://wg21.link/p1381r1

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. 1 Changes
  2. 2 Introduction
  3. 3 Problem
  4. 4 What can we do?
  5. 5 Proposed wording

1. Changes

Revision 1:

2. Introduction

In San Diego, EWG decided to allow capture by value for structured bindings. The following polls were taken:

  1. 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 |

  1. 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 |

  1. 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.