<!DOCTYPE html>
<html>
<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>constexpr_bool_conv_r1</title>
  <style type="text/css">code{white-space: pre;}</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(title);
    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>
  <link rel="stylesheet" href="github.css">
  <!-- Style for Markdown -->
  <style>
  .md2html-container {
    max-width: 800px;
    margin: 0 auto;
  }
  .md2html-container > h1:first-child {
    margin-top: 0;
  }
  body {
  font-family: Helvetica, arial, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  padding-top: 10px;
  padding-bottom: 10px;
  background-color: white;
  padding: 30px; }

body > *:first-child {
  margin-top: 0 !important; }
body > *:last-child {
  margin-bottom: 0 !important; }

a {
  color: #4183C4; }
a.absent {
  color: #cc0000; }
a.anchor {
  display: block;
  padding-left: 30px;
  margin-left: -30px;
  cursor: pointer;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0; }

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
  cursor: text;
  position: relative; }

h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
  background: url("../../images/modules/styleguide/para.png") no-repeat 10px center;
  text-decoration: none; }

h1 tt, h1 code {
  font-size: inherit; }

h2 tt, h2 code {
  font-size: inherit; }

h3 tt, h3 code {
  font-size: inherit; }

h4 tt, h4 code {
  font-size: inherit; }

h5 tt, h5 code {
  font-size: inherit; }

h6 tt, h6 code {
  font-size: inherit; }

h1 {
  font-size: 28px;
  color: black; }

h2 {
  font-size: 24px;
  border-bottom: 1px solid #cccccc;
  color: black; }

h3 {
  font-size: 18px; }

h4 {
  font-size: 16px; }

h5 {
  font-size: 14px; }

h6 {
  color: #777777;
  font-size: 14px; }

p, blockquote, ul, ol, dl, li, table, pre {
  margin: 15px 0; }

hr {
  background: transparent url("../../images/modules/pulls/dirty-shade.png") repeat-x 0 0;
  border: 0 none;
  color: #cccccc;
  height: 4px;
  padding: 0; }

body > h2:first-child {
  margin-top: 0;
  padding-top: 0; }
body > h1:first-child {
  margin-top: 0;
  padding-top: 0; }
  body > h1:first-child + h2 {
    margin-top: 0;
    padding-top: 0; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
  margin-top: 0;
  padding-top: 0; }

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0; }

h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
  margin-top: 0; }

li p.first {
  display: inline-block; }

ul, ol {
  padding-left: 30px; }

ul :first-child, ol :first-child {
  margin-top: 0; }

ul :last-child, ol :last-child {
  margin-bottom: 0; }

dl {
  padding: 0; }
  dl dt {
    font-size: 14px;
    font-weight: bold;
    font-style: italic;
    padding: 0;
    margin: 15px 0 5px; }
    dl dt:first-child {
      padding: 0; }
    dl dt > :first-child {
      margin-top: 0; }
    dl dt > :last-child {
      margin-bottom: 0; }
  dl dd {
    margin: 0 0 15px;
    padding: 0 15px; }
    dl dd > :first-child {
      margin-top: 0; }
    dl dd > :last-child {
      margin-bottom: 0; }

blockquote {
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777; }
  blockquote > :first-child {
    margin-top: 0; }
  blockquote > :last-child {
    margin-bottom: 0; }

table {
  border-collapse: collapse;
  padding: 0; }
  table tr {
    border-top: 1px solid #cccccc;
    background-color: white;
    margin: 0;
    padding: 0; }
    table tr:nth-child(2n) {
      background-color: #f8f8f8; }
    table tr th {
      font-weight: bold;
      border: 1px solid #cccccc;
      text-align: left;
      margin: 0;
      padding: 6px 13px; }
    table tr td {
      border: 1px solid #cccccc;
      text-align: left;
      margin: 0;
      padding: 6px 13px; }
    table tr th :first-child, table tr td :first-child {
      margin-top: 0; }
    table tr th :last-child, table tr td :last-child {
      margin-bottom: 0; }

img {
  max-width: 100%; }

span.frame {
  display: block;
  overflow: hidden; }
  span.frame > span {
    border: 1px solid #dddddd;
    display: block;
    float: left;
    overflow: hidden;
    margin: 13px 0 0;
    padding: 7px;
    width: auto; }
  span.frame span img {
    display: block;
    float: left; }
  span.frame span span {
    clear: both;
    color: #333333;
    display: block;
    padding: 5px 0 0; }
span.align-center {
  display: block;
  overflow: hidden;
  clear: both; }
  span.align-center > span {
    display: block;
    overflow: hidden;
    margin: 13px auto 0;
    text-align: center; }
  span.align-center span img {
    margin: 0 auto;
    text-align: center; }
span.align-right {
  display: block;
  overflow: hidden;
  clear: both; }
  span.align-right > span {
    display: block;
    overflow: hidden;
    margin: 13px 0 0;
    text-align: right; }
  span.align-right span img {
    margin: 0;
    text-align: right; }
span.float-left {
  display: block;
  margin-right: 13px;
  overflow: hidden;
  float: left; }
  span.float-left span {
    margin: 13px 0 0; }
span.float-right {
  display: block;
  margin-left: 13px;
  overflow: hidden;
  float: right; }
  span.float-right > span {
    display: block;
    overflow: hidden;
    margin: 13px auto 0;
    text-align: right; }

code, tt {
  margin: 0 2px;
  padding: 0 5px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px; }

pre code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent; }

.highlight pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px; }

pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px; }
  pre code, pre tt {
    background-color: transparent;
    border: none; }
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
  <div class="md2html-container">
<p>Document No: P1401r1 <br> Date: 2019-06-16 <br> Author: Andrzej Krzemieński <br> Reply-to: akrzemi1 (at) gmail (dot) com <br> Audience: EWG</p>
<h1 id="narrowing-contextual-conversions-to-bool">Narrowing contextual conversions to <code>bool</code></h1>
<p>This paper proposes to allow conversions from integral types to type <code>bool</code> in <em>contextually converted constant expression of type <code>bool</code></em>.</p>
<h3 id="tony-tables">Tony tables</h3>
<table>
<thead>
<tr class="header">
<th>Today</th>
<th>If accepted</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>if constexpr(bool(flags &amp; Flags::Exec))</code></td>
<td><code>if constexpr(flags &amp; Flags::Exec)</code></td>
</tr>
<tr class="even">
<td><code>if constexpr(flags &amp; Flags::Exec != 0)</code></td>
<td><code>if constexpr(flags &amp; Flags::Exec)</code></td>
</tr>
<tr class="odd">
<td><code>static_assert(bool(N));</code></td>
<td><code>static_assert(N);</code></td>
</tr>
<tr class="even">
<td><code>static_assert(N % 4 != 0);</code></td>
<td><code>static_assert(N % 4);</code></td>
</tr>
</tbody>
</table>
<h2 id="revisions">Revisions</h2>
<h3 id="r0---r1">R0 -&gt; R1</h3>
<p>Extended the discussion and problem analysis. Outlined the reange of possible changes. Not proposing wording anymore: the goal is to obtain the direction from EWG first.</p>
<h2 id="motivation">Motivation</h2>
<p>Clang currently fails to compile the following program, and this behavior is Standard-compliant:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb1-1" title="1"><span class="kw">enum</span> Flags { Write = <span class="dv">1</span>, Read = <span class="dv">2</span>, Exec = <span class="dv">4</span> };</a>
<a class="sourceLine" id="cb1-2" title="2"></a>
<a class="sourceLine" id="cb1-3" title="3"><span class="kw">template</span> &lt;Flags flags&gt;</a>
<a class="sourceLine" id="cb1-4" title="4"><span class="dt">int</span> f() {</a>
<a class="sourceLine" id="cb1-5" title="5">  <span class="cf">if</span> <span class="kw">constexpr</span> (flags &amp; Flags::Exec) <span class="co">// fails to compile due to narrowing</span></a>
<a class="sourceLine" id="cb1-6" title="6">    <span class="cf">return</span> <span class="dv">0</span>;</a>
<a class="sourceLine" id="cb1-7" title="7">  <span class="cf">else</span></a>
<a class="sourceLine" id="cb1-8" title="8">    <span class="cf">return</span> <span class="dv">1</span>;</a>
<a class="sourceLine" id="cb1-9" title="9">}</a>
<a class="sourceLine" id="cb1-10" title="10"></a>
<a class="sourceLine" id="cb1-11" title="11"><span class="dt">int</span> main() {</a>
<a class="sourceLine" id="cb1-12" title="12">  <span class="cf">return</span> f&lt;Flags::Exec&gt;(); <span class="co">// when instantiated like this</span></a>
<a class="sourceLine" id="cb1-13" title="13">}</a></code></pre></div>
<p>This is because, as currently specified, narrowing is not allowed in contextual conversion to <code>bool</code> in core constant expressions. If compilers were standard-compliant, even the following code would be ill-formed.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb2-1" title="1"><span class="kw">template</span> &lt;<span class="bu">std::</span>size_t N&gt; </a>
<a class="sourceLine" id="cb2-2" title="2"><span class="kw">class</span> Array</a>
<a class="sourceLine" id="cb2-3" title="3">{</a>
<a class="sourceLine" id="cb2-4" title="4">  <span class="kw">static_assert</span>(N, <span class="st">&quot;no 0-size Arrays&quot;</span>);</a>
<a class="sourceLine" id="cb2-5" title="5">  <span class="co">// ...</span></a>
<a class="sourceLine" id="cb2-6" title="6">};</a>
<a class="sourceLine" id="cb2-7" title="7"></a>
<a class="sourceLine" id="cb2-8" title="8">Array&lt;<span class="dv">16</span>&gt; a; <span class="co">// fails to compile in pure C++</span></a></code></pre></div>
<p>All these situations can be fixed by typing a <code>static_cast</code> to type <code>bool</code> or comparing the result to 0, but the fact remains that this behavior is surprising. For instance, using run-time equivalents of the above constructs compiles and executes fine:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb3-1" title="1"><span class="cf">if</span> (flags &amp; Flags::Exec) <span class="co">// ok</span></a>
<a class="sourceLine" id="cb3-2" title="2">  {}</a></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb4-1" title="1"><span class="ot">assert</span>(N); <span class="co">// ok</span></a></code></pre></div>
<p>Note that the proposal only affects the contextual conversions to <code>bool</code>: it does not affect implicit conversions to <code>bool</code> in other contexts.</p>
<h2 id="background">Background</h2>
<p>The no-narrowing requirement was added in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2039">[CWG 2039]</a>, which indicates it was intentional. However, the issue documentation does not state the reason.</p>
<p>The no-narrowing requirement looks justified in the context of <code>noexcept</code> specifications, where the “double <code>noexcept</code>” syntax is so strange that it can be easily misused. For instance, if I want to say that my function <code>f()</code> has the same <code>noexcept</code> specification as function <code>g()</code>, it doesn’t seem impossible that I could mistakenly type this as:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb5-1" title="1"><span class="dt">void</span> f() <span class="kw">noexcept</span>(g);</a></code></pre></div>
<p>To the uninitiated this looks reasonable; and it compiles. Also, if <code>g()</code> is a <code>constexpr</code> function, the following works as well:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb6-1" title="1"><span class="dt">void</span> f() <span class="kw">noexcept</span>(g());</a></code></pre></div>
<p>The no-narrowing requirement helps minimize these bugs, so it has merit. But other contexts, like <code>static_assert</code>, are only victims thereof.</p>
<h2 id="analysis">Analysis</h2>
<h3 id="affected-contexts">Affected contexts</h3>
<p>The definition of <em>contextually converted constant expression of type <code>bool</code></em> ([expr.const]/7) is used in four places in the standard:</p>
<ul>
<li><code>static_assert</code></li>
<li><code>if constexpr</code></li>
<li><code>explicit(bool)</code></li>
<li><code>noexcept(bool)</code></li>
</ul>
<p>Note that <code>requires</code>-clause does not use the definition, as it requires that the expression “shall be a constant expression of type <code>bool</code>” ([temp.constr.atomic]/3). The problems caused by the <em>contextually converted constant expression of type <code>bool</code></em> are mostly visible in the first two cases. In case of <code>explicit(bool)</code> we expext a type trait to be used as an expression.</p>
<p>Similarly, in the case of <code>noexcept(bool)</code> we only expect a type trait or a <code>noexcept</code>-expression.</p>
<p>The following table illustrates where compilers allow a conversion to bool in a <em>contextually converted constant expression of type <code>bool</code></em> against the C++ requirements:</p>
<table>
<thead>
<tr class="header">
<th>context</th>
<th>gcc</th>
<th>clang</th>
<th>icc</th>
<th>msvc</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>static_assert</code></td>
<td>yes</td>
<td>yes</td>
<td>yes</td>
<td>yes</td>
</tr>
<tr class="even">
<td><code>if constexpr</code></td>
<td>yes</td>
<td>no</td>
<td>yes</td>
<td>yes*</td>
</tr>
<tr class="odd">
<td><code>explicit(bool)</code></td>
<td>no</td>
<td>no</td>
<td>–**</td>
<td>–**</td>
</tr>
<tr class="even">
<td><code>noexcept(bool)</code></td>
<td>no</td>
<td>yes</td>
<td>yes</td>
<td>yes*</td>
</tr>
</tbody>
</table>
<p>* MSVC accepts the code but issues a warning even in <code>/W1</code>.<br />
** Feature not implemented.</p>
<p>Accepting this proposal would be to some extent standardizing the existing practice among compiler vendors.</p>
<h3 id="types-contextually-convertible-to-type-bool">Types contextually convertible to type <code>bool</code></h3>
<p>The following table lists types that are contextually convertible to type <code>bool</code>:</p>
<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 22%" />
<col style="width: 21%" />
</colgroup>
<thead>
<tr class="header">
<th>type</th>
<th>allowed in constant expr</th>
<th><code>true</code> when</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>class with conversion to <code>bool</code></td>
<td>yes</td>
<td>operator returns <code>true</code></td>
</tr>
<tr class="even">
<td>class with conversion to a built-in type convertibel to <code>bool</code></td>
<td>as per rules below</td>
<td>as per below rules</td>
</tr>
<tr class="odd">
<td>object/function pointer</td>
<td>no</td>
<td>not null</td>
</tr>
<tr class="even">
<td>function name/reference</td>
<td>no</td>
<td>always</td>
</tr>
<tr class="odd">
<td>array name/reference</td>
<td>no</td>
<td>always</td>
</tr>
<tr class="even">
<td>pointer to member</td>
<td>no</td>
<td>not null</td>
</tr>
<tr class="odd">
<td>integral type</td>
<td>no, except for 0 and 1</td>
<td>not zero</td>
</tr>
<tr class="even">
<td>floating-point type</td>
<td>no</td>
<td>not plus/minus zero</td>
</tr>
<tr class="odd">
<td>nullptr_t</td>
<td>no</td>
<td>never</td>
</tr>
<tr class="even">
<td>unscoped enumeration</td>
<td>no, except for 0 and 1</td>
<td>not zero</td>
</tr>
</tbody>
</table>
<p>The problem, which this proposal is trying to fix, has only been reported when conversions from integral types or unscoped enumeraiotn types are involved, as for these types such conversion has practical and often used meaning:</p>
<ul>
<li>non-empty collection/sequence,</li>
<li>is a given bit in a bitmask set.</li>
</ul>
<p>We have never encountered a need to check if a floating-point value is exactly +/-0 in this way. Technically, checking a pointer has a meaning: “is it really pointing to some object/function”, but it is more difficult to imagine a practical use case for it in <em>contextually converted constant expression of type <code>bool</code></em>.</p>
<h3 id="implicit-conversions-to-bool">Implicit conversions to <code>bool</code></h3>
<p>Some have suggested that a conversion to <code>bool</code> in general should not be considered narrowing, that <code>bool</code> should not be treated as a small integral type, and that the conversion to <code>bool</code> should be treated as a request to classify the states of the object as one of the two categories.</p>
<p>We do not want to go there. Even this seemingly correct reasoning can lead to bugs like this one:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb7-1" title="1"><span class="kw">struct</span> Container {</a>
<a class="sourceLine" id="cb7-2" title="2">  <span class="kw">explicit</span> Container(<span class="dt">bool</span> zeroSize, <span class="dt">bool</span> zeroCapacity) {}</a>
<a class="sourceLine" id="cb7-3" title="3">  <span class="kw">explicit</span> Container(<span class="dt">size_t</span> size, <span class="dt">int</span>* begin) {}</a>
<a class="sourceLine" id="cb7-4" title="4">};</a>
<a class="sourceLine" id="cb7-5" title="5"></a>
<a class="sourceLine" id="cb7-6" title="6"><span class="dt">int</span> main() {</a>
<a class="sourceLine" id="cb7-7" title="7">  <span class="bu">std::</span>vector&lt;<span class="dt">int</span>&gt; v;</a>
<a class="sourceLine" id="cb7-8" title="8">  X x (v.data(), v.size()); <span class="co">// bad order!</span></a>
<a class="sourceLine" id="cb7-9" title="9">}</a></code></pre></div>
<p>If the feature that prevents narrowing conversions can detect this bug, we would like to use this opportunity.</p>
<h3 id="implicit-conversions-to-bool-in-constant-expressions">Implicit conversions to <code>bool</code> in constant expressions</h3>
<p>Another situation brought up while discussing this problem was if the following code should be correct:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb8-1" title="1"><span class="co">// a C++03 type trait</span></a>
<a class="sourceLine" id="cb8-2" title="2"><span class="kw">template</span> &lt;<span class="kw">typename</span> T&gt;</a>
<a class="sourceLine" id="cb8-3" title="3"><span class="kw">struct</span> is_small {</a>
<a class="sourceLine" id="cb8-4" title="4">  <span class="kw">enum</span> { value = (<span class="kw">sizeof</span>(T) == <span class="dv">1</span>) };</a>
<a class="sourceLine" id="cb8-5" title="5">};</a>
<a class="sourceLine" id="cb8-6" title="6"></a>
<a class="sourceLine" id="cb8-7" title="7"><span class="kw">template</span> &lt;<span class="dt">bool</span> small&gt; <span class="kw">struct</span> S {};</a>
<a class="sourceLine" id="cb8-8" title="8">S&lt;is_small&lt;<span class="dt">char</span>&gt;::value&gt; s; <span class="co">// int 1 converted to bool</span></a></code></pre></div>
<p>In constant expressions the situation is different, because whether a conversion is narrowing or not depends not only on the types but also on the velaues, which are known at compile-time. We think that after <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r4.html">[P0907r4]</a> was adopted, and <code>bool</code> has a well defined representation, conversion from <code>1</code> to <code>true</code> is now defined as non-narrowing.</p>
<h3 id="compatibility-with-c-assert-macro">Compatibility with C <code>assert()</code> macro</h3>
<p>As described in <a href="https://cplusplus.github.io/LWG/issue3011">[LWG 3011]</a>, currently macro <code>assert()</code> from the C Standard Library only allows expressions of scalar types, and does not support the concept of expressions “contextually converted to <code>bool</code>”. We believe that this issue does not interact with our proposal. For instance, the following example works even under the C definition of macro <code>assert()</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb9-1" title="1"><span class="kw">template</span> &lt;<span class="bu">std::</span>size_t N&gt; </a>
<a class="sourceLine" id="cb9-2" title="2"><span class="kw">auto</span> makeArray()</a>
<a class="sourceLine" id="cb9-3" title="3">{</a>
<a class="sourceLine" id="cb9-4" title="4">  <span class="ot">assert</span>(N);</a>
<a class="sourceLine" id="cb9-5" title="5">  <span class="co">// ...</span></a>
<a class="sourceLine" id="cb9-6" title="6">}</a></code></pre></div>
<p>But it stops working if we change <code>assert(N)</code> to <code>static_assert(N)</code>.</p>
<h2 id="how-to-fix-this">How to fix this</h2>
<p>There is a two-dimensional space of possible solutions to this problems with two extremal solutions being:</p>
<ol type="1">
<li>Leave the specification as it is: no narrowing is allowed. (This leaves all the known compilers non-conformant.)</li>
<li>Just allow any implicit conversions in <em>contextually converted constant expression of type <code>bool</code></em>. (This compromizes the solution in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2039">[CWG 2039]</a>, whatever its intent was.)</li>
</ol>
<p>The two “degrees of freedom” in the solution space are:</p>
<ol type="1">
<li>Apply the fix only in the subset of the four contexts where the definition of <em>contextually converted constant expression of type <code>bool</code></em> is used; e.g., only in <code>static_assert</code> and <code>if constexpr</code>.</li>
<li>Allow conversion to <code>bool</code> only from a subset of types implicitly convertible to <code>bool</code>, e.g., only integral and scoped enumeration types.</li>
</ol>
<p>In fact, relaxing only <code>static_assert</code> and <code>if constexpr</code>, only for integral and scoped enumeration types solves all issues that have been reported by users that we are aware of.</p>
<p>We request guidance from EWG on which approach to adopt.</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>Jason Merrill originally reported this issue in CWG reflector. Tomasz Kamiński reviewed the paper and suggested improvements.</p>
<p>Members of EWGI significantly improved the quality of the paper.</p>
<h2 id="references">References</h2>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2039">[CWG 2039]</a> Richard Smith, “Constant conversions to <code>bool</code>”.</p>
<p><a href="https://cplusplus.github.io/LWG/issue3011">[LWG 3011]</a> Jonathan Wakely, “Requirements for <code>assert(E)</code> inconsistent with C”.</p>
<p><a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2207.htm">[WG14 N2207]</a> Martin Sebor, Jonathan Wakely, Florian Weimer, “Assert Expression Problematic For C++”.</p>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r4.html">[P0907r4]</a> JF Bastien, “Signed Integers are Two’s Complement”.</p>
  </div>
</body>
</html>

