<html>
<head>
<title>
 N2434 Standard Library Applications for Explicit Conversion Operators
</title>
<base href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/" />
<style type="text/css">
  p {text-align:justify}
  li {text-align:justify}
  ins {background-color:#FFFF99}
  del {background-color:#FF9999}
</style>
</head>
<body>
<h1>Standard Library Applications for Explicit Conversion Operators</h1>
Document Number: N2434(07-0304)<br/>
2007-10-03<br/>
Alisdair Meredith &lt;public@alisdairm.net><br/>
<h2>Background and Rationale</h2>
One feature of the next version of the C++ Language will be Explicit Conversion operators, as descibed in <a href="../2007/n2380.pdf">n2380</a>.  One of the key motivating examples is to simplify the 'conversion to unspecified bool' idiom. This paper proposes to replace most use of unspecified-bool-type with explicit bool conversion operators.  This will simplify the library clauses and aid clarity by removing pseudo-code from normative signatures and simpliying the associated explanatory text.  In particular, note that hole in the type system that 20.5.14.2.6 [func.wrap.func.undef] works around is closed, removing the whole clause.
<p/>
On the other hand, it deliberately leaves the <code>operator bool()</code> conversion function for the <code>vector&lt;bool></code> and <code>bitset</code> proxy classes as implicit.
<p/>
While this paper has no suggested applications of the feature beyond boolean conversions, the committee might want to explore explicit
pointer conversion operators for the library smart pointers.
<p/>
The paper would also resolve LWG issue 644 as NAD.
<p/>
(A couple of Minor editorial nits (typos etc) are also fixed without comment.)

<h2>History</h2>

This paper is a revision of <a href="../2007/n2293.html">N2293</a>. There are two  changes:
<li>
Removed all changes to smart pointers, to be reconsidered once <code>nullptr_t</code> is available.  The issue is that the unspecified bool idiom supports a slightly wider range of comparisons that make sense for pointers
</li>
<li>
Removed the update to <code>basic_ios</code> for concern this might break existing code written against an implementation supporting defect report 468. Suggestion is to follow with wording that allows both implementations in this case, under some as-if clause.
</li>

<h2>Proposed Changes to Working Draught (n2284)</h2>

<ul>
<li>

<p>
Change 19.4.2.1 [sys.errcode.overview]
</p>

<blockquote><pre>
namespace std {
  class error_code {
  public:

    ...

    // observers:
    value_type value() const;
    con<ins>s</ins>t error_category&amp; category() const;
    posix_errno posix() const;
    string message() const;
    wstring wmessage() const;
    <ins>explicit</ins> operator <del>unspecified-</del>bool<del>-type</del><ins>()</ins> const;

    ...
  };
} <em>// namespace std</em>

...

<ins>explicit</ins> operator <del>unspecified-</del>bool<del>-type</del> () const;
</pre></blockquote>
<p>-11- <em>Returns:</em> <del>If</del> value() != value_type()<del>, returns a value that will evaluate <code>true</code> in a boolean context; otherwise,
returs a value that will evaluate <code>false</code>. The return type shall not be convertible to int.</p></del>
<p>-12- <em>Throws:</em> Nothing.</p>
<p><del>-13- [ Note: This conversion can be used in contexts where a bool is expected (e.g., an if condition); however, implicit
conversions (e.g., to int) that can occur with bool are not allowed, eliminating some sources of user error. One
possible implementation choice for this type is pointer to member. - end note ]</del></p>


</pre>
</li>

<li>

<p>
Change 20.5.14.2 [func.wrap.func]:
</p>

<blockquote><pre>

namespace std {
  template&lt;class&gt; class function; // undefined

  template&lt;class R, class... ArgTypes&gt;
  class function&lt;R(ArgTypes...)&gt;
    : public unary_function&lt;T1, R&gt;	// iff sizeof...(ArgTypes) == 1 and ArgTypes contains T1
    : public binary_function&lt;T1, T2, R&gt;	// iff sizeof...(ArgTypes) == 2 and ArgTypes contains T1 and T2
  {
  public:
    ...

    // 20.5.14.2.3, <em>function capacity:</em>
    <ins>explicit</ins> operator <del>unspecified-</del>bool<del>-type</del> () const;

    ...

    <del>private:
    // 20.5.14.2.6, <em>undefined operators:</em>
    template&lt;class R2, class... ArgTypes2&gt; bool operator==(const function&lt;R2(ArgTypes2...)&gt;&amp;);
    template&lt;class R2, class... ArgTypes2&gt; bool operator!=(const function&lt;R2(ArgTypes2...)&gt;&amp;);</del>
  };
} <em>// namespace std</em>
</pre></blockquote>


<p>
and 20.5.14.2.3 [func.wrap.func.cap]:
</p>

<blockquote><pre>
<ins>explicit</ins> operator <del>unspecified-</del>bool<del>-type</del> () const
</pre></blockquote>
<p>
-1- <em>Returns:</em> if *this has a target<del>,</del> returns <del>a value that will evaluate</del> <code>true</code><del> in a boolean context</del>; otherwise<del>,</del> returns <del>a value that will evaluate </del><code>false</code><del> in a boolean context</del>.<del> The value type returned shall not be convertible to int.</del></p>
<p>
-2- <em>Throws:</em> nothing.<del></p>
<p>-3- [ Note: This conversion can be used in contexts where a bool is expected (e.g., an if condition); however, implicit conversions (e.g., to int) that can occur with bool are not allowed, eliminating some sources of user error. One possible implementation choice for this type is pointer-to-member. - end note ]
</del>
</p>

<p>
and remove 20.5.14.2.6 [func.wrap.func.undef]:
</p>
<del>
20.5.14.2.6 undefined operators [func.wrap.func.undef]
<blockquote><pre>
template&lt;class R2, class... ArgTypes2&gt; bool operator==(const function&lt;R2(ArgTypes2...)&gt;&amp;);
template&lt;class R2, class... ArgTypes2&gt; bool operator!=(const function&lt;R2(ArgTypes2...)&gt;&amp;);
</pre></blockquote>
<p>-1- These member functions shall be left undefined.</p>
<p>-2- [ Note: the boolean-like conversion opens a loophole whereby two function instances can be compared via or !=. These undefined void operators close the loophole and ensure a compile-time error. - end note ]</p>
</del>
</li>

<li>


<p>
Change 27.6.1.1.3 [istream::sentry]
</p>

<blockquote><pre>
namespace std {
  template &lt;class charT,class traits = char_traits&lt;charT> >
  class basic_istream&lt;charT,traits>::sentry {
    typedef traits traits_type;
    // bool ok_; exposition only
  public:
    explicit sentry(basic_istream&lt;charT,traits>&amp; is , bool noskipws = false);
    ~sentry();
    <ins>explicit</ins> operator bool() const { return ok_; }
  private:
    sentry(const sentry&amp;); // not defined
    sentry&amp; operator=(const sentry&amp;); // not defined
  };
}
</pre></blockquote>

</li>

<li>

<p>
Change 27.6.2.4 [ostream::sentry]
</p>

<blockquote><pre>
namespace std {
  template &lt;class charT,class traits = char_traits&lt;charT> >
  class basic_ostream&lt;charT,traits>::sentry {
    <em>// bool ok_; exposition only</em>
  public:
    explicit sentry(basic_ostream&lt;charT,traits>&amp; <em>os</em>);
    ~sentry();
    <ins>explicit</ins> operator bool() const { return <em>ok_</em>; }
  private:
    sentry(const sentry&amp;); // not defined
    sentry&amp; operator=(const sentry&amp;); // not defined
  };
}
</pre></blockquote>

</li>

</body>
</html>
