<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2040: Missing type traits related to is_convertible</title>
<meta property="og:title" content="Issue 2040: Missing type traits related to is_convertible">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2040.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#Resolved">Resolved</a> status.</em></p>
<h3 id="2040"><a href="lwg-defects.html#2040">2040</a>. Missing type traits related to <code>is_convertible</code></h3>
<p><b>Section:</b> 21 <a href="https://wg21.link/meta">[meta]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2011-03-03 <b>Last modified:</b> 2020-09-06</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#meta">active issues</a> in [meta].</p>
<p><b>View all other</b> <a href="lwg-index.html#meta">issues</a> in [meta].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>
<p>
When <a href="https://wg21.link/n3142.html">n3142</a>
was suggested, it concentrated on constructions, assignments, and destructions, but overlooked 
to complement the single remaining compiler-support trait
</p>
<blockquote><pre>
template &lt;class From, class To&gt; struct is_convertible;
</pre></blockquote>
<p>
with the no-throw and triviality related aspects as it had been done with the other
expression-based traits. Specifically, the current specification misses to add the
following traits:
</p>
<blockquote><pre>
template &lt;class From, class To&gt; struct is_nothrow_convertible;
template &lt;class From, class To&gt; struct is_trivially_convertible;
</pre></blockquote>

<p>
In particular the lack of <code>is_nothrow_convertible</code> is severely restricting. This
was recently recognized when the proposal for <code>decay_copy</code> was prepared by 
<a href="https://wg21.link/n3255.html">n3255</a>.
There does not exist a portable means to define the correct conditional <code>noexcept</code>
specification for the <code>decay_copy</code> function template, which is declared as:
</p>
<blockquote><pre>
template &lt;class T&gt; 
typename decay&lt;T&gt;::type decay_copy(T&amp;&amp; v) noexcept(<i>???</i>);
</pre></blockquote>

<p>
The semantics of <code>decay_copy</code> bases on an implicit conversion which again
influences the overload set of functions that are viable here. In most circumstances
this will have the same effect as comparing against the trait 
<code>std::is_nothrow_move_constructible</code>, but there is no guarantee for that being
the right answer. It is possible to construct examples, where this would lead
to the false result, e.g.
</p>
<blockquote><pre>
struct S {
  S(const S&amp;) noexcept(false);
 
  template&lt;class T&gt;
  explicit S(T&amp;&amp;) noexcept(true);
};
</pre></blockquote>

<p>
<code>std::is_nothrow_move_constructible</code> will properly honor the explicit template
constructor because of the direct-initialization context which is part of the
<code>std::is_constructible</code> definition and will in this case select it, such that
<code>std::is_nothrow_move_constructible&lt;S&gt;::value == true</code>, but if we had
the traits <code>is_nothrow_convertible</code>, <code>is_nothrow_convertible&lt;S, S&gt;::value</code>
would evaluate to <code>false</code>, because it would use the copy-initialization context
that is part of the <code>is_convertible</code> definition, excluding any explicit
constructors and giving the opposite result.
</p>

<p>
The <code>decay_copy</code> example is surely not one of the most convincing examples, but
<code>is_nothrow_convertible</code> has several use-cases, and can e.g. be used to express
whether calling the following implicit conversion function could throw an exception or not:
</p>

<blockquote><pre>
template&lt;class T, class U&gt;
T implicit_cast(U&amp;&amp; u) noexcept(is_nothrow_convertible&lt;U, T&gt;::value) 
{
  return std::forward&lt;U&gt;(u);
}
</pre></blockquote>

<p>
Therefore I suggest to add the missing trait <code>is_nothrow_convertible</code> and for
completeness also the missing trait <code>is_trivially_convertible</code> to 21 <a href="https://wg21.link/meta">[meta]</a>.
</p>

<p><i>[2011-03-24 Madrid meeting]</i></p>

<p>
Daniel K: This is a new feature so out of scope.
<p/>
Pablo: Any objections to moving 2040 to Open?
<p/>
No objections. 
</p>

<p><i>[Bloomington, 2011]</i></p>

<p>
Move to NAD Future, this would be an extension to existing functionality.
</p>

<p><i>[LEWG, Kona 2017]</i></p>

<p>
Fallen through the cracks since 2011, but we should discuss it. Alisdair points out that triviality is 
about replacing operations with <code>memcpy</code>, so be sure this is false for <code>int</code>-&gt;<code>float</code>. 
</p>    

<p><i>[Rapperswil, 2018]</i></p>

<p>
Resolved by the adoption of <a href="wg21.link/p0758r1">p0758r1</a>.
</p>


<p id="res-2040"><b>Proposed resolution:</b></p>

<ol>
<li><p>Ammend the following declarations to the header <code>&lt;type_traits&gt;</code> synopsis
in 21.3.3 <a href="https://wg21.link/meta.type.synop">[meta.type.synop]</a>:</p>

<blockquote><pre>
namespace std {
  &hellip;
  // 20.9.6, type relations:
  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_trivially_convertible;</ins>
  <ins>template &lt;class From, class To&gt; struct is_nothrow_convertible;</ins>

  &hellip;
}
</pre></blockquote>
</li>

<li><p>Modify Table 51 &mdash; &quot;Type relationship predicates&quot; as indicated. The removal of the
remaining traces of the trait <code>is_explicitly_convertible</code> is an editorial
step, it was removed by <a href="https://wg21.link/n3047.html">n3047</a>:
</p>

<blockquote>
<table border="1">
<caption>Table 51 &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><code>template &lt;class From, class To&gt;<br/>
struct is_convertible;</code></td>
<td><i>see below</i></td>
<td><code>From</code> and <code>To</code> shall be complete<br/>
types, arrays of unknown bound, or<br/>
(possibly cv-qualified) <code>void</code><br/>
types.</td>
</tr>

<tr>
<td><del><code>template &lt;class From, class To&gt;<br/>
struct is_explicitly_convertible;</code></del></td>
<td><del><code>is_constructible&lt;To, From&gt;::value</code></del></td>
<td><del>a synonym for a two-argument<br/>
version of <code>is_constructible</code>.<br/>
An implementation may define it<br/>
as an alias template.</del></td>
</tr>

<tr>
<td><ins><code>template &lt;class From, class To&gt;<br/>
struct is_trivially_convertible;</code></ins></td>
<td><ins><code>is_convertible&lt;From,<br/>
 To&gt;::value</code> is <code>true</code> and the<br/>
conversion, as defined by<br/>
<code>is_convertible</code>, is known<br/>
to call no operation that is<br/>
not trivial ([basic.types], [special]).</ins></td>
<td><ins><code>From</code> and <code>To</code> shall be complete<br/>
types, arrays of unknown bound,<br/>
or (possibly cv-qualified) <code>void</code><br/>
types.</ins></td>
</tr>

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

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

</table>
</blockquote>

</li>
</ol>





</body>
</html>
