<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC
    "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
    "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
<html xml:lang='en' xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/1999/xhtml'>
<head><meta content='application/xhtml+xml;charset=utf-8' http-equiv='Content-type' /><title>Relaxed switch statement</title></head>
<body><!-- maruku -o switch.html switch.md --><style type='text/css'>
pre code { display: block; margin-left: 2em; }
ins { text-decoration: none; font-weight: bold; background-color: #A0FFA0 }
del { text-decoration: line-through; background-color: #FFA0A0 }
</style><table><tbody>
<tr><th>Doc. no.:</th>	<td>N3627</td></tr>
<tr><th>Date:</th>	<td>2013-02-07</td></tr>
<tr><th>Project:</th>	<td>Programming Language C++, Evolution Working Group</td></tr>
<tr><th>Reply-to:</th>	<td>Zhihao Yuan &lt;lichray at gmail dot com&gt;</td></tr>
</tbody></table>
<h1 id='relaxed_switch_statement'>Relaxed switch statement</h1>

<h2 id='motivation'>Motivation</h2>

<pre><code>switch (s) {
case &quot;add&quot;:
	// ...
}</code></pre>

<p>What is the first time you heard of that the <code>switch</code> statement only allows integers? The time you want something like this, I suppose? Well, we have reasons to place such a limitation before C++11, but now, we have <code>constexpr</code> constructors. We can trivially relax the expression inside the <code>switch</code> statement to cover more literal types.</p>

<h2 id='scope'>Scope</h2>

<p>Some C-like programming languages, like JavaScript, furtherly allows any expressions to be used in the <code>case</code> labels. This proposal does not include such a change, because the semantics of the <code>switch</code> statement has to be changed from &#8220;matching&#8221; (in any order) to &#8220;comparing from top to bottom&#8221; to satisfy the possible side-effects inside the <code>case</code> labels.</p>

<p>Although, with the proposed change, the comparison may rely on a user-defined <code>operator==</code> at runtime when matching a <code>case</code> label, but the same <code>operator==</code> has to be used at compile-time to ensure that all of the <code>case</code> are identical. So, the solution is to simply ill-form the use of a user-defined literal type without a <code>constexpr operator==</code> in the <code>switch</code> statement.</p>

<p>One benefit of having a side-effect-free matching is that the <code>case</code> labels can be matched in any order, hence, as an optimization, the labels can be sorted at compile-time to enable a binary search at runtime. &#8211; By Gabriel Dos Reis.</p>

<h2 id='examples'>Examples</h2>

<p>There are several control logics that can&#8217;t be achieved in a scalable way with an &#8220;if&#8230;else&#8221; chain, like fall-through:</p>

<pre><code>switch (s) {
case &quot;pre&quot;:
	// do something
case &quot;prefix&quot;:
	// do more things
	break;
}</code></pre>

<p>The code above requires <code>s</code> to be of a user-defined literal type. The perfect candidate (focusing on C++14) is &#8220;string_ref: a non-owning reference to a string&#8221;<a href='http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3512.html'>[N3512]</a>.</p>

<p>The uniform initialization is allowed in a <code>case</code> label. This idea is initially driven by &#8220;to allow implicit conversion from multiple values&#8221;.</p>

<pre><code>switch (e /* std::complex&lt;double&gt;, or std::array&lt;double, 2&gt; */) {
case { 1.0, 3.0 }:
	break;
}</code></pre>

<p>If the proposal &#8220;User-defined Literals for Standard Library Types&#8221;<a href='http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3402.pdf'>[N3402]</a> gets accepted, the syntax to <code>switch</code> on a <code>std::complex&lt;double&gt;</code> can be furtherly simplified:</p>

<pre><code>switch (e) {
case 1.0+3.0i:
	break;
}</code></pre>

<p>I personally suggest the <code>operator &quot;&quot;s(CharT const *, size_t)</code> to be assigned to the literal types, e.g., <code>string_ref</code> (or <code>string_view</code>, another possible name), so that we can match arbitrary strings with:</p>

<pre><code>switch (header) {
case &quot;MA\0GIC&quot;s:
	// file type determined
}</code></pre>

<p>The proposal &#8220;Relaxed switch statement&#8221; itself is fairly simple and does not depend on the proposals/suggestions motioned above.</p>

<h2 id='wording'>Wording</h2>

<p>Change in 4 conv paragraph 2:</p>

<blockquote>
<p>&#8211; When used in the expression of a <code>switch</code> statement<ins>, if the given
type is a class type implicitly convertible to an integral or enumeration
type</ins>. The destination type is integral (6.4).</p>
</blockquote>

<p>Change in 6.4 stmt.select paragraph 4:</p>

<blockquote>
<p>The value of a condition that is an initialized declaration in a statement other than a <code>switch</code> statement <ins>with the declared variable of integral or enumeration type, or of that
variable implicitly converted to integral or enumeration type,</ins> is the value of the declared variable contextually converted to <code>bool</code> (Clause 4). &#8230; The value of a condition that is an expression is the value of the expression, contextually converted to <code>bool</code> for statements other than <code>switch</code> <ins>with the expression of integral or enumeration type, or of that
expression implicitly converted to integral or enumeration type</ins>; if that conversion is ill-formed, the program is ill-formed. &#8230;</p>
</blockquote>

<p>Change in 6.4.2 stmt.switch paragraph 2:</p>

<blockquote>
<p>The condition <del>shall</del> <ins>can</ins> be of integral type, enumeration type, or of a class type for which a single non-explicit conversion function to integral or enumeration type exists (12.3). If the condition is of class type, the condition is converted by calling that conversion function, and the result of the conversion is used in place of the original condition for the remainder of this section. Integral promotions are performed. <ins>The promoted type is the destination type.</ins> <ins> The condition can also be of floating point type or a literal class
type which is not implicitly convertible to integral or enumeration type.
The type of the condition is the destination type.</ins> <del>*anything left in this paragraph*</del></p>
</blockquote>

<p>Add two new paragraphs after 6.4.2 stmt.switch paragraph 2:</p>

<blockquote>
<p>Any statement within the <code>switch</code> statement can be labeled with one or more <code>case</code> labels using one of the following syntax:</p>

<blockquote>
<p><strong><code>case</code></strong> <em>constant-expression</em> <strong><code>:</code></strong></p>
</blockquote>

<p>where the <em>constant-expression</em> shall be a converted constant expression (5.19) of the destination type of the switch condition; and</p>

<blockquote>
<p><strong><code>case</code></strong> <em>braced-init-list</em> <strong><code>:</code></strong></p>
</blockquote>

<p>which is equivalent to</p>

<blockquote>
<p><strong><code>case</code></strong> <em><code>t</code></em> <strong><code>:</code></strong></p>
</blockquote>

<p>for some invented temporary variable <code>t</code> of the destination type <code>T</code>, where <code>constexpr T t = </code><em><code>braced-init-list</code></em>.</p>
</blockquote>

<p><em>Non-editorial Note: There is no conversion rule specified by the <em>converted constant expression</em> for the floating point type; use the second syntax <code>{ 3.0 }</code> to get a consistent conversion behavior.</em></p>

<blockquote>
<p>For a <code>switch</code> statement with one or more <code>case</code> labels,<br /></p>

<blockquote>
<p><code>switch (</code><em>s</em><code>) {</code><br /> <code>case </code><em>e<sub>1</sub></em><code>:</code> &#8230;<br /> <code>case </code><em>e<sub>2</sub></em><code>:</code> &#8230;<br /> &#8230;<br /> <code>case </code><em>e<sub>k</sub></em><code>:</code> &#8230;<br /> <code>}</code></p>
</blockquote>

<p>the converted constant expressions <em>e<sub>i</sub></em> <code>==</code> <em>e<sub>i</sub></em>, <code>!(</code><em>e<sub>i</sub></em> <code>&lt;</code> <em>e<sub>i</sub></em><code>)</code>, and <em>e<sub>i</sub></em> <code>!=</code> <em>e<sub>j</sub></em> where <em>i &#8800; j</em>, if any, when contextually converted to <code>bool</code> (4), must yield <code>true</code> for each <em>1 &#8804; i &#8804; k</em> and <em>1 &#8804; j &#8804; k</em>; otherwise, the program is ill-formed. <em>[Note: For a literal class type not implicitly convertible to integral or enumeration type, at compile-time, a user-defined <code>constexpr operator==</code> needs to be issued to ensure the uniqueness of <em>e<sub>1</sub> &#8230; e<sub>k</sub></em>, and a user-defined <code>constexpr operator&lt;</code> can be issued to ensure the sortability of <em>e<sub>1</sub> &#8230; e<sub>k</sub></em>; the same operators shall be selected at runtime, if needed. &#8211;end note]</em> The elements <code>e</code> of a sorted sequence containing <em>e<sub>1</sub> &#8230; e<sub>k</sub></em> are partitioned with respect to the expression <code>e &lt; s</code> and <code>!(s &lt; e)</code>, while for all elements <code>e</code>, <code>e &lt; s</code> shall imply <code>!(s &lt; e)</code>; otherwise, the behavior is undefined.</p>
</blockquote>

<p><em>Non-editorial Note: A &#8220;switch&#8221; statement may be implemented using an &#8220;if&#8230;else&#8221; chain, a binary search, or even a hash table. The requirements above ensure that a complexity of log(N) can always be implemented (but not enforced).</em></p>

<p>Add a new grammar in A.5 gram.stmt:</p>

<blockquote>
<p><em>labeled-statement:</em></p>

<blockquote>
<p>&#8230;<br /> <em>attribute-specifier-seq<sub>opt</sub></em> <strong><code>case</code></strong> <em>braced-init-list</em> <strong><code>:</code></strong> <em>statement</em><br /> &#8230;</p>
</blockquote>
</blockquote>
</body></html>
