<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<title>Implicit conversion traits and utility functions</title>

<style type="text/css">
  p {text-align:justify}
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  blockquote.note
  {
   background-color:#E0E0E0;
   padding-left: 15px;
   padding-right: 15px;
   padding-top: 1px;
   padding-bottom: 1px;
  }
</style>
</head><body>
<address style="text-align: left;">
Document number: P0758R1<br>
Date: 2018-06-06<br>
Audience: Library Working Group<br>
Author: Daniel Kr&uuml;gler<br>
Reply-to: <a href="mailto:daniel.kruegler@gmail.com">Daniel Kr&uuml;gler</a>
</address>
<hr>
<h1 style="text-align: center;">Implicit conversion traits and utility functions</h1>

<ul>
<li><a href="#Intro">Introduction</a></li>
<li><a href="#RevisionHistory">Revision History</a></li>
<li><a href="#Discussion">Discussion</a></li>
<li><a href="#ProposalCandidates">Proposal Candidate</a></li>
<li><a href="#Issues_Resolved">Resolved Issues</a></li>
<li><a href="#Proposed_resolution">Proposed Resolution</a></li>
<li><a href="#Bibliography">Bibliography</a></li>
<li><a href="#Appendix">Sample Implementation</a></li>
</ul>

<h2><a name="Intro"></a>Introduction</h2>
<p>
This proposal became a rather minimalistic proposal by suggesting only a single new trait
<tt>is_nothrow_convertible</tt>, based on the feedback the author got from both the LEWG and LWG discussions.
<p/>
By means of these suggested new facilities, this paper attempts to resolve the existing library issue 
<a href="http://wg21.link/lwg2040">LWG 2040</a> and provides a tool that would allow to resolve 
<a href="http://wg21.link/lwg2999">LWG 2999</a>.
</p>

<h2><a name="RevisionHistory"></a>Revision History</h2>
<p>
Changes since <a href="http://wg21.link/p0758r0">P0758R0</a>:
</p>
<ul>
<li><p>Rebases to the reference working draft <a href="http://wg21.link/n4750">N4750</a></p></li>
<li><p>Eliminates the suggestions to add <tt>is_trivially_convertible</tt>, <tt>decay_copy</tt>, and <tt>implicit_cast</tt>. 
Reasons for this decision are two-fold:</p>
<ol>
<li><p><a href="https://issues.isocpp.org/show_bug.cgi?id=356">LEWG straw polls</a> indicated no convincing
motivation to add either <tt>decay_copy</tt> or <tt>implicit_cast</tt>.</p></li>
<li><p>During the Rapperswil 2108 LWG session concerns were expressed that adding <tt>is_trivially_convertible</tt>
could easily be a cause of nasty compile-time errors or ODR-violations (Similar to those of the pre-existing <tt>is_trivially_constructible</tt> trait),
when at least one of the template arguments would be a type (such as a pointer type) which is complete according to the core language, 
but whose referred to type is incomplete. Another concern was that <a href="http://wg21.link/p0758r0">P0758R0</a> did not present 
a concrete use-case demonstrating the motivation for another intrinsic-depending trait. The author therefore decided to
split-off <tt>is_trivially_convertible</tt> from this proposal, suggesting to defer a potential addition by an
independent proposal.</p></li>
</ol>
</li>
<li><p>The proposal no longer recommends to specify an SG10 feature-testing macro name.</p></li>
</ul>

<h2><a name="Discussion"></a>Discussion</h2>
<p>
This paper revision does not repeat the sections 
<a href="http://wg21.link/p0758r0#Discussion">Discussion</a>,
<a href="http://wg21.link/p0758r0#ProposalCandidates.is_trivially_convertible">2. <tt>is_trivially_convertible</tt></a>,
<a href="http://wg21.link/p0758r0#ProposalCandidates.decay_copy">3. <tt>decay_copy</tt></a>, and
<a href="http://wg21.link/p0758r0#ProposalCandidates.implicit_cast">4. <tt>implicit_cast</tt></a>
of its predecessor <a href="http://wg21.link/p0758r0">P0758R0</a>.
<p/>
Please refer to the previous paper regarding general background and (extended) rationale.
</p>

<h2><a name="ProposalCandidates"></a>Proposal Candidate</h2>
<h3><a name="ProposalCandidates.is_nothrow_convertible"></a><tt>is_nothrow_convertible</tt></h3>
<p>
The <tt>is_nothrow_convertible</tt> trait 
</p>
<blockquote><pre>
template &lt;class From, class To&gt; 
struct is_nothrow_convertible;
</pre></blockquote>
<p>
is presumably one of the most often asked for traits related to <tt>is_convertible</tt>.
One of the earliest official notes of the lack of that feature occurred during the publication of the
<a href="#bib-n3255">N3255</a> proposal that shortly before the C++11 finalization attempted to standardize a new Standard
Library function template <tt>decay_copy</tt> as replacement for the existing <tt><i>DECAY_COPY</i></tt> pseudo-function.
Among other reasons (especially the lateness of the feature request), this proposal failed, because it couldn't provide
the correct conditional exception specification, concluding:
</p>
<blockquote><p> 
"What we would need is <tt>std::is_nothrow_convertible</tt>."
</p></blockquote>
<p>
Shortly after C++11 standardization, <a href="http://wg21.link/lwg2040">LWG 2040</a> was filed requesting the addition
of <tt>is_nothrow_convertible</tt> and <tt>is_trivially_convertible</tt>, but is since then in a kind of zombie state.
<p/>
There are several concrete use-cases for the <tt>is_nothrow_convertible</tt> trait:
</p>
<ol>
<li><p>
It could be used to specify the correct <tt>noexcept</tt> expression for a <tt>decay_copy</tt> replacement template
for <tt><i>DECAY_COPY</i></tt>, which would resolve one important aspect of <a href="http://wg21.link/lwg2999">LWG 2999</a>.
</p></li>
<li><p>
It could be used to restore the valueable (now conditionally) <tt>noexcept</tt> specification for several 
non-throwing <tt>basic_string</tt> functions that had been "<tt>string_view</tt>"-ified, as described by
<a href="http://wg21.link/lwg2946">LWG 2946</a>. As example consider adjusting the currently suggested wording changes for
the following <tt>find</tt> signature:
</p>
<blockquote>
<pre>
<ins>template &lt;class T&gt;</ins>
size_type find(<del>basic_string_view&lt;charT, traits&gt; sv</del><ins>const T&amp; t</ins>, size_type pos = 0) const noexcept<ins>(<i>see below</i>)</ins>;
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> <ins>Creates a variable, <tt>sv</tt>, as if by <tt>basic_string_view&lt;charT, traits&gt; sv = t;</tt> 
and then d</ins><del>D</del>etermines the lowest position <tt>xpos</tt>, if possible, such that both of the following conditions
hold: [&hellip;]
<p/>
-2- <i>Returns:</i> <tt>xpos</tt> if the function can determine such a value for <tt>xpos</tt>. Otherwise, returns <tt>npos</tt>.
<p/>
<ins>-?- <i>Remarks:</i> This function shall not participate in overload resolution unless 
<tt>is_convertible_v&lt;const T&amp;, basic_string_view&lt;charT, traits&gt;&gt;</tt> is <tt>true</tt> and 
<tt>is_convertible_v&lt;const T&amp;, const charT*&gt;</tt> is <tt>false</tt>. The expression inside <tt>noexcept</tt> 
is equivalent to:</ins>
</p>
<blockquote><pre>
<ins>is_nothrow_convertible_v&lt;const T&amp;, basic_string_view&lt;charT, traits&gt;&gt;</ins>
</pre></blockquote>
</blockquote>
</blockquote>
</li>
<li><p>
It could be used to define exception-correct &mdash; either by user-code or by the Standard Library &mdash; a
fundamental <tt>implicit_cast</tt> utility function, as suggested by.
</p></li>
</ol>

<h2><a name="Issues_Resolved"></a>Resolved Issues</h2>
<p>
If the proposed resolution will be accepted, the following library issues will be resolved:
</p>
<table border="1">
  <tr>
    <th>Number</th>
    <th>Description</th>
  </tr>
  <tr>
    <td><a href="http://wg21.link/lwg2040">2040</a></td>
    <td>Missing type traits related to <tt>is_convertible</tt></td>
  </tr>
</table> 

<h2><a name="Proposed_resolution"></a>Proposed resolution</h2>

<p>
The proposed wording changes refer to <a href="http://wg21.link/n4750">N4750</a>.
</p>

<ol>
<li><p>Change 23.15.2 [meta.type.synop], header <tt>&lt;type_traits&gt;</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
namespace std {
  [&hellip;]
  <i>// 23.15.6 [meta.rel], type relations</i>
  template &lt;class T, class U&gt; struct is_same;
  template &lt;class Base, class Derived&gt; struct is_base_of;
  template &lt;class From, class To&gt; struct is_convertible;
  <ins>template &lt;class From, class To&gt; struct is_nothrow_convertible;</ins>
  [&hellip;]
  
  <i>// 23.15.6 [meta.rel], type relations</i>
  template &lt;class T, class UGt; inline constexpr bool is_same_v
    = is_same&lt;T, U&gt;::value;
  template &lt;class Base, class Derived&gt; inline constexpr bool is_base_of_v
    = is_base_of&lt;Base, Derived&gt;::value;
  template &lt;class From, class To&gt; inline constexpr bool is_convertible_v
    = is_convertible&lt;From, To&gt;::value;
  <ins>template &lt;class From, class To&gt; inline constexpr bool is_nothrow_convertible_v
    = is_nothrow_convertible&lt;From, To&gt;::value;</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>

<li><p>Change 23.15.6 [meta.rel], Table 44 &mdash; "Type relationship predicates", as indicated:</p>

<blockquote>
<table border="1">
<caption>Table 44 &mdash; Type relationship predicates</caption>

<tr>
<th>Template</th>
<th>Condition</th>
<th>Comments</th>
</tr>

<tr>
<td colspan="3" style="text-align:center;">&hellip;</td> 
</tr>

<tr>
<td><tt>template &lt;class From, class To&gt;<br/>
struct is_convertible;</tt></td>
<td><i>see below</i></td>
<td><tt>From</tt> and <tt>To</tt> shall be complete<br/>
types, arrays of unknown<br/>
bound, or <i>cv</i> <tt>void</tt> types.</td>
</tr>

<tr>
<td><ins><tt>template &lt;class From, class To&gt;<br/>
struct is_nothrow_convertible;</tt></ins></td>
<td><ins><tt>is_convertible_v&lt;From, To&gt;</tt><br/>
is <tt>true</tt> and the<br/>
conversion, as defined by<br/>
<tt>is_convertible</tt>, is known<br/>
not to throw any<br/>
exceptions ([expr.unary.noexcept]).</ins></td>
<td><ins><tt>From</tt> and <tt>To</tt> shall be complete<br/>
types, arrays of unknown<br/>
bound, or <i>cv</i> <tt>void</tt> types.</ins></td>
</tr>

<tr>
<td colspan="3" style="text-align:center;">&hellip;</td> 
</tr>

</table>
</blockquote>
</li>

</ol>

<h2><a name="Bibliography"></a>Bibliography</h2>
<p>
<a name="bib-n3255"></a><a href="http://wg21.link/n3255">N3255 Lawrence Crowl, Daniel Kr&uuml;gler: "C++ Decay Copy"</a>
<p/>
<a name="bib-P0705R0"></a><a href="http://wg21.link/p0705r0">P0705R0 Tony Van Eerd: "Implicit and Explicit Conversions"</a>
</p>

<h2><a name="Appendix"></a>Sample Implementation</h2>
<p>
Example implementation for the <tt>is_nothrow_convertible</tt> type trait.
</p>
<blockquote>
<pre>
#include &lt;type_traits&gt; // std::enable_if, ...
#include &lt;utility&gt;     // std::forward, std::declval

namespace xstd {

namespace details {

template &lt;class From, class To, bool =
  std::disjunction&lt;
    std::is_void&lt;From&gt;, std::is_function&lt;To&gt;, std::is_array&lt;To&gt;
  &gt;::value
&gt;
struct do_is_nothrow_convertible
{
  using type = std::is_void&lt;To&gt;;
};

struct do_is_nothrow_convertible_impl
{
  template &lt;class To&gt;
  static void test_aux(To) noexcept;

  template &lt;class From, class To&gt;
  static std::bool_constant&lt;noexcept(test_aux&lt;To&gt;(std::declval&lt;From&gt;()))&gt;
  test(int);

  template &lt;class, class&gt;
  static std::false_type
  test(...);
};

template &lt;class From, class To&gt;
struct do_is_nothrow_convertible&lt;From, To, false&gt;
{
  using type = decltype(do_is_nothrow_convertible_impl::test&lt;From, To&gt;(0));
};

} // details

template &lt;class From, class To&gt;
struct is_nothrow_convertible :
  details::do_is_nothrow_convertible&lt;From, To&gt;::type
{ };

template &lt;class From, class To&gt;
inline constexpr bool is_nothrow_convertible_v 
  = is_nothrow_convertible&lt;From, To&gt;::value;

} // xstd
</pre>
</blockquote>

</body></html>