<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>pattern_matching</title>
  <style type="text/css">
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
  </style>
  <style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
  { position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
  { content: attr(data-line-number);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; pointer-events: all; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {  }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<h1 id="pattern-matching">Pattern Matching</h1>
<ul>
<li>Document number: P1308R0</li>
<li>Date: 2018-10-07</li>
<li>Reply-to: David Sankel &lt;dsankel@bloomberg.net&gt;, Dan Sarginson&lt;dsarginson@bloomberg.net&gt;, Sergei Murzin&lt;smurzin@bloomberg.net&gt;</li>
<li>Audience: Evolution</li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>Pattern matching improves code readability, makes the language easier to use, and prevent common mishaps.</p>
<h2 id="history">History</h2>
<p><em>P1308R0</em>. Initial version of this paper which was extracted from <a href="http://wg21.link/p0095r1">P0095R1</a>. Disambiguation between a expression <code>inspect</code> and a statement <code>inspect</code> is now based on the context in which it appears. Parentheses are now used to disambiguate between <code>constexpr</code> expressions and new identifiers. Matching may now be used on inheritance hierarchies. Matching against constexpr expressions has been extended to all types instead of only supporting integral and enum types. Additionally a new <a href="#open-design-questions">Open Design Questions</a> section was added.</p>
<h2 id="introduction">Introduction</h2>
<p>There is general agreement that pattern matching would make C++ programmers more productive. However, a design that has the elegance of a functional language, but with the performance and utility of a systems language is not forthcoming. Add to that the requirements of backwards compatibility and consistency with the rest of C++, and we’ve got quite a challenging problem.</p>
<p>This paper presents a design for pattern matching that the authors feel has the right mix of syntactic elegance, low-level performance, and consistency with other language features.</p>
<figure>
<figcaption>
Figure 1: Switching an enum.
</figcaption>
<table border="1">
<tr>
<th>
before
</th>
<th>
after
</th>
</tr>
<tr>
<td colspan="2">
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="kw">enum</span> color { red, yellow, green, blue };</a></code></pre></div>
</td>
</tr>
<td valign="top">
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb2-1" data-line-number="1"><span class="at">const</span> Vec3 opengl_color = [&amp;c] {</a>
<a class="sourceLine" id="cb2-2" data-line-number="2">  <span class="cf">switch</span>(c) {</a>
<a class="sourceLine" id="cb2-3" data-line-number="3">    <span class="cf">case</span> red:</a>
<a class="sourceLine" id="cb2-4" data-line-number="4">      <span class="cf">return</span> Vec3(<span class="fl">1.0</span>, <span class="fl">0.0</span>, <span class="fl">0.0</span>);</a>
<a class="sourceLine" id="cb2-5" data-line-number="5">      <span class="cf">break</span>;</a>
<a class="sourceLine" id="cb2-6" data-line-number="6">    <span class="cf">case</span> yellow:</a>
<a class="sourceLine" id="cb2-7" data-line-number="7">      <span class="cf">return</span> Vec3(<span class="fl">1.0</span>, <span class="fl">1.0</span>, <span class="fl">0.0</span>);</a>
<a class="sourceLine" id="cb2-8" data-line-number="8">      <span class="cf">break</span>;</a>
<a class="sourceLine" id="cb2-9" data-line-number="9">    <span class="cf">case</span> green:</a>
<a class="sourceLine" id="cb2-10" data-line-number="10">      <span class="cf">return</span> Vec3(<span class="fl">0.0</span>, <span class="fl">1.0</span>, <span class="fl">0.0</span>);</a>
<a class="sourceLine" id="cb2-11" data-line-number="11">      <span class="cf">break</span>;</a>
<a class="sourceLine" id="cb2-12" data-line-number="12">    <span class="cf">case</span> blue:</a>
<a class="sourceLine" id="cb2-13" data-line-number="13">      <span class="cf">return</span> Vec3(<span class="fl">0.0</span>, <span class="fl">0.0</span>, <span class="fl">1.0</span>);</a>
<a class="sourceLine" id="cb2-14" data-line-number="14">      <span class="cf">break</span>;</a>
<a class="sourceLine" id="cb2-15" data-line-number="15">    <span class="cf">default</span>:</a>
<a class="sourceLine" id="cb2-16" data-line-number="16">      <span class="bu">std::</span>abort();</a>
<a class="sourceLine" id="cb2-17" data-line-number="17">  }();</a></code></pre></div>
</td>
<td valign="top">
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="at">const</span> Vec3 opengl_color =</a>
<a class="sourceLine" id="cb3-2" data-line-number="2">  inspect(c) {</a>
<a class="sourceLine" id="cb3-3" data-line-number="3">    red    =&gt; Vec3(<span class="fl">1.0</span>, <span class="fl">0.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb3-4" data-line-number="4">    yellow =&gt; Vec3(<span class="fl">1.0</span>, <span class="fl">1.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb3-5" data-line-number="5">    green  =&gt; Vec3(<span class="fl">0.0</span>, <span class="fl">1.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb3-6" data-line-number="6">    blue   =&gt; Vec3(<span class="fl">0.0</span>, <span class="fl">0.0</span>, <span class="fl">1.0</span>)</a>
<a class="sourceLine" id="cb3-7" data-line-number="7">  };</a></code></pre></div>
</td>
</tr>
</table>
</figure>
<figure>
<figcaption>
Figure 2: <code>struct</code> inspection
</figcaption>
<table border="1">
<tr>
<th>
before
</th>
<th>
after
</th>
</tr>
<tr>
<td colspan="2">
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb4-1" data-line-number="1"><span class="kw">struct</span> player {</a>
<a class="sourceLine" id="cb4-2" data-line-number="2">  <span class="bu">std::</span>string name;</a>
<a class="sourceLine" id="cb4-3" data-line-number="3">  <span class="dt">int</span> hitpoints;</a>
<a class="sourceLine" id="cb4-4" data-line-number="4">  <span class="dt">int</span> lives;</a>
<a class="sourceLine" id="cb4-5" data-line-number="5">};</a></code></pre></div>
</td>
</tr>
<td valign="top">
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="dt">void</span> takeDamage(player &amp;p) {</a>
<a class="sourceLine" id="cb5-2" data-line-number="2">  <span class="cf">if</span>(p.hitpoints == <span class="dv">0</span> &amp;&amp; p.lives == <span class="dv">0</span>)</a>
<a class="sourceLine" id="cb5-3" data-line-number="3">    gameOver();</a>
<a class="sourceLine" id="cb5-4" data-line-number="4">  <span class="cf">else</span> <span class="cf">if</span>(p.hitpoints == <span class="dv">0</span>) {</a>
<a class="sourceLine" id="cb5-5" data-line-number="5">    p.hitpoints = <span class="dv">10</span>;</a>
<a class="sourceLine" id="cb5-6" data-line-number="6">    p.lives--;</a>
<a class="sourceLine" id="cb5-7" data-line-number="7">  }</a>
<a class="sourceLine" id="cb5-8" data-line-number="8">  <span class="cf">else</span> <span class="cf">if</span>(p.hitpoints &lt;= <span class="dv">3</span>) {</a>
<a class="sourceLine" id="cb5-9" data-line-number="9">    p.hitpoints--;</a>
<a class="sourceLine" id="cb5-10" data-line-number="10">    messageAlmostDead();</a>
<a class="sourceLine" id="cb5-11" data-line-number="11">  }</a>
<a class="sourceLine" id="cb5-12" data-line-number="12">  <span class="cf">else</span> {</a>
<a class="sourceLine" id="cb5-13" data-line-number="13">    p.hitpoints--;</a>
<a class="sourceLine" id="cb5-14" data-line-number="14">  }</a>
<a class="sourceLine" id="cb5-15" data-line-number="15">}</a></code></pre></div>
</td>
<td valign="top">
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb6-1" data-line-number="1"><span class="dt">void</span> takeDamage(player &amp;p) {</a>
<a class="sourceLine" id="cb6-2" data-line-number="2">  inspect(p) {</a>
<a class="sourceLine" id="cb6-3" data-line-number="3">    [hitpoints:   <span class="dv">0</span>, lives:<span class="dv">0</span>]   =&gt; gameOver();</a>
<a class="sourceLine" id="cb6-4" data-line-number="4">    [hitpoints:hp<span class="er">@</span><span class="dv">0</span>, lives:l]   =&gt; hp=<span class="dv">10</span>, l--;</a>
<a class="sourceLine" id="cb6-5" data-line-number="5">    [hitpoints:hp] <span class="cf">if</span> (hp &lt;= <span class="dv">3</span>) =&gt; { hp--; messageAlmostDead(); }</a>
<a class="sourceLine" id="cb6-6" data-line-number="6">    [hitpoints:hp] =&gt; hp--;</a>
<a class="sourceLine" id="cb6-7" data-line-number="7">  }</a>
<a class="sourceLine" id="cb6-8" data-line-number="8">}</a></code></pre></div>
</td>
</tr>
</table>
</figure>
<h2 id="motivation">Motivation</h2>
<p>A well-designed pattern matching syntax makes simple problems simple, and enables programmers to express their solution in an intuitive way. The C++ language continuously evolves to allow us to deal with common tasks using constructs that abstract away much of the ‘how’ and allow us to focus on the ‘what’, and in this way complex comparison and selection semantics have not moved with the state of the art.</p>
<p>In the same way that smart pointers have allowed us to express our high-level intent without the risks associated with manual memory management, pattern matching will allow the programmer to clearly express their high-level goal without the tedious and potentially error-prone task of creating and testing deeply-nested conditional constructs.</p>
<p>As proposed, pattern matching is <em>teachable</em>: it can be easily explained by one developer to another. Pattern matching is <em>reviewable</em>: it can be quickly read and verified to achieve the desired effect. Pattern matching is <em>powerful</em>: it can achieve a lot in a a small amount of terse syntax.</p>
<h2 id="pattern-matching-with-inspect">Pattern Matching With <code>inspect</code></h2>
<p>This section overviews the proposed pattern matching syntax and how it applies to integral types, arrays and non-union classes with public data members. A future paper will explore opt-in extensions for user-defined and STL types.</p>
<p>Pattern matching builds upon <a href="https://en.cppreference.com/w/cpp/language/structured_binding">structured binding</a> and follows the same name binding rules. The syntax is extended for pattern matching.</p>
<p>Some terms used in this paper:</p>
<ul>
<li>We use the word <code>struct</code> to mean non-union class with public data members.</li>
<li>The word “piece” is used to denote a field in such a <code>struct</code>.</li>
</ul>
<h3 id="pattern-matching-values">Pattern matching values</h3>
<p>The most basic pattern matching is that of values and that is the subject of this section. Before we get there, however, we need to distinguish between the two places pattern matching can occur. The first is in the statement context. This context is most useful when the intent of the pattern is to produce some kind of action. The <code>if</code> statement, for example, is used in this way. The second place pattern matching can occur is is in an expression context. Here the intent of the pattern is to produce a value of some sort. The ternary operator <code>?:</code>, for example, is used in this context. Upcoming examples will help clarify the distinction.</p>
<p>In the following example, we’re using <code>inspect</code> as a <em>statement</em> to check for certain values of an int <code>i</code>:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb7-1" data-line-number="1">inspect(i) {</a>
<a class="sourceLine" id="cb7-2" data-line-number="2">  <span class="dv">0</span> =&gt;</a>
<a class="sourceLine" id="cb7-3" data-line-number="3">    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;I can&#39;t say I&#39;m positive or negative on this syntax.&quot;</span></a>
<a class="sourceLine" id="cb7-4" data-line-number="4">              &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb7-5" data-line-number="5">  <span class="dv">6</span> =&gt;</a>
<a class="sourceLine" id="cb7-6" data-line-number="6">    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Perfect!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb7-7" data-line-number="7">  _ =&gt;</a>
<a class="sourceLine" id="cb7-8" data-line-number="8">    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;I don&#39;t know what to do with this.&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb7-9" data-line-number="9">}</a></code></pre></div>
<p>The <code>_</code> character is the pattern which always succeeds. It represents a wildcard or fallthrough. The above code is equivalent to the following <code>switch</code> statement.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="cf">switch</span>(i) {</a>
<a class="sourceLine" id="cb8-2" data-line-number="2">  <span class="cf">case</span> <span class="dv">0</span>:</a>
<a class="sourceLine" id="cb8-3" data-line-number="3">    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;I can&#39;t say I&#39;m positive or negative on this syntax.&quot;</span></a>
<a class="sourceLine" id="cb8-4" data-line-number="4">              &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb8-5" data-line-number="5">    <span class="cf">break</span>;</a>
<a class="sourceLine" id="cb8-6" data-line-number="6">  <span class="cf">case</span> <span class="dv">6</span>:</a>
<a class="sourceLine" id="cb8-7" data-line-number="7">    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Perfect!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb8-8" data-line-number="8">    <span class="cf">break</span>;</a>
<a class="sourceLine" id="cb8-9" data-line-number="9">  <span class="cf">default</span>:</a>
<a class="sourceLine" id="cb8-10" data-line-number="10">    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;I don&#39;t know what to do with this.&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb8-11" data-line-number="11">}</a></code></pre></div>
<p>In the following example, we’re using <code>inspect</code> as an <em>expression</em>, to match a pattern and produce a value based upon <code>c</code>, an instance of the <code>color</code> <code>enum</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="kw">enum</span> color { red, yellow, green, blue };</a>
<a class="sourceLine" id="cb9-2" data-line-number="2"></a>
<a class="sourceLine" id="cb9-3" data-line-number="3"><span class="co">// elsewhere...</span></a>
<a class="sourceLine" id="cb9-4" data-line-number="4"></a>
<a class="sourceLine" id="cb9-5" data-line-number="5"><span class="at">const</span> Vec3 opengl_color = inspect(c) {</a>
<a class="sourceLine" id="cb9-6" data-line-number="6">                            red    =&gt; Vec3(<span class="fl">1.0</span>, <span class="fl">0.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb9-7" data-line-number="7">                            yellow =&gt; Vec3(<span class="fl">1.0</span>, <span class="fl">1.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb9-8" data-line-number="8">                            green  =&gt; Vec3(<span class="fl">0.0</span>, <span class="fl">1.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb9-9" data-line-number="9">                            blue   =&gt; Vec3(<span class="fl">0.0</span>, <span class="fl">0.0</span>, <span class="fl">1.0</span>)</a>
<a class="sourceLine" id="cb9-10" data-line-number="10">                          };</a></code></pre></div>
<p>Note that the cases do not end in a semicolon when appearing in an expression context.</p>
<p>It is also important to note that if an <code>inspect</code> expression does not have a matching pattern, an <code>std::no_match</code> exception is thrown. This differs from <code>inspect</code> statements which simply move on to the next statement if no pattern matches.</p>
<p>All we’ve seen so far is a condensed and safer <code>switch</code> syntax which can also be used in expressions of any type (<code>==</code>-comparison is used). Pattern matching’s real power comes when we use more complex patterns. We’ll see some of that below.</p>
<h3 id="pattern-matching-structs">Pattern matching structs</h3>
<p>Pattern matching <code>struct</code>s in isolation isn’t all that interesting: they merely bind new identifiers to each of the fields.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb10-1" data-line-number="1"><span class="kw">struct</span> player {</a>
<a class="sourceLine" id="cb10-2" data-line-number="2">  <span class="bu">std::</span>string name;</a>
<a class="sourceLine" id="cb10-3" data-line-number="3">  <span class="dt">int</span> hitpoints;</a>
<a class="sourceLine" id="cb10-4" data-line-number="4">  <span class="dt">int</span> coins;</a>
<a class="sourceLine" id="cb10-5" data-line-number="5">};</a></code></pre></div>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb11-1" data-line-number="1"><span class="dt">void</span> log_player( <span class="at">const</span> player &amp; p ) {</a>
<a class="sourceLine" id="cb11-2" data-line-number="2">  inspect(p) {</a>
<a class="sourceLine" id="cb11-3" data-line-number="3">    [n,h,c]</a>
<a class="sourceLine" id="cb11-4" data-line-number="4">      =&gt; <span class="bu">std::</span>cout &lt;&lt; n &lt;&lt; <span class="st">&quot; has &quot;</span> &lt;&lt; h &lt;&lt; <span class="st">&quot; hitpoints and &quot;</span> &lt;&lt; c &lt;&lt; <span class="st">&quot; coins.&quot;</span>;</a>
<a class="sourceLine" id="cb11-5" data-line-number="5">  }</a>
<a class="sourceLine" id="cb11-6" data-line-number="6">}</a></code></pre></div>
<p><code>n</code>, <code>h</code>, and <code>c</code> are “bound” to their underlying values in a similar way to structured bindings. See <a href="https://en.cppreference.com/w/cpp/language/structured_binding">structured binding</a> for more information on what it means to bind a value.</p>
<p><code>struct</code> patterns aren’t limited to binding new identifiers though. We can instead use a nested pattern as in the following example.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb12-1" data-line-number="1"><span class="dt">void</span> get_hint( <span class="at">const</span> player &amp; p ) {</a>
<a class="sourceLine" id="cb12-2" data-line-number="2">  inspect( p ) {</a>
<a class="sourceLine" id="cb12-3" data-line-number="3">    [_, <span class="dv">1</span>, _] =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;You&#39;re almost destroyed. Give up!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb12-4" data-line-number="4">    [_,<span class="dv">10</span>,<span class="dv">10</span>] =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;I need the hints from you!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb12-5" data-line-number="5">    [_, _,<span class="dv">10</span>] =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more hitpoints!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb12-6" data-line-number="6">    [_,<span class="dv">10</span>, _] =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more ammo!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb12-7" data-line-number="7">    [n, _, _] =&gt; <span class="cf">if</span>( n != <span class="st">&quot;The Bruce Dickenson&quot;</span> )</a>
<a class="sourceLine" id="cb12-8" data-line-number="8">                   <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more hitpoints and ammo!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb12-9" data-line-number="9">                 <span class="cf">else</span></a>
<a class="sourceLine" id="cb12-10" data-line-number="10">                   <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;More cowbell!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb12-11" data-line-number="11">  }</a>
<a class="sourceLine" id="cb12-12" data-line-number="12">}</a></code></pre></div>
<p>While the above code is certainly condensed, it lacks clarity. It is tedious to remember the ordering of a <code>struct</code>’s fields. Not all is lost, however. Alternatively we can match using field names.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb13-1" data-line-number="1"><span class="dt">void</span> get_hint( <span class="at">const</span> player &amp; p ) {</a>
<a class="sourceLine" id="cb13-2" data-line-number="2">  inspect(p) {</a>
<a class="sourceLine" id="cb13-3" data-line-number="3"></a>
<a class="sourceLine" id="cb13-4" data-line-number="4">    [hitpoints:<span class="dv">1</span>]</a>
<a class="sourceLine" id="cb13-5" data-line-number="5">      =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;You&#39;re almost destroyed. Give up!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb13-6" data-line-number="6"></a>
<a class="sourceLine" id="cb13-7" data-line-number="7">    [hitpoints:<span class="dv">10</span>, coins:<span class="dv">10</span>]</a>
<a class="sourceLine" id="cb13-8" data-line-number="8">      =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;I need the hints from you!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb13-9" data-line-number="9"></a>
<a class="sourceLine" id="cb13-10" data-line-number="10">    [coins:<span class="dv">10</span>]</a>
<a class="sourceLine" id="cb13-11" data-line-number="11">      =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more hitpoints!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb13-12" data-line-number="12"></a>
<a class="sourceLine" id="cb13-13" data-line-number="13">    [hitpoints:<span class="dv">10</span>]</a>
<a class="sourceLine" id="cb13-14" data-line-number="14">      =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more ammo!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb13-15" data-line-number="15"></a>
<a class="sourceLine" id="cb13-16" data-line-number="16">    [name:n]</a>
<a class="sourceLine" id="cb13-17" data-line-number="17">      =&gt; <span class="cf">if</span>( n != <span class="st">&quot;The Bruce Dickenson&quot;</span> )</a>
<a class="sourceLine" id="cb13-18" data-line-number="18">           <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more hitpoints and ammo!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb13-19" data-line-number="19">         <span class="cf">else</span></a>
<a class="sourceLine" id="cb13-20" data-line-number="20">           <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;More cowbell!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb13-21" data-line-number="21">  }</a>
<a class="sourceLine" id="cb13-22" data-line-number="22">}</a></code></pre></div>
<p>Finally, our patterns can incorporate guards through use of an if clause. The last pattern in the above function can be replaced with the following two patterns:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb14-1" data-line-number="1">[name:n] <span class="cf">if</span>( n == <span class="st">&quot;The Bruce Dickenson&quot;</span> ) =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;More cowbell!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb14-2" data-line-number="2">_ =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more hitpoints and ammo!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a></code></pre></div>
<h4 id="alternative-field-matching-syntax">Alternative field matching syntax</h4>
<p>With the addition of designated initialization to C++ with <a href="http://wg21.link/p0329">P0329</a>, it may be interesting to use similar <code>.</code> syntax for matching by field name. With this approach the above example would look as follows:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb15-1" data-line-number="1"><span class="dt">void</span> get_hint( <span class="at">const</span> player &amp; p ) {</a>
<a class="sourceLine" id="cb15-2" data-line-number="2">  inspect(p) {</a>
<a class="sourceLine" id="cb15-3" data-line-number="3"></a>
<a class="sourceLine" id="cb15-4" data-line-number="4">    [.hitpoints <span class="dv">1</span>]</a>
<a class="sourceLine" id="cb15-5" data-line-number="5">      =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;You&#39;re almost destroyed. Give up!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb15-6" data-line-number="6"></a>
<a class="sourceLine" id="cb15-7" data-line-number="7">    [.hitpoints <span class="dv">10</span>, .coins <span class="dv">10</span>]</a>
<a class="sourceLine" id="cb15-8" data-line-number="8">      =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;I need the hints from you!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb15-9" data-line-number="9"></a>
<a class="sourceLine" id="cb15-10" data-line-number="10">    [.coins <span class="dv">10</span>]</a>
<a class="sourceLine" id="cb15-11" data-line-number="11">      =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more hitpoints!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb15-12" data-line-number="12"></a>
<a class="sourceLine" id="cb15-13" data-line-number="13">    [.hitpoints <span class="dv">10</span>]</a>
<a class="sourceLine" id="cb15-14" data-line-number="14">      =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more ammo!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb15-15" data-line-number="15"></a>
<a class="sourceLine" id="cb15-16" data-line-number="16">    [.name n]</a>
<a class="sourceLine" id="cb15-17" data-line-number="17">      =&gt; <span class="cf">if</span>( n != <span class="st">&quot;The Bruce Dickenson&quot;</span> )</a>
<a class="sourceLine" id="cb15-18" data-line-number="18">           <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Get more hitpoints and ammo!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb15-19" data-line-number="19">         <span class="cf">else</span></a>
<a class="sourceLine" id="cb15-20" data-line-number="20">           <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;More cowbell!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb15-21" data-line-number="21">  }</a>
<a class="sourceLine" id="cb15-22" data-line-number="22">}</a></code></pre></div>
<p>We omit usage of <code>=</code> to make it less likely the pattern match will be confused with an assignment.</p>
<h3 id="pattern-matching-arrays">Pattern matching arrays</h3>
<p>Similar to structured binding, we can define pattern matching for fixed-size arrays, by binding all elements in order.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb16-1" data-line-number="1"><span class="at">const</span> <span class="dt">int</span> dimensions[<span class="dv">3</span>] = { <span class="dv">1</span>, <span class="dv">4</span>, <span class="dv">2</span> };</a>
<a class="sourceLine" id="cb16-2" data-line-number="2"></a>
<a class="sourceLine" id="cb16-3" data-line-number="3">inspect(dimensions) {</a>
<a class="sourceLine" id="cb16-4" data-line-number="4">  [x, _, _] <span class="cf">if</span> (x &gt; <span class="dv">10</span>)</a>
<a class="sourceLine" id="cb16-5" data-line-number="5">    =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;First dimension must be less than 10!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb16-6" data-line-number="6">  [x, y, z] <span class="cf">if</span> (x + y + z &gt; <span class="dv">100</span>)</a>
<a class="sourceLine" id="cb16-7" data-line-number="7">    =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Sum of dimensions should be less than 100!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb16-8" data-line-number="8">}</a></code></pre></div>
<p>Similar to struct pattern matching above, we can also allow index-based binding of elements, instead of binding all elements.</p>
<h3 id="pattern-matching-pointers">Pattern matching pointers</h3>
<p>To allow pattern matching over pointer types, we introduce two patterns.</p>
<p><code>nullptr</code> pattern is used to match over a pointer that matches <code>p == nullptr</code> and we use <code>*&lt;pattern&gt;</code> pattern to match a type that has valid dereference operator and value that it points to matches <code>&lt;pattern&gt;</code>.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb17-1" data-line-number="1"><span class="kw">struct</span> node {</a>
<a class="sourceLine" id="cb17-2" data-line-number="2">  <span class="bu">std::</span>unique_ptr&lt;node&gt; left;</a>
<a class="sourceLine" id="cb17-3" data-line-number="3">  <span class="bu">std::</span>unique_ptr&lt;node&gt; right;</a>
<a class="sourceLine" id="cb17-4" data-line-number="4">  <span class="dt">int</span> value;</a>
<a class="sourceLine" id="cb17-5" data-line-number="5">};</a>
<a class="sourceLine" id="cb17-6" data-line-number="6"></a>
<a class="sourceLine" id="cb17-7" data-line-number="7"><span class="kw">template</span> &lt;<span class="kw">typename</span> Visitor&gt;</a>
<a class="sourceLine" id="cb17-8" data-line-number="8"><span class="dt">void</span> visit_leftmost(<span class="at">const</span> node&amp; node, Visitor&amp;&amp; visitor) {</a>
<a class="sourceLine" id="cb17-9" data-line-number="9">    inspect(node) {</a>
<a class="sourceLine" id="cb17-10" data-line-number="10">        [left: <span class="kw">nullptr</span>] =&gt; visitor(node);</a>
<a class="sourceLine" id="cb17-11" data-line-number="11">        [left: *left_child] =&gt; visit_leftmost(left_child,</a>
<a class="sourceLine" id="cb17-12" data-line-number="12">                                              <span class="bu">std::</span>forward&lt;Visitor&gt;(visitor));</a>
<a class="sourceLine" id="cb17-13" data-line-number="13">    }</a>
<a class="sourceLine" id="cb17-14" data-line-number="14">}</a></code></pre></div>
<p>A special dereferencing pattern syntax may seem strange for folks coming from a functional language. However, when we take into account that C++ uses pointers for all recursive structures it makes a lot of sense. Without it, the above pattern would be much more complicated.</p>
<h3 id="pattern-matching-class-hierarchies">Pattern matching class hierarchies</h3>
<p>Pattern matching must allow inspection of class hierarchies to extend the improvements in productivity and expressiveness to those working primarily within an object oriented paradigm.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb18-1" data-line-number="1"><span class="kw">class</span> Animal {</a>
<a class="sourceLine" id="cb18-2" data-line-number="2"><span class="kw">public</span>:</a>
<a class="sourceLine" id="cb18-3" data-line-number="3">  <span class="kw">virtual</span> <span class="dt">void</span> speak() <span class="at">const</span> = <span class="dv">0</span>;</a>
<a class="sourceLine" id="cb18-4" data-line-number="4">};</a>
<a class="sourceLine" id="cb18-5" data-line-number="5"></a>
<a class="sourceLine" id="cb18-6" data-line-number="6"><span class="kw">class</span> Cat : <span class="kw">public</span> Animal {</a>
<a class="sourceLine" id="cb18-7" data-line-number="7"><span class="kw">public</span>:</a>
<a class="sourceLine" id="cb18-8" data-line-number="8">  <span class="kw">virtual</span> <span class="dt">void</span> speak() <span class="at">const</span> <span class="kw">override</span> {</a>
<a class="sourceLine" id="cb18-9" data-line-number="9">    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Meow from &quot;</span> &lt;&lt; name &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb18-10" data-line-number="10">  }</a>
<a class="sourceLine" id="cb18-11" data-line-number="11"></a>
<a class="sourceLine" id="cb18-12" data-line-number="12">  <span class="bu">std::</span>string name;</a>
<a class="sourceLine" id="cb18-13" data-line-number="13">};</a>
<a class="sourceLine" id="cb18-14" data-line-number="14"></a>
<a class="sourceLine" id="cb18-15" data-line-number="15"><span class="kw">class</span> Crow : <span class="kw">public</span> Animal {</a>
<a class="sourceLine" id="cb18-16" data-line-number="16"><span class="kw">public</span>:</a>
<a class="sourceLine" id="cb18-17" data-line-number="17">  <span class="kw">virtual</span> <span class="dt">void</span> speak() <span class="at">const</span> <span class="kw">override</span> {</a>
<a class="sourceLine" id="cb18-18" data-line-number="18">    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;Caaaw!&quot;</span> &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb18-19" data-line-number="19">  }</a>
<a class="sourceLine" id="cb18-20" data-line-number="20">};</a>
<a class="sourceLine" id="cb18-21" data-line-number="21"></a>
<a class="sourceLine" id="cb18-22" data-line-number="22"><span class="dt">void</span> listen(<span class="at">const</span> Animal &amp;a) {</a>
<a class="sourceLine" id="cb18-23" data-line-number="23">  inspect(a) {</a>
<a class="sourceLine" id="cb18-24" data-line-number="24">    Cat c<span class="er">@</span>[<span class="st">&quot;Fluffy&quot;</span>] =&gt; fluffySays(c.speak());</a>
<a class="sourceLine" id="cb18-25" data-line-number="25">    Cat [name] =&gt; storeNewCatName(name);</a>
<a class="sourceLine" id="cb18-26" data-line-number="26">    Crow c =&gt; <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;All crows say &quot;</span> &lt;&lt; c.speak() &lt;&lt; <span class="bu">std::</span>endl;</a>
<a class="sourceLine" id="cb18-27" data-line-number="27">  }</a>
<a class="sourceLine" id="cb18-28" data-line-number="28">}</a></code></pre></div>
<h3 id="order-of-pattern-evaluation">Order of pattern evaluation</h3>
<p>In order to keep code easy to read and understand we propose to keep order of pattern evaluation linear. Evaluation proceeds from the first to the last supplied pattern and the first acceptable pattern that matches causes evaluation to execute the associated expression and terminate the search.</p>
<p>For example, inspecting class hierarchies in this way will select the first acceptable match from the list of potential patterns. There is no concept of a ‘best’ or ‘better’ match.</p>
<h2 id="wording-skeleton">Wording Skeleton</h2>
<p>What follows is an incomplete wording for inspection presented for the sake of discussion.</p>
<h3 id="inspect-statement">Inspect Statement</h3>
<p><em>inspect-statement</em>:<br>  <code>inspect</code> <code>(</code> <em>expression</em> <code>)</code> <code>{</code> <em>inspect-statement-cases<sub>opt</sub></em> <code>}</code></p>
<p><em>inspect-statement-cases</em>:<br>  <em>inspect-statement-case</em> <em>inspect-statement-cases<sub>opt</sub></em></p>
<p><em>inspect-statement-case</em>:<br>  <em>guarded-inspect-pattern</em> <code>=&gt;</code> <em>statement</em></p>
<p>The identifiers in <em>inspect-pattern</em> are available in <em>statement</em>.</p>
<p>In the case that none of the patterns match the value, execution continues.</p>
<h3 id="inspect-expression">Inspect Expression</h3>
<p><em>inspect-expression</em>:<br>  <code>inspect</code> <code>(</code> <em>expression</em> <code>)</code> <code>{</code> <em>inspect-expression-cases<sub>opt</sub></em> <code>}</code></p>
<p><em>inspect-expression-cases</em>:<br>  <em>inspect-expression-case</em> <em>inspect-expression-cases<sub>opt</sub></em></p>
<p><em>inspect-expression-case</em>:<br>  <em>guarded-inspect-pattern</em> <code>=&gt;</code> <em>expression</em></p>
<p>The identifiers in <em>inspect-pattern</em> are available in <em>expression</em>.</p>
<p>In the case that none of the patterns match the value, a <code>std::no_match</code> exception is thrown.</p>
<h3 id="inspect-pattern">Inspect Pattern</h3>
<p><em>guarded-inspect-pattern</em>:<br>  <em>inspect-pattern</em> <em>guard<sub>opt</sub></em></p>
<p><em>guard</em>:<br>  <code>if</code> <code>(</code> <em>condition</em> <code>)</code></p>
<p><em>inspect-pattern</em>:<br>  <code>_</code><br>  <code>nullptr</code><br>  <code>*</code> <em>inspect-pattern</em> <br>  <em>identifier</em> ( <code>@</code> <code>(</code> <em>inspect-pattern</em> <code>)</code> )<sub>opt</sub><br>  <em>alternative-selector</em> <em>inspect-pattern</em> <br>  <code>(</code> <em>constant-expression</em> <code>)</code><br>  <em>constant-expression</em> <br>  <code>[</code> <em>tuple-like-patterns<sub>opt</sub></em> <code>]</code></p>
<h4 id="wildcard-pattern">Wildcard pattern</h4>
<p><em>inspect-pattern</em>:<br>  <code>_</code><br></p>
<p>The wildcard pattern matches any value and always succeeds.</p>
<h4 id="nullptr-pattern"><code>nullptr</code> pattern</h4>
<p><em>inspect-pattern</em>:<br>  <code>nullptr</code><br></p>
<p>The <code>nullptr</code> pattern matches values <code>v</code> where <code>v == nullptr</code>.</p>
<h4 id="dereference-pattern">Dereference pattern</h4>
<p><em>inspect-pattern</em>:<br>  <code>*</code> <em>inspect-pattern</em> <br></p>
<p>The dereferencing pattern matches values <code>v</code> where <code>*v</code> matches the nested pattern. Note that dereferencing the value occurs as part of the match.</p>
<h4 id="binding-pattern">Binding pattern</h4>
<p><em>inspect-pattern</em>:<br>  <em>identifier</em> ( <code>@</code> <code>(</code> <em>inspect-pattern</em> <code>)</code> )<sub>opt</sub><br></p>
<p>If <code>@</code> is not used, the binding pattern matches all values and binds the specified identifier to the value being matched. If <code>@</code> is used, the pattern is matched only if the nested pattern matches the value being matched.</p>
<h4 id="expression-pattern">Expression pattern</h4>
<p><em>inspect-pattern</em>:<br>  <em>constant-expression</em><br> <em>inspect-pattern</em>:<br>  <code>(</code> <em>inspect-pattern</em> <code>)</code><br></p>
<p>The expression pattern matches against all types supporting equality comparison. The pattern is valid if the matched type is the same as the <em>constant-expression</em> type. The pattern matches if the matched value is equal to the <em>constant-expression</em> value based on <code>==</code> comparison.</p>
<p>Note that the binding pattern takes precedence if there is ambiguity.</p>
<h4 id="tuple-like-patterns">Tuple-like patterns</h4>
<p><em>inspect-pattern</em>:<br>  <code>[</code> <em>tuple-like-patterns<sub>opt</sub></em> <code>]</code></p>
<p><em>tuple-like-patterns</em>:<br>  <em>sequenced-patterns</em><br>  <em>field-patterns</em></p>
<p><em>sequenced-patterns</em>:<br>  <em>inspect-pattern</em> (<code>,</code> <em>sequenced-patterns</em>)<sub>opt</sub></p>
<p><em>field-patterns</em>:<br>  <em>field-pattern</em> (<code>,</code> <em>field-patterns</em>)<sub>opt</sub></p>
<p><em>field-pattern</em>:<br>  <em>piece-selector</em> <code>:</code> <em>inspect-pattern</em></p>
<p><em>piece-selector</em>:<br>  <em>constant-expression</em><br>  <em>identifier</em></p>
<p>Tuple-like patterns come in two varieties: a sequence of patterns and field patterns.</p>
<p>A sequenced pattern is valid if the following conditions are true:</p>
<ol type="1">
<li>The matched type is either a <code>class</code> with all public member variables or has a valid extract operator. Say the number of variables or arguments to extract is <code>n</code>.</li>
<li>There are exactly <code>n</code> patterns in the sequence.</li>
<li>Each of the sequenced patterns is valid for the corresponding piece in the matched value.</li>
</ol>
<p>A field pattern is valid if the following conditions are true:</p>
<ol type="1">
<li>The matched type is either a <code>class</code> with all public member variables or has a valid extract operator.</li>
<li><em>piece-selector</em>s, if they are <em>constant-expression</em>, must have the same type as the extract operator’s <code>std::tuple_piece</code>s second template argument.</li>
<li><em>piece-selector</em>s, if they are <em>identifier</em>s, must correspond to field names in the <code>class</code> with all public member variables.</li>
<li>Each of the field patterns is valid for the the corresponding piece in the matched value.</li>
</ol>
<p>Both patterns match if the pattern for each piece matches its corresponding piece.</p>
<p>The <em>constant-expression</em> shall be a converted constant expression (5.20) of the type of the inspect condition’s extract piece discriminator. The <em>identifier</em> will correspond to a field name if inspect’s condition is an class or an identifier that is within scope of the class definition opting into the tuple-like pattern.</p>
<h2 id="design-choices">Design Choices</h2>
<h3 id="inspect-as-a-statement-and-an-expression"><code>inspect</code> as a statement and an expression</h3>
<p>If <code>inspect</code> were a statement-only, it could be used in expressions via. a lambda function. For example:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb19-1" data-line-number="1"><span class="at">const</span> Vec3 opengl_color = [&amp;c]{</a>
<a class="sourceLine" id="cb19-2" data-line-number="2">  inspect(c) {</a>
<a class="sourceLine" id="cb19-3" data-line-number="3">    red    =&gt; <span class="cf">return</span> Vec3(<span class="fl">1.0</span>, <span class="fl">0.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb19-4" data-line-number="4">    yellow =&gt; <span class="cf">return</span> Vec3(<span class="fl">1.0</span>, <span class="fl">1.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb19-5" data-line-number="5">    green  =&gt; <span class="cf">return</span> Vec3(<span class="fl">0.0</span>, <span class="fl">1.0</span>, <span class="fl">0.0</span>)</a>
<a class="sourceLine" id="cb19-6" data-line-number="6">    blue   =&gt; <span class="cf">return</span> Vec3(<span class="fl">0.0</span>, <span class="fl">0.0</span>, <span class="fl">1.0</span>)</a>
<a class="sourceLine" id="cb19-7" data-line-number="7">  } }();</a></code></pre></div>
<p>Because we expect that <code>inspect</code> expressions will be the most common use case, we feel the syntactic overhead and tie-in to another complex feature (lambdas) too much to ask from users.</p>
<h3 id="inspect-with-multiple-arguments"><code>inspect</code> with multiple arguments</h3>
<p>It is a straightforward extension of the above syntax to allow for inspecting multiple values at the same time.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb20-1" data-line-number="1">lvariant tree {</a>
<a class="sourceLine" id="cb20-2" data-line-number="2">  <span class="dt">int</span> leaf;</a>
<a class="sourceLine" id="cb20-3" data-line-number="3">  <span class="bu">std::</span>pair&lt; <span class="bu">std::</span>unique_ptr&lt;tree&gt;, <span class="bu">std::</span>unique_ptr&lt;tree&gt; &gt; branch;</a>
<a class="sourceLine" id="cb20-4" data-line-number="4">}</a>
<a class="sourceLine" id="cb20-5" data-line-number="5"></a>
<a class="sourceLine" id="cb20-6" data-line-number="6"><span class="dt">bool</span> sameStructure(<span class="at">const</span> tree&amp; lhs, <span class="at">const</span> tree&amp; rhs) {</a>
<a class="sourceLine" id="cb20-7" data-line-number="7">  <span class="cf">return</span> inspect(lhs, rhs) {</a>
<a class="sourceLine" id="cb20-8" data-line-number="8">           [leaf _, leaf _] =&gt; <span class="kw">true</span></a>
<a class="sourceLine" id="cb20-9" data-line-number="9">           [branch [*lhs_left, *lhs_right], branch [*rhs_left, *rhs_right]] </a>
<a class="sourceLine" id="cb20-10" data-line-number="10">             =&gt;    sameStructure(lhs_left , rhs_left)</a>
<a class="sourceLine" id="cb20-11" data-line-number="11">                &amp;&amp; samestructure(lhs_right, rhs_right)</a>
<a class="sourceLine" id="cb20-12" data-line-number="12">           _ =&gt; <span class="kw">false</span></a>
<a class="sourceLine" id="cb20-13" data-line-number="13">         };</a>
<a class="sourceLine" id="cb20-14" data-line-number="14">}</a></code></pre></div>
<p>It is our intent that the final wording will allow for such constructions.</p>
<h2 id="open-design-questions">Open Design Questions</h2>
<p>There is an open design questions that the authors would like feedback on from EWG.</p>
<h3 id="surface-syntax">Surface syntax</h3>
<p>Herb Sutter suggested that extending the existing <code>switch/case</code> syntax would be more desirable than introducing a new <code>inspect/=&gt;</code> syntax. For example, instead of ‘:’, a switch statement could use braces.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb21-1" data-line-number="1"><span class="cf">switch</span> (x) {</a>
<a class="sourceLine" id="cb21-2" data-line-number="2">  <span class="cf">case</span> A { <span class="co">/*A*/</span> }</a>
<a class="sourceLine" id="cb21-3" data-line-number="3">  <span class="cf">case</span> B { <span class="co">/*B*/</span> }</a>
<a class="sourceLine" id="cb21-4" data-line-number="4">  <span class="cf">default</span> { }</a>
<a class="sourceLine" id="cb21-5" data-line-number="5">}</a></code></pre></div>
<p><code>A</code> and <code>B</code> could, for example, be <em>inspect-pattern</em>s according to this proposal. The benefit would be that transitioning to a safer, more powerful switch is made easier. One drawback is that it may not be immediately obvious whether or not fallthrough is happening with a given switch statement.</p>
<h2 id="conclusion">Conclusion</h2>
<p>We conclude that pattern matching enables programmers to express their solution in more intuitive, uniform and simple way. Concentrating attention on ‘what’ rather than ‘how’, allowing to express control flows in lightweight and readable way.</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>Thanks to Vicente Botet Escribá, John Skaller, Dave Abrahams, Bjarne Stroustrup, Bengt Gustafsson, and the C++ committee as a whole for productive design discussions. Also, Yuriy Solodkyy, Gabriel Dos Reis, and Bjarne Stroustrup’s prior research into generalized pattern matching as a C++ library has been very helpful. Also thanks to Herb Sutter for providing feedback on this proposal.</p>
<h2 id="references">References</h2>
<ul>
<li>V. Botet Escribá. Product types access. P0327R0. WG21</li>
<li>V. Botet Escribá. Structured binding: customization points issues. P0326R0. WG21</li>
<li>D. Sankel. <a href="http://davidsankel.com/uncategorized/c-language-support-for-pattern-matching-and-variants/">C++ Langauge Support for Pattern Matching and Variants</a>. davidsankel.com.</li>
<li>Y. Solodkyy, G. Dos Reis, B. Stroustrup. <a href="http://www.stroustrup.com/OpenPatternMatching.pdf">Open Pattern Matching for C++</a>. GPCE 2013.</li>
</ul>
</body>
</html>
