<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2587: "Convertible to bool" requirement in conjunction and disjunction</title>
<meta property="og:title" content="Issue 2587: &quot;Convertible to bool&quot; requirement in conjunction and disjunction">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2587.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++17">C++17</a> status.</em></p>
<h3 id="2587"><a href="lwg-defects.html#2587">2587</a>. "Convertible to <code>bool</code>" requirement in <code>conjunction</code> and <code>disjunction</code></h3>
<p><b>Section:</b> 21.3.10 <a href="https://wg21.link/meta.logical">[meta.logical]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Tim Song <b>Opened:</b> 2016-01-18 <b>Last modified:</b> 2017-12-05</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="lwg-index.html#meta.logical">issues</a> in [meta.logical].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The specification of <code>conjunction</code> and <code>disjunction</code> in 21.3.10 <a href="https://wg21.link/meta.logical">[meta.logical]</a> p2 and p5 requires 
<code>Bi::value</code> to be convertible to <code>bool</code>, but nothing in the specification of the actual behavior of the 
templates, which instead uses the expressions <code>Bi::value == false</code> and <code>Bi::value != false</code> instead, 
actually requires this conversion.
<p/>
If the intention of this requirement is to allow implementations to pass <code>Bi::value</code> directly to <code>std::conditional</code>, 
like the sample implementation in P0013R1:
</p>
<blockquote><pre>
template&lt;class B1, class B2&gt;
struct and_&lt;B1, B2&gt; : conditional_t&lt;B1::value, B2, B1&gt; { };
</pre></blockquote>
<p>
then it's insufficient in at least two ways:
</p>
<ol>
<li><p>Nothing in the specification requires the result of comparing <code>Bi::value</code> with <code>false</code> to be consistent 
with the result of the implicit conversion. This is similar to LWG <a href="lwg-defects.html#2114" title="Incorrect &quot;contextually convertible to bool&quot; requirements (Status: Resolved)">2114</a><sup><a href="https://cplusplus.github.io/LWG/issue2114" title="Latest snapshot">(i)</a></sup>, though I don't think the 
<code>BooleanTestable</code> requirements in that issue's P/R covers <code>Bi::value == false</code> and <code>Bi::value != false</code>.</p></li>
<li><p>More importantly, the above implementation is ill-formed for, e.g., 
<code>std::conjunction&lt;std::integral_constant&lt;int, 2&gt;, std::integral_constant&lt;int, 4&gt;&gt;</code>, because converting 2 
to <code>bool</code> is a narrowing conversion that is not allowed for non-type template arguments (see 7.7 <a href="https://wg21.link/expr.const">[expr.const]</a>/4). 
(Note that GCC currently doesn't diagnose this error at all, and Clang doesn't diagnose it inside system headers.) It's not clear 
whether such constructs are intended to be supported, but if they are not, the current wording doesn't prohibit it.</p></li> 
</ol>

<p><i>[2016-08-03 Chicago LWG]</i></p>

<p>
Walter, Nevin, and Jason provide initial Proposed Resolution.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>

<blockquote class="note">
<p>This wording is relative to N4606.</p>

<ol>
<li><p>Change 21.3.10 <a href="https://wg21.link/meta.logical">[meta.logical]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class... B&gt; struct conjunction : <i>see below</i> { };
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-3- The BaseCharacteristic of a specialization <code>conjunction&lt;B<sub><i>1</i></sub>, ..., B<sub><i>N</i></sub>&gt;</code>
is the first type <code>B<sub><i>i</i></sub></code> in the list <code>true_type, B<sub><i>1</i></sub>, ..., B<sub><i>N</i></sub></code>
for which <code><del>B<sub><i>i</i></sub>::value == false</del><ins>! bool(B<sub><i>i</i></sub>::value)</ins></code>,
or if every <code><del>B<sub><i>i</i></sub>::value != false</del><ins>bool(B<sub><i>i</i></sub>::value)</ins></code>, the
BaseCharacteristic is the last type in the list. [&hellip;]
<p/>
-4- For a specialization <code>conjunction&lt;B<sub>1</sub>, ..., B<sub><i>N</i></sub>&gt;</code>, if there is a template
type argument <code>B<sub><i>i</i></sub></code> with <code><del>B<sub><i>i</i></sub>::value ==
false</del><ins>! bool(B<sub><i>i</i></sub>::value)</ins></code>, then instantiating [&hellip;]
</p>
</blockquote>
<pre>
template&lt;class... B&gt; struct disjunction : <i>see below</i> { };
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-6- The BaseCharacteristic of a specialization <code>disjunction&lt;B<sub><i>1</i></sub>, ..., B<sub><i>N</i></sub>&gt;</code>
is the first type <code>B<sub><i>i</i></sub></code> in the list <code>false_type, B<sub><i>1</i></sub>, ...,
B<sub><i>N</i></sub></code> for which <code><del>B<sub><i>i</i></sub>::value !=
false</del><ins>bool(B<sub><i>i</i></sub>::value)</ins></code>, or if every
<code><del>B<sub><i>i</i></sub>::value == false</del><ins>! bool(B<sub><i>i</i></sub>::value)</ins></code>, the
BaseCharacteristic is the last type in the list. [&hellip;]
<p/>
-7- For a specialization <code>disjunction&lt;B1, ..., BN&gt;</code>, if there is a template type argument <code>Bi</code> with
<code><del>B<sub><i>i</i></sub>::value != false</del><ins>bool(B<sub><i>i</i></sub>::value)</ins></code>, then instantiating
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class B&gt; struct negation : bool_constant&lt;!<ins>bool(</ins>B::value<ins>)</ins>&gt; { };
</pre>
<blockquote>
<p>
-8- The class template negation forms the logical negation of its template type argument. The type
<code>negation&lt;B&gt;</code> is a UnaryTypeTrait with a BaseCharacteristic of
<code>bool_constant&lt;!<ins>bool(</ins>B::value<ins>)</ins>&gt;</code>.
</p>
</blockquote>
</blockquote>
</li>
</ol>
</blockquote>
<p><i>[Dec 2017 - The resolution for this issue shipped in the C++17 standard; setting status to 'C++17']</i></p>



<p id="res-2587"><b>Proposed resolution:</b></p>
<p>
The resolution for this issue was combined with the resolution for LWG <a href="lwg-defects.html#2567" title="Specification of logical operator traits uses BaseCharacteristic, which is defined only for UnaryTypeTraits 
and BinaryTypeTraits (Status: C++17)">2567</a><sup><a href="https://cplusplus.github.io/LWG/issue2567" title="Latest snapshot">(i)</a></sup>, so <a href="lwg-defects.html#2567" title="Specification of logical operator traits uses BaseCharacteristic, which is defined only for UnaryTypeTraits 
and BinaryTypeTraits (Status: C++17)">2567</a><sup><a href="https://cplusplus.github.io/LWG/issue2567" title="Latest snapshot">(i)</a></sup> 
resolves this issue here as well.
</p>





</body>
</html>
