<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2019-11-15" />
  <title>Casting convertible_to&lt;bool&gt; considered harmful</title>
  <style>
      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>
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
  { counter-reset: source-line 0; }
pre.numberSource code > span
  { position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
  { content: counter(source-line);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; 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
  {  background-color: #f6f8fa; }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span. { } /* Normal */
code span.al { color: #ff0000; } /* Alert */
code span.an { } /* Annotation */
code span.at { } /* Attribute */
code span.bn { color: #9f6807; } /* BaseN */
code span.bu { color: #9f6807; } /* BuiltIn */
code span.cf { color: #00607c; } /* ControlFlow */
code span.ch { color: #9f6807; } /* Char */
code span.cn { } /* Constant */
code span.co { color: #008000; font-style: italic; } /* Comment */
code span.cv { color: #008000; font-style: italic; } /* CommentVar */
code span.do { color: #008000; } /* Documentation */
code span.dt { color: #00607c; } /* DataType */
code span.dv { color: #9f6807; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #9f6807; } /* Float */
code span.fu { } /* Function */
code span.im { } /* Import */
code span.in { color: #008000; } /* Information */
code span.kw { color: #00607c; } /* Keyword */
code span.op { color: #af1915; } /* Operator */
code span.ot { } /* Other */
code span.pp { color: #6f4e37; } /* Preprocessor */
code span.re { } /* RegionMarker */
code span.sc { color: #9f6807; } /* SpecialChar */
code span.ss { color: #9f6807; } /* SpecialString */
code span.st { color: #9f6807; } /* String */
code span.va { } /* Variable */
code span.vs { color: #9f6807; } /* VerbatimString */
code span.wa { color: #008000; font-weight: bold; } /* Warning */
code.diff {color: #898887}
code.diff span.va {color: #006e28}
code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }

div#refs p { padding-left: 32px; text-indent: -32px; }
</style>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
</style>
  <link href="data:image/vnd.microsoft.icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  <!--[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="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Casting <code class="sourceCode cpp">convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code> considered harmful</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #: </td>
    <td>P1964R0</td>
  </tr>
  <tr>
    <td>Date: </td>
    <td>2019-11-15</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project: </td>
    <td>Programming Language C++<br>
      LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to: </td>
    <td>
      Tim Song<br>&lt;<a href="mailto:t.canens.cpp@gmail.com" class="email">t.canens.cpp@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#revision-history"><span class="toc-section-number">2</span> Revision history<span></span></a></li>
<li><a href="#problem-statement"><span class="toc-section-number">3</span> Problem statement<span></span></a><ul>
<li><a href="#nonuniformity-of-application-remains"><span class="toc-section-number">3.1</span> Nonuniformity of application remains<span></span></a></li>
<li><a href="#contradiction-with-lwgs-preferred-direction-for-lwg2114"><span class="toc-section-number">3.2</span> Contradiction with LWG’s preferred direction for <span class="citation" data-cites="LWG2114">[<span>LWG2114</span>]</span><span></span></a></li>
<li><a href="#conflict-with-existing-practice"><span class="toc-section-number">3.3</span> Conflict with existing practice<span></span></a></li>
<li><a href="#unreasonable-burden-for-implementers-and-users"><span class="toc-section-number">3.4</span> Unreasonable burden for implementers and users<span></span></a></li>
</ul></li>
<li><a href="#proposal-require-the-logical-operators-to-just-work"><span class="toc-section-number">4</span> Proposal: require the logical operators to “just work”<span></span></a></li>
<li><a href="#alternative-direction-limit-the-set-of-permitted-types-to-a-known-set-of-well-behaved-types-not-proposed"><span class="toc-section-number">5</span> Alternative direction: limit the set of permitted types to a known set of well-behaved types (not proposed)<span></span></a></li>
<li><a href="#references"><span class="toc-section-number">6</span> References<span></span></a></li>
</ul>
</div>
<h1 id="abstract" style="border-bottom:1px solid #cccccc"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p><span class="citation" data-cites="P1934R0">[<a href="#ref-P1934R0" role="doc-biblioref">P1934R0</a>]</span> proposes removing the <code class="sourceCode cpp">boolean</code> concept and replacing its uses with <code class="sourceCode cpp">convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code> instead. The proposed replacement fails to completely fix the problems with <code class="sourceCode cpp">boolean</code> identified by the paper, contradicts LWG’s preferred direction for <span class="citation" data-cites="LWG2114">[<a href="#ref-LWG2114" role="doc-biblioref">LWG2114</a>]</span>, conflicts with existing practice, imposes an unreasonable burden on implementers and users alike, and should be reconsidered.</p>
<h1 id="revision-history" style="border-bottom:1px solid #cccccc"><span class="header-section-number">2</span> Revision history<a href="#revision-history" class="self-link"></a></h1>
<ul>
<li>R0: Initial revision for the post-Belfast mailing. An early draft of this paper was written during the Belfast meeting, attached to the LEWG wiki, and subsequently presented to LEWG; this version has been substantially revised from that draft to better follow the actual presentation.</li>
</ul>
<h1 id="problem-statement" style="border-bottom:1px solid #cccccc"><span class="header-section-number">3</span> Problem statement<a href="#problem-statement" class="self-link"></a></h1>
<p><span class="citation" data-cites="P1934R0">[<a href="#ref-P1934R0" role="doc-biblioref">P1934R0</a>]</span> proposes removing the <code class="sourceCode cpp">boolean</code> concept and replacing its uses with <code class="sourceCode cpp">convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code> instead. As <code class="sourceCode cpp">boolean</code> is currently used in the comparison concepts and the <code class="sourceCode cpp">predicate</code> concept, this change requires generic code performing comparisons and invoking predicates to convert the result to <code class="sourceCode cpp"><span class="dt">bool</span></code>. This can be done implicitly, explicitly, or contextually:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Implicit</strong>
</div></th>
<th><div style="text-align:center">
<strong>Explicit</strong>
</div></th>
<th><div style="text-align:center">
<strong>Contextual</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="dt">bool</span> r <span class="op">=</span> x <span class="op">!=</span> y;</span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="dt">bool</span> f<span class="op">()</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="cf">return</span> a <span class="op">&lt;</span> b; <span class="op">}</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;(</span>x <span class="op">==</span> y<span class="op">)</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="dt">bool</span><span class="op">(</span>c <span class="op">&gt;</span> d<span class="op">)</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> y<span class="op">)</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="cf">while</span> <span class="op">(</span>pred<span class="op">(</span>z<span class="op">))</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>However, even though the built-in operators <code class="sourceCode cpp"><span class="op">!</span></code>, <code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code> and <code class="sourceCode cpp"><span class="op">||</span></code> contextually convert their operands to <code class="sourceCode cpp"><span class="dt">bool</span></code>, the existence of operator overloading means that they cannot be used directly with something that’s only required to model <code class="sourceCode cpp">convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code> is required:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Cast not required</strong>
</div></th>
<th><div style="text-align:center">
<strong>Cast required</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S,</span>
<span id="cb4-2"><a href="#cb4-2"></a>         weakly_incrementable O<span class="op">&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>    <span class="kw">requires</span> indirectly_copyable<span class="op">&lt;</span>I, O<span class="op">&gt;</span></span>
<span id="cb4-4"><a href="#cb4-4"></a>O copy<span class="op">(</span>I first, S last, O out<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5"></a>    <span class="cf">for</span><span class="op">(</span>; first <span class="op">!=</span> last; <span class="op">++</span>first, <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">++</span>out<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6"></a>        <span class="op">*</span>out <span class="op">=</span> <span class="op">*</span>first;</span>
<span id="cb4-7"><a href="#cb4-7"></a>    <span class="op">}</span></span>
<span id="cb4-8"><a href="#cb4-8"></a>    <span class="cf">return</span> out;</span>
<span id="cb4-9"><a href="#cb4-9"></a><span class="op">}</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_iterator I1, sentinel_for<span class="op">&lt;</span>I1<span class="op">&gt;</span> S1,</span>
<span id="cb5-2"><a href="#cb5-2"></a>         input_iterator I2, sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2<span class="op">&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3"></a>    <span class="kw">requires</span> indirectly_comparable<span class="op">&lt;</span>I1, I2, ranges<span class="op">::</span>equal<span class="op">&gt;</span></span>
<span id="cb5-4"><a href="#cb5-4"></a><span class="dt">bool</span> equal<span class="op">(</span>I1 first1, S1 last1, I2 first2, S2 last2<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-5"><a href="#cb5-5"></a>    <span class="cf">for</span><span class="op">(</span>; <span class="dt">bool</span><span class="op">(</span>first1 <span class="op">!=</span> last1<span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="dt">bool</span><span class="op">(</span>first2 <span class="op">!=</span> last2<span class="op">)</span>; <span class="co">// both casts required</span></span>
<span id="cb5-6"><a href="#cb5-6"></a>          <span class="op">++</span>first1, <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">++</span>first2<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7"></a>        <span class="cf">if</span> <span class="op">(*</span>first1 <span class="op">!=</span> <span class="op">*</span>first2<span class="op">)</span></span>
<span id="cb5-8"><a href="#cb5-8"></a>            <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb5-9"><a href="#cb5-9"></a>    <span class="op">}</span></span>
<span id="cb5-10"><a href="#cb5-10"></a>    <span class="cf">return</span> <span class="dt">bool</span><span class="op">(</span>first1 <span class="op">==</span> last1<span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="dt">bool</span><span class="op">(</span>first2 <span class="op">==</span> last2<span class="op">)</span>; <span class="co">// ditto</span></span>
<span id="cb5-11"><a href="#cb5-11"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>There are a multitude of problems with this proposed replacement.</p>
<h2 id="nonuniformity-of-application-remains"><span class="header-section-number">3.1</span> Nonuniformity of application remains<a href="#nonuniformity-of-application-remains" class="self-link"></a></h2>
<p>The keenly-eyed reader may have noticed that the examples in the above table are the same as those in section 2.2 “Nonuniformity of application” of <span class="citation" data-cites="P1934R0">[<a href="#ref-P1934R0" role="doc-biblioref">P1934R0</a>]</span>, only modified to be correct.</p>
<p>In other words, P1934R0 fails to solve the motivating example it presented for this problem: a cast is still sometimes required, sometimes not. While it is certainly an improvement over <code class="sourceCode cpp">boolean</code> - the demarcation of the two “sometimes” is cleaner and easier to reason about - the problem remains.</p>
<h2 id="contradiction-with-lwgs-preferred-direction-for-lwg2114"><span class="header-section-number">3.2</span> Contradiction with LWG’s preferred direction for <span class="citation" data-cites="LWG2114">[<a href="#ref-LWG2114" role="doc-biblioref">LWG2114</a>]</span><a href="#contradiction-with-lwgs-preferred-direction-for-lwg2114" class="self-link"></a></h2>
<p>Since C++98, the current library specification has been filled with requirements for something to be “convertible to <code class="sourceCode cpp"><span class="dt">bool</span></code>” requirements (see, e.g., what is now called <em>Cpp17LessThanComparable</em> <span>16.5.3.1 <a href="https://wg21.link/utility.arg.requirements">[utility.arg.requirements]</a></span>) and “contextually convertible to <code class="sourceCode cpp"><span class="dt">bool</span></code>” has been added to the mix since C++11 (see, e.g., <em>Cpp17NullablePointer</em> <span>16.5.3.3 <a href="https://wg21.link/nullablepointer.requirements">[nullablepointer.requirements]</a></span>).</p>
<p>However, these requirements date from a time where library specification has been quite imprecise; as Casey Carter put it during the LEWG discussion of an early draft of this paper, what was meant was more like “it converts to <code class="sourceCode cpp"><span class="dt">bool</span></code> when the library wants it to convert to <code class="sourceCode cpp"><span class="dt">bool</span></code>”.</p>
<p>A library issue, <span class="citation" data-cites="LWG2114">[<a href="#ref-LWG2114" role="doc-biblioref">LWG2114</a>]</span>, was opened in 2011 to address the formulation of these requirements; in 2012, STL explained in the issue that implementations want to do things well beyond just converting them to <code class="sourceCode cpp"><span class="dt">bool</span></code>; the example given from the Dinkumware Standard Library implementation then were:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="cf">if</span> <span class="op">(</span>pred<span class="op">(</span>args<span class="op">))</span></span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="cf">if</span> <span class="op">(!</span>pred<span class="op">(</span>args<span class="op">))</span></span>
<span id="cb6-3"><a href="#cb6-3"></a><span class="cf">if</span> <span class="op">(</span>cond <span class="op">&amp;&amp;</span> pred<span class="op">(</span>args<span class="op">))</span></span>
<span id="cb6-4"><a href="#cb6-4"></a><span class="cf">if</span> <span class="op">(</span>cond <span class="op">&amp;&amp;</span> <span class="op">!</span>pred<span class="op">(</span>args<span class="op">))</span></span></code></pre></div>
<p>All but the first would have required explicit <code class="sourceCode cpp"><span class="dt">bool</span></code> casts if “convertible to <code class="sourceCode cpp"><span class="dt">bool</span></code>” were the sole requirement.</p>
<p>LWG’s direction for LWG2114 has consistently been to require the logical operators to work correctly for these types. However, formulation of correct wording has proven difficult, and since this was seen as a defect in wording and required no implementation changes, it justifiably received a lower priority.</p>
<p><span class="citation" data-cites="P1934R0">[<a href="#ref-P1934R0" role="doc-biblioref">P1934R0</a>]</span> contradicts this longstanding direction. If the former is adopted, then either we need to require implementations to litter <code class="sourceCode cpp"><span class="dt">bool</span></code> casts everywhere through their existing code, or introduce an odd inconsistency in how the algorithms handle such types. Neither is appealing.</p>
<h2 id="conflict-with-existing-practice"><span class="header-section-number">3.3</span> Conflict with existing practice<a href="#conflict-with-existing-practice" class="self-link"></a></h2>
<p><span class="citation" data-cites="P1934R0">[<a href="#ref-P1934R0" role="doc-biblioref">P1934R0</a>]</span> claims that <code class="sourceCode cpp">convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code> “is quite close to the ‘old’ notion of what a predicate should yield”. As seen from the history above, this is simply not the case in practice. None of the three major implementations in fact accept everything “convertible to <code class="sourceCode cpp"><span class="dt">bool</span></code>”; they all make use of logical operations on the result and expect them to work. It takes five minutes to find examples in their current code base:</p>
<table>
<colgroup>
<col style="width: 16%"></col>
<col style="width: 83%"></col>
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Implementation</strong>
</div></th>
<th><div style="text-align:center">
<strong>Example</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>MSVC</td>
<td><code class="sourceCode cpp"><span class="cf">while</span> <span class="op">(</span>_UFirst1 <span class="op">!=</span> _ULast1 <span class="op">&amp;&amp;</span> _UFirst2 <span class="op">!=</span> _ULast2 <span class="op">&amp;&amp;</span> _Pred<span class="op">(*</span>_UFirst1, <span class="op">*</span>_UFirst2<span class="op">))</span></code></td>
</tr>
<tr class="even">
<td>libstdc++</td>
<td><code class="sourceCode cpp"><span class="cf">while</span> <span class="op">(</span>__first <span class="op">!=</span> __last <span class="op">&amp;&amp;</span> <span class="op">!</span>__pred<span class="op">(</span>__first<span class="op">))</span></code></td>
</tr>
<tr class="odd">
<td>libc++</td>
<td><code class="sourceCode cpp"><span class="cf">for</span> <span class="op">(</span>; __first1 <span class="op">!=</span> __last1 <span class="op">&amp;&amp;</span> __first2 <span class="op">!=</span> __last2; <span class="op">++</span>__first1, <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">++</span>__first2<span class="op">)</span></code></td>
</tr>
</tbody>
</table>
<p>It’s also worth noting that two of the three examples above depend on the built-in operator <code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code>’s short-circuiting behavior.</p>
<p>In other words, while “convertible to <code class="sourceCode cpp"><span class="dt">bool</span></code>” or “contextually convertible to <code class="sourceCode cpp"><span class="dt">bool</span></code>” might have been the requirement <em>on paper</em>, it has never been the reality.</p>
<h2 id="unreasonable-burden-for-implementers-and-users"><span class="header-section-number">3.4</span> Unreasonable burden for implementers and users<a href="#unreasonable-burden-for-implementers-and-users" class="self-link"></a></h2>
<p>The benefit conferred by the choice of <code class="sourceCode cpp">convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code> is that it enables certain highly questionable types to be returned from predicates and comparisons - overloading <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&amp;&amp;</span></code> and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">||</span></code> is universally recommended against due to such overloads not having the built-in operator’s short-circuit semantics. But the costs imposed are substantial enough to be unreasonable when measured against the minimal benefit it confers:</p>
<ul>
<li>Implementations, as well as generic code authors using standard library concepts, must now perform <code class="sourceCode cpp"><span class="dt">bool</span></code> casts for correctness. The fact that these casts are only <em>sometimes</em> required compounds the problem.</li>
<li>It’s unclear how many will actually do so, given the unnatural verbosity of these casts, and the lack of these questionable types in the wild. In LWG discussion, a major implementation stated that they have never received a user complaint for not supporting such types, even as they added support for overloaded address-of and comma operators. The lack of such types in the wild also makes it easy to overlook the need for casting and difficult to test for missing casts.</li>
<li>It is very common for authors of concrete iterators in particular to just specify the iterator concept (or named requirement) supported. The standard itself does so for the iterators of containers, as well as things like <code class="sourceCode cpp">filesystem<span class="op">::</span>directory_iterator</code>. Without further changes in the library specification, <em>users</em> would be required to cast the result of comparing two <code class="sourceCode cpp">vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;::</span>iterator</code> to <code class="sourceCode cpp"><span class="dt">bool</span></code>, which is obviously untenable. Similarly, authors of concrete iterators will need to revise their documentation to assure their users that casting is not required. While this might not be a major burden, the fact that doing so is necessary at all should give us pause.</li>
</ul>
<h1 id="proposal-require-the-logical-operators-to-just-work" style="border-bottom:1px solid #cccccc"><span class="header-section-number">4</span> Proposal: require the logical operators to “just work”<a href="#proposal-require-the-logical-operators-to-just-work" class="self-link"></a></h1>
<p>Instead of <code class="sourceCode cpp">convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code>, we propose to replace <code class="sourceCode cpp">boolean</code> with an exposition-only concept <em><code class="sourceCode cpp">boolean<span class="op">-</span>testable</code></em>:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2"></a><span class="kw">concept</span> <em>boolean-testable</em> <span class="op">=</span> convertible_to<span class="op">&lt;</span>T, <span class="dt">bool</span><span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="kw">requires</span> <span class="op">(</span>T<span class="op">&amp;&amp;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3"></a>    <span class="op">{</span> <span class="op">!</span>std<span class="op">::</span>forward<span class="op">&lt;</span>T<span class="op">&gt;(</span>t<span class="op">)</span> <span class="op">}</span> <span class="op">-&gt;</span> convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span>;</span>
<span id="cb7-4"><a href="#cb7-4"></a><span class="op">}</span>;</span></code></pre></div>
<p>and further add the semantic requirement that all logical operators “just work”:</p>
<ul>
<li><code class="sourceCode cpp"><span class="op">!</span></code> can be overloaded but must have the usual semantics;</li>
<li><code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code> and <code class="sourceCode cpp"><span class="op">||</span></code> must have their built-in meaning.</li>
</ul>
<p>This is the same set of operations required to be supported by the current proposed resolution of <span class="citation" data-cites="LWG2114">[<a href="#ref-LWG2114" role="doc-biblioref">LWG2114</a>]</span>; casting to <code class="sourceCode cpp"><span class="dt">bool</span></code> will not be necessary for these operations.</p>
<p>The primary difficulty that has plagued previous attempts at expressing the requirement as to <code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code> and <code class="sourceCode cpp"><span class="op">||</span></code> is that it seems to require universal quantification: for a <em><code class="sourceCode cpp">boolean<span class="op">-</span>testable</code></em> type, we must require that <code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code> and <code class="sourceCode cpp"><span class="op">||</span></code> can be used with <em>every</em> <em><code class="sourceCode cpp">boolean<span class="op">-</span>testable</code></em> type. This is impossible to express in concepts, and exceedingly difficult at best to formulate even in prose, as the drafting history of <span class="citation" data-cites="LWG2114">[<a href="#ref-LWG2114" role="doc-biblioref">LWG2114</a>]</span> attests. Moreover, stating the requirement in this manner makes it difficult to answer even simple questions like “is <code class="sourceCode cpp"><span class="dt">bool</span></code> <em><code class="sourceCode cpp">boolean<span class="op">-</span>testable</code></em>?” If there’s a <code class="sourceCode cpp">Evil</code> type that works with itself but no other type, is <code class="sourceCode cpp">Evil</code> the broken one, or is it everything else? How can you tell?</p>
<p>To address this difficulty and allow the type to be analyzed in isolation, we propose to strengthen the requirement: the type must not introduce a potentially viable <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&amp;&amp;</span></code> or <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">||</span></code> candidate into the overload set. This is a requirement that can be answered easily: given a type, we know its member functions and its associated namespaces and classes (if any). We therefore know the result of class member lookup and argument-dependent lookup for the names <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&amp;&amp;</span></code> and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">||</span></code>. If there is no member with these names, and ADL also does not find an overload that can possibly be viable, then we know that using this type in an expression cannot possibly bring in viable <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&amp;&amp;</span></code> and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">||</span></code> overloads, and so using <code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code> or <code class="sourceCode cpp"><span class="op">||</span></code> with two such types will always resolve to the built-in operator.</p>
<p>While this is a stronger requirement than what is strictly necessary, it allows analysis based on a single type (possibly by a static analyzer), and still admits a wide set of models including well-behaved class and enumeration types. There is some subtlety here (the wording needs to be carefully crafted to ensure that <code class="sourceCode cpp">std<span class="op">::</span>valarray</code>’s <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&amp;&amp;</span></code> and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">||</span></code> do not disqualify <code class="sourceCode cpp">std<span class="op">::</span>true_type</code>, for example), but the rule to teach is simple: just don’t overload the conditional operators, and your type will be fine.</p>
<h1 id="alternative-direction-limit-the-set-of-permitted-types-to-a-known-set-of-well-behaved-types-not-proposed" style="border-bottom:1px solid #cccccc"><span class="header-section-number">5</span> Alternative direction: limit the set of permitted types to a known set of well-behaved types (not proposed)<a href="#alternative-direction-limit-the-set-of-permitted-types-to-a-known-set-of-well-behaved-types-not-proposed" class="self-link"></a></h1>
<p>Alternative suggestions have been made to limit these expression to a small set of permitted types that we know to be well-behaved. Various options have been proposed in this direction.</p>
<table>
<colgroup>
<col style="width: 44%"></col>
<col style="width: 55%"></col>
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Option</strong>
</div></th>
<th><div style="text-align:center">
<strong>Permitted result type of a comparison of predicate</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code class="sourceCode cpp">same_as<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code></td>
<td><code class="sourceCode cpp"><span class="dt">bool</span></code>, only. <code class="sourceCode cpp"><span class="kw">const</span> <span class="dt">bool</span><span class="op">&amp;</span></code> is not allowed.</td>
</tr>
<tr class="even">
<td><code class="sourceCode cpp">decays_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span></code></td>
<td>Anything that decays to <code class="sourceCode cpp"><span class="dt">bool</span></code>, thus allowing, e.g., <code class="sourceCode cpp"><span class="kw">const</span> <span class="dt">bool</span><span class="op">&amp;</span></code> (important for when a pointer to data member is used as an invocable predicate)</td>
</tr>
<tr class="odd">
<td><code class="sourceCode cpp">decays_to<span class="op">&lt;</span>integral<span class="op">&gt;</span></code></td>
<td>Anything that decays to an integral type, such as <code class="sourceCode cpp"><span class="dt">bool</span></code>, <code class="sourceCode cpp"><span class="dt">int</span></code>, or <code class="sourceCode cpp"><span class="kw">const</span> <span class="dt">int</span><span class="op">&amp;</span></code>. This allows things like Windows <code class="sourceCode cpp">BOOL</code> and C functions like <code class="sourceCode cpp">isupper</code> that returns an <code class="sourceCode cpp"><span class="dt">int</span></code>.</td>
</tr>
<tr class="even">
<td><code class="sourceCode cpp">decays_to<span class="op">&lt;</span>integral <span class="kw">or</span> pointer <span class="kw">or</span> pointer<span class="op">-</span>to<span class="op">-</span>member<span class="op">&gt;</span></code></td>
<td>Anything that decays to an integral/pointer/pointer to member type. This enables returning possibly-null pointers from predicates without having to convert them to <code class="sourceCode cpp"><span class="dt">bool</span></code> first.</td>
</tr>
<tr class="odd">
<td><code class="sourceCode cpp">decays_to<span class="op">&lt;</span>integral <span class="kw">or</span> true_type <span class="kw">or</span> false_type<span class="op">&gt;</span></code></td>
<td>This accepts two known-good class types for which support have been requested.</td>
</tr>
</tbody>
</table>
<p>By necessity, they are all significantly more limiting than the <em><code class="sourceCode cpp">boolean<span class="op">-</span>testable</code></em> approach: class types and enumeration types cannot be supported generally; even supporting a select set requires giving up support for pointers and pointers to member. This paper does not propose this approach, but mentions it for completeness.</p>
<h1 id="references" style="border-bottom:1px solid #cccccc"><span class="header-section-number">6</span> References<a href="#references" class="self-link"></a></h1>

<div id="refs" role="doc-bibliography">
<div id="ref-LWG2114">
<p>[LWG2114] Daniel Krügler. Incorrect “contextually convertible to bool” requirements. <br />
<a href="https://wg21.link/lwg2114">https://wg21.link/lwg2114</a></p>
</div>
<div id="ref-P1934R0">
<p>[P1934R0] Casey Carter, Christopher Di Bella, Eric Niebler. 2019. boolean Considered Harmful. <br />
<a href="https://wg21.link/p1934r0">https://wg21.link/p1934r0</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
