<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Boolean conversion for Standard Library types</title>
    <style>
        ins { background-color: LightGreen; }
        del { background-color: LightPink; }
        pre { font: inherit; margin: 1em 3em; }
        h1 { counter-reset: h2; }
        h2:before { counter-increment: h2; content: counter(h2, upper-roman) ". "; }
        nav ol { list-style-type: upper-roman; }
        table.bordered, table.bordered th, table.bordered td { border: thin solid; }
    </style>
</head>
<body>

    <table><tbody>
        <tr><td>Document number:</td><td>P0116R0</td></tr>
        <tr><td>Date:</td><td>2015-09-25</td></tr>
        <tr><td>Project:</td><td>Programming Language C++, Library Evolution Working Group</td></tr>
        <tr><td>Reply-to:</td><td>Robert Kawulak &lt;Robert Kawulak at gmail dot com&gt;</td></tr>
    </tbody></table>

    <h1>Boolean conversion for Standard Library types</h1>

    <nav><h2 id="contents">Table of Contents</h2>
        <ol start="2">
            <li><a href="#introduction">Introduction</a></li>
            <li><a href="#motivation">Motivation</a></li>
            <li><a href="#impact">Impact on the Standard</a></li>
            <li><a href="#design">Design Decisions</a></li>
            <li><a href="#specifications">Technical Specifications</a></li>
        </ol>
    </nav>

    <section><h2 id="introduction">Introduction</h2>

The paper proposes addition of explicit <code>bool</code> conversion operator to the following Standard Library types:
<ul>
<li><code>std::bitset</code></li>
<li><code>std::chrono::duration</code></li>
<li><code>std::complex</code></li>
</ul>
It also discusses possibility of adding the operator to other types.

    </section>

    <section><h2 id="motivation">Motivation</h2>

<p>Types providing a boolean conversion operator offer a convenient way to check whether an object is in some kind of type-specific invalid or “empty” state. With the addition of explicit conversion operators and contextual conversions to C++11, such operators also have much less chance to cause confusion. Some built-in and Standard Library types provide boolean conversion, but there are still some types in the Standard Library that lack this feature despite its potential usefulness.</p>

<p>For example, it's been a common situation for the author to need to check a <code>std::chrono::duration</code> value for being non-zero. Currently, this can be achieved like this:

<pre><code>std::chrono::seconds delay = get_delay();
if ( delay != std::chrono::seconds::zero() )
{
    // there is some delay, handle it…
}
</code></pre>

Or, alternatively, in a less verbose way:

<pre><code>std::chrono::seconds delay = get_delay();
if ( delay.count() )
{
    // there is some delay, handle it…
}
</code></pre>

The proposed addition would allow for expressing the same in a shorter and more readable way, for example:

<pre><code>std::chrono::seconds delay = get_delay();
if ( delay )
{
    // there is some delay, handle it…
}
</code></pre>

Or even:

<pre><code>if ( std::chrono::seconds delay = get_delay() )
{
    // there is some delay, handle it…
}
</code></pre></p>

    </section>

    <section><h2 id="impact">Impact on the Standard</h2>

The proposal describes an extension to some Standard Library types that should generally be safe and have no impact on existing code. However, it might be a breaking change in rare cases, like in code explicitly checking for existence of <code>bool</code> conversion operator in Standard Library types.

    </section>

    <section><h2 id="design">Design Decisions</h2>

<p>The author searched the Standard Library for types that have a notion of invalid or “empty” state but lack a <code>bool</code> conversion operator. The types found are grouped into two categories: <a href="#proposed">proposed</a> and <a href="#possible">possible</a>.</p>

<p>Note that these lists lack string, container and range types since there already was a <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3509.htm">proposal</a> to add a <code>bool</code> conversion operator to them and it has been <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3849.html#operator-bool">rejected</a>.</p>

        <section><h3 id="proposed">Proposed</h3>

<p>These types could have a <code>bool</code> conversion operator with natural semantics and their usability would clearly benefit. The author proposes to add the operator to them. The types and the corresponding operator's semantics are presented in the table below.</p>

<table class="bordered">
    <thead>
        <tr><th>type                              </th><th><code>operator bool ()</code> semantics    </th></tr>
    </thead>
    <tbody>
        <tr><td><code>std::bitset          </code></td><td><code>count() != 0                  </code></td></tr>
        <tr><td><code>std::chrono::duration</code></td><td><code>*this != zero()               </code></td></tr>
        <tr><td><code>std::complex         </code></td><td><code>real() != T() || imag() != T()</code></td></tr>
    </tbody>
</table>

        </section>

        <section><h3 id="possible">Possible</h3>

<p>These types have some kind of invalid or “empty” state and technically could have a <code>bool</code> conversion operator, but the author is not certain that the semantics are not potentially confusing or that there is obvious usability gain. Therefore the types are currently not included in the proposed types list, but the author is open to include those that the Committee would find worthwhile.</p>

<table class="bordered">
    <thead>
        <tr><th>type                           </th><th><code>operator bool ()</code> semantics</th></tr>
    </thead>
    <tbody>
        <tr><td><code>std::weak_ptr     </code></td><td><code>!expired()                </code></td></tr>
        <tr><td><code>std::sub_match    </code></td><td><code>matched                   </code></td></tr>
        <tr><td><code>std::match_results</code></td><td><code>ready()                   </code></td></tr>
        <tr><td><code>std::thread       </code></td><td><code>get_id() != id()          </code></td></tr>
        <tr><td><code>std::thread::id   </code></td><td><code>*this != id()             </code></td></tr>
        <tr><td><code>std::future       </code></td><td><code>valid()                   </code></td></tr>
        <tr><td><code>std::shared_future</code></td><td><code>valid()                   </code></td></tr>
        <tr><td><code>std::packaged_task</code></td><td><code>valid()                   </code></td></tr>
    </tbody>
</table>

        </section>

    </section>

    <section><h2 id="specifications">Technical Specifications</h2>

The proposed wording is relative to the <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4527.pdf">N4527</a> working draft. It only includes changes related to types listed in <a href="#proposed">Proposed</a> section.

<ul>

<li>Change § 20.6 p. 1 [template.bitset] as follows:
<pre>…
<code>bool any() const noexcept;
bool none() const noexcept;
<ins>explicit operator bool() const noexcept;</ins></code>
…</pre></li>

<li>Change § 20.6.2 [bitset.members] as follows:
<pre>…
<code>bool any() const noexcept;</code>
<small>45</small> <i>Returns:</i> <code>count() != 0</code>
<code>bool none() const noexcept;</code>
<small>46</small> <i>Returns:</i> <code>count() == 0</code>
<ins><code>explicit operator bool() const noexcept;</code>
<small>47</small> <i>Returns:</i> <code>count() != 0</code></ins>
…</pre></li>

<li>Change § 20.12.5 p. 1 [time.duration] as follows:
<pre>…
<i>// 20.12.5.2, observer<ins>s</ins>:</i>
<code>constexpr rep count() const;
<ins>constexpr explicit operator bool() const;</ins></code>
…</pre></li>

<li>Change § 20.12.5.2 [time.duration.observer] as follows:
<pre><b>20.12.5.2 <code>duration</code> observer<ins>s</ins> [time.duration.observer<ins>s</ins>]</b>
<code>constexpr rep count() const;</code>
<small>1</small> <i>Returns:</i> <code>rep_</code>.
<ins><code>constexpr explicit operator bool() const;</code>
<small>2</small> <i>Returns:</i> <code>*this != zero()</code>.</ins></pre></li>

<li>Change § 26.4.2 [complex] as follows:
<pre>…
<code>constexpr T imag() const;
void imag(T);
<ins>constexpr explicit operator bool() const;</ins></code>
…</pre></li>

<li>Change § 26.4.3 [complex.special] as follows:
<pre>…
<code>constexpr float imag() const;
void imag(float);
<ins>constexpr explicit operator bool() const;</ins></code>
…
<code>constexpr double imag() const;
void imag(double);
<ins>constexpr explicit operator bool() const;</ins></code>
…
<code>constexpr long double imag() const;
void imag(long double);
<ins>constexpr explicit operator bool() const;</ins></code>
…</pre></li>

<li>Change § 26.4.4 [complex.members] as follows:
<pre>…
<code>constexpr T imag() const;</code>
<i>Returns:</i> The value of the imaginary component.
<code>void imag(T val);</code>
<i>Effects:</i> Assigns <code>val</code> to the imaginary component.
<ins><code>constexpr explicit operator bool() const;</code>
<i>Returns:</i> <code>real() != T() || imag() != T()</code>.</ins></pre></li>

</ul>

    </section>

</body>
</html>
