Skip to content

Latest commit

 

History

History
158 lines (131 loc) · 5.34 KB

D1469R1.md

File metadata and controls

158 lines (131 loc) · 5.34 KB
title document date audience author toc toc-depth
Disallow `_` Usage in C++20 for Pattern Matching in C++23
D1469R1
2019-02-19
Evolution
name email
Sergei Murzin
<smurzin@bloomberg.net>
name email
Michael Park
<mcypark@gmail.com>
name email
David Sankel
<dsankel@bloomberg.net>
name email
Dan Sarginson
<dsarginson@bloomberg.net>
true
4

Introduction

We need to deprecate a rare usage of _ as an identifier in C++20 so it can be safely used for pattern matching [@P1371] which is targeting C++23. The issue is simple, we'd like structured binding code as in,

auto [a, _] = std::make_pair(3, 4);

to have _ represent a wildcard pattern instead of binding the identifier _. There are a few ways to do this and we suggest what we think is the ideal engineering approach.

Various Approaches

Use something besides _ (BAD)

Why is _ so important when ? is available? Languages with pattern matching almost universally use _ as a wildcard pattern and popular libraries in C++ (like Google Test) do the same. It would be awkward and somewhat embarrassing if C++ were to not use such a ubiquitous token. Furthermore, because _ has so much existing widespread use, we expect people to use _ anyway, and accidentally bind the _ identifier.

__ is another possiblility, but it is difficult to recognize as a double underscore with many fonts and we expect significant confusion were we to use this.

Deprecate all or most uses of _ as an identifier (WORSE)

Another option is to deprecate all or most uses of _ as an identifier. We could, for instance, deprecate references to _ identifiers declared in block-scope. The migration cost for this is unfortunately quite a steep one. There are more instances of the _ token than short in the wild according to [@ACTCD16]. Breaking all this code would be extremely costly for the C++ community.

Deprecate _ access when structured-binding bound (OKAY)

Finally, we could deprecate referencing _ identifiers that are bound as part of a structured binding. Because structured binding is a relatively new feature and most uses of _ as a structured binding identifier are expected to be wildcard uses anyway, the cost of fixing breakages would be low. This change to be a sweet spot for engineering value, but we need to act quickly if we want to take advantage of this for pattern matching in C++23.

Disallow _ access when structured-binding bound (GOOD)

Because usages of _ identifiers that are bound by structured binding are so rare, there is little engineering benefit in deprecating these usages instead of just making access illegal altogether. In fact, a deprecation period can actually increase cost as engineers (who ignore warnings) will have more opportunity to use _ identifiers bound by structured bindings.

Should we generalize this as in P1110R0?

[@P1110R0] suggests that we make something like the wildcard (_) pattern accessible in many other places than patterns (e.g. in an enumerator). The authors of this paper find questionable engineering value for many of these suggestions and have no opinion on others. Our primary focus is on parity between structured bindings and pattern matching.

Wording

Change in 7.5.4.1 [expr.prim.id.unqual] paragraph 2:

The result is the entity denoted by the identifier. [Use of the identifier _ to denote a structured binding is deprecated.]{.add} If the entity is a local entity...

Change in 7.5.5.2 [expr.prim.lambda.capture] paragraph 4:

The identifier in a simple-capture is looked up using the usual rules for unqualified name lookup (6.4.1); each such lookup shall find a local entity. [Use of the identifier _ in a simple-capture is deprecated if the identifier denotes a structured binding.]{.add} The simple-captures this and * this denote...

Insert a new subclause before D.2 [depr.capture.this]:

:::add

D.2 Use of _ as a structured binding [depr.uscore]

The ability to refer to a structured binding named _ is deprecated (7.5.4.1 [expr.prim.id.unqual], 7.5.5.2 [expr.prim.lambda.capture]). [Example:

| void f() { | int a[] = {2005, 7, 14}; | auto [x, _, z] = a; // ok | int y = _; // deprecated, reference to _ | [_](){}; // deprecated, capture of _ | }

-- end example] :::

Conclusion

Right now we have an opportunity to prevent mistakes being made by using the wildcard that everyone expects for pattern matching. Let's deprecate or disallow access to _ variables if they are bound by structured binding.


references:

  • id: P1110R0 citation-label: P1110R0 title: "A placeholder with no name" author:
  • id: P1371 citation-label: P1371 title: "Pattern Matching" author:
    • family: Murzin given: Sergei
    • family: Park given: Michael
    • family: Sankel given: David
    • family: Sarginson given: Dan issued: year: 2019 URL: http://wg21.link/P1371
  • id: ACTCD16 citation-label: ACTCD16 title: "Andrew's C/C++ Token Count Dataset 2016 (ACTCD16)" author: