title | document | date | audience | author | toc | toc-depth | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Disallow `_` Usage in C++20 for Pattern Matching in C++23 |
D1469R1 |
2019-02-19 |
Evolution |
|
true |
4 |
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.
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.
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.
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.
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.
[@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.
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-capturesthis
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] :::
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:
- family: Yasskin given: Jeffrey
- family: Bastien given: JF issued: year: 2018 URL: http://wg21.link/P1110R0
- 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:
- family: Tomazos given: Andrew URL: http://www.tomazos.com/actcd16.pdf