<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2939: Some type-completeness constraints of traits are overspecified</title>
<meta property="og:title" content="Issue 2939: Some type-completeness constraints of traits are overspecified">
<meta property="og:description" content="C++ library issue. Status: Open">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2939.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#Open">Open</a> status.</em></p>
<h3 id="2939"><a href="lwg-active.html#2939">2939</a>. Some type-completeness constraints of traits are overspecified</h3>
<p><b>Section:</b> 21.3.3 <a href="https://wg21.link/meta.type.synop">[meta.type.synop]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2017-03-02 <b>Last modified:</b> 2024-08-21</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="lwg-index-open.html#meta.type.synop">active issues</a> in [meta.type.synop].</p>
<p><b>View all other</b> <a href="lwg-index.html#meta.type.synop">issues</a> in [meta.type.synop].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Open">Open</a> status.</p>
<p><b>Discussion:</b></p>
<p>
LWG <a href="lwg-defects.html#2797" title="Trait precondition violations (Status: Resolved)">2797</a><sup><a href="https://cplusplus.github.io/LWG/issue2797" title="Latest snapshot">(i)</a></sup> (RU 2) suggests that certain type-traits should be required to
diagnose violations of their pre-conditions. The basic idea is founded and I see no problems for
requiring this for the mentioned traits <code>alignment_of</code> or <code>is_base_of</code>,
for example. But if we want to require this diagnostics for some other traits, such as <code>is_convertible</code>,
<code>is_constructible</code> (and friends), or <code>is_callable</code> (and possibly some others), we really should
be sure that our current requirements are OK. 
<p/>
Unfortunately, there exists some cases, where we currently overspecify imposing complete type requirements where they
are not actually required. For example, for the following situation the answer of the trait could 
be given without ever needing the complete type of <code>X</code>:
</p>
<blockquote><pre>
struct X; // Never defined

static_assert(std::is_convertible_v&lt;X, const X&amp;&gt;);
</pre></blockquote>
<p>
Unfortunately we cannot <em>always</em> allow incomplete types, because most type constructions or conversions indeed
require a complete type, so <em>generally</em> relaxing the current restrictions is also not an option.
<p/>
The core language has a solution for this "small" gap of situations, where the response of the compiler <em>might</em>
depend on type completeness: Undefined behaviour. So, I believe we need a somewhat more detailled form to express the
intend here. Informally, I would suggest that the program should only be ill-formed in the situation described by 
LWG <a href="lwg-defects.html#2797" title="Trait precondition violations (Status: Resolved)">2797</a><sup><a href="https://cplusplus.github.io/LWG/issue2797" title="Latest snapshot">(i)</a></sup>, if there exists the <em>possibility</em> that the compiler would require complete types for the
considered operation. The example shown above, <code>std::is_convertible_v&lt;X, const X&amp;&gt;</code>, would <b>never</b>
require the need to complete <code>X</code>, so here no violation should exist.
<p/>
The presented example might seem a tiny one, but the Standard Library type traits are extreme fundamental tools and we should
try to not give the impression that an approximate rule of the current type constraints breaks reasonable code.
<p/>
It is correct, that above example has currently undefined behaviour due to the breakage of pre-conditions, therefore
this issue suggests to fix the current situation <em>before</em> enforcing a diagnostic for such valid situations.
</p>

<p><i>[2017-03-04, Kona]</i></p>

<p>Set priority to 2. Is related to <a href="lwg-defects.html#2797" title="Trait precondition violations (Status: Resolved)">2797</a><sup><a href="https://cplusplus.github.io/LWG/issue2797" title="Latest snapshot">(i)</a></sup>, but really needs an audit of the type traits.</p>

<p><i>[2018-08 Batavia Monday issue discussion]</i></p>

<p>Issues <a href="lwg-defects.html#2797" title="Trait precondition violations (Status: Resolved)">2797</a><sup><a href="https://cplusplus.github.io/LWG/issue2797" title="Latest snapshot">(i)</a></sup>, <a href="lwg-active.html#2939" title="Some type-completeness constraints of traits are overspecified (Status: Open)">2939</a><sup><a href="https://cplusplus.github.io/LWG/issue2939" title="Latest snapshot">(i)</a></sup>, <a href="lwg-defects.html#3022" title="is_convertible&lt;derived*, base*&gt; may lead to ODR (Status: Resolved)">3022</a><sup><a href="https://cplusplus.github.io/LWG/issue3022" title="Latest snapshot">(i)</a></sup>, and <a href="lwg-active.html#3099" title="is_assignable&lt;Incomplete&amp;, Incomplete&amp;&gt; (Status: Open)">3099</a><sup><a href="https://cplusplus.github.io/LWG/issue3099" title="Latest snapshot">(i)</a></sup> are all closely related. Walter to write a paper resolving them.</p>

<p><i>[2020-02 Prague Thursday issue discussion]</i></p>

<p>
Two of the issues (<a href="lwg-defects.html#2797" title="Trait precondition violations (Status: Resolved)">2797</a><sup><a href="https://cplusplus.github.io/LWG/issue2797" title="Latest snapshot">(i)</a></sup> and <a href="lwg-defects.html#3022" title="is_convertible&lt;derived*, base*&gt; may lead to ODR (Status: Resolved)">3022</a><sup><a href="https://cplusplus.github.io/LWG/issue3022" title="Latest snapshot">(i)</a></sup>) had been resolved by the
acceptance of <a href="https://wg21.link/p1285r0">P1285R0</a>.
</p>

<p><i>[2024-05-09; Jonathan provides wording]</i></p>

<p>
We could also relax the type completeness requirements for
<code class='backtick'>reference_converts_from_temporary</code> and <code class='backtick'>reference_constructs_from_temporary</code>,
as the result is always false if the first type is a non-reference,
so we don't need complete types in that case.
This doesn't seem important to support, but if we wanted to then we could say:
<blockquote>
<ins> Either <code class='backtick'>T</code> is not a reference type, or </ins>
<del><code class='backtick'>T</code> and</del>
<code class='backtick'>U</code> shall be <ins>a complete type</ins> <del>complete types</del>,
<i>cv</i> <code class='backtick'>void</code>, or <ins>an array</ins><del>arrays</del> of unknown bound.
</blockquote>
</p>
<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">

<p>This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.</p>
<blockquote>
<ol>
<li>
In 21.3.6.4 <a href="https://wg21.link/meta.unary.prop">[meta.unary.prop]</a> Table 51,
change the <b>Preconditions</b> text for
<code class='backtick'>is_constructible</code>, <code class='backtick'>is_trivially_constructible</code>, <code class='backtick'>is_nothrow_constructible</code>,
<code class='backtick'>is_convertible</code>, and <code class='backtick'>is_nothrow_convertible</code>,
as indicated.
<blockquote>
<table style="border: 1px solid; border-spacing: 1.5em">
<thead style="text-align: center">
<tr><th>Template</th><th>Condition</th><th>Preconditions</th></tr>
</thead>
<tbody style="vertical-align: top">
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
<tr>
<td>
<pre><code>template&lt;class T, class... Args&gt;
struct is_constructible;</code></pre>
</td>
<td>
For a function type <code class='backtick'>T</code> or
for a <i>cv</i> <code class='backtick'>void</code> type <code class='backtick'>T</code>,
<code>is_constructible_v&lt;T, Args...&gt;</code>
is <code class='backtick'>false</code>,
otherwise <i>see below</i>
<ins>.</ins>
</td>
<td>
<ins>
Either <code class='backtick'>T</code> is a reference type and <code class='backtick'>Args</code> contains a single type that
is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;T&gt;</code>, or
</ins>
<code class='backtick'>T</code> and all types in the template parameter pack <code class='backtick'>Args</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
<tr>
<td>
<pre><code>template&lt;class T, class... Args&gt;
struct is_trivially_constructible;</code></pre>
</td>
<td>
<code>is_constructible_v&lt;T, Args...&gt;</code>
is <code class='backtick'>true</code> and the variable definition for <code class='backtick'>is_constructible</code>,
as defined below, is known to call no operation that is not trivial
(6.9.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a>, 11.4.4 <a href="https://wg21.link/special">[special]</a>).
</td>
<td>
<ins>
Either <code class='backtick'>T</code> is a reference type and <code class='backtick'>Args</code> contains a single type that
is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;T&gt;</code>, or
</ins>
<code class='backtick'>T</code> and all types in the template parameter pack <code class='backtick'>Args</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
<tr>
<td>
<pre><code>template&lt;class T, class... Args&gt;
struct is_nothrow_constructible;</code></pre>
</td>
<td>
<code>is_constructible_v&lt;T, Args...&gt;</code>
is <code class='backtick'>true</code> and the variable definition for <code class='backtick'>is_constructible</code>,
as defined below, is known not to throw any exceptions
(7.6.2.7 <a href="https://wg21.link/expr.unary.noexcept">[expr.unary.noexcept]</a>).
</td>
<td>
<ins>
Either <code class='backtick'>T</code> is a reference type and <code class='backtick'>Args</code> contains a single type that
is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;T&gt;</code>, or
</ins>
<code class='backtick'>T</code> and all types in the template parameter pack <code class='backtick'>Args</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
</tbody>
</table>
</blockquote>
</li>
<li>
In 21.3.8 <a href="https://wg21.link/meta.rel">[meta.rel]</a> Table 53,
change the <b>Comments</b> text for
<code class='backtick'>is_convertible</code> and <code class='backtick'>is_nothrow_convertible</code>
as indicated.
<blockquote>
<table style="border: 1px solid; border-spacing: 1.5em">
<thead style="text-align: center">
<tr><th>Template</th><th>Condition</th><th>Comments</th></tr>
</thead>
<tbody style="vertical-align: top">
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
<tr>
<td>
<pre><code>template&lt;class From, class To&gt;
struct is_convertible;</code></pre>
</td>
<td>
<i>see below</i>
</td>
<td>
<ins>
Either <code class='backtick'>To</code> is a reference type and <code class='backtick'>From</code>
is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;To&gt;</code>, or
</ins>
<code class='backtick'>From</code> and <code class='backtick'>To</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
<tr>
<td>
<pre><code>template&lt;class From, class To&gt;
struct is_nothrow_convertible;</code></pre>
</td>
<td>
<code>is_convertible_v&lt;From, To&gt;</code>
is <code class='backtick'>true</code> and the conversion, as defined by <code class='backtick'>is_convertible</code>,
is known not to throw any exceptions
(7.6.2.7 <a href="https://wg21.link/expr.unary.noexcept">[expr.unary.noexcept]</a>).
</td>
<td>
<ins>
Either <code class='backtick'>To</code> is a reference type and <code class='backtick'>From</code>
is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;To&gt;</code>, or
</ins>
<code class='backtick'>From</code> and <code class='backtick'>To</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
</tbody>
</table>
</blockquote>
</li>
</ol>
</blockquote>
</blockquote>

<p><i>[2024-08-21; Jonathan provides improved wording]</i></p>

<p>
Following on LWG telecon review,
change "Args contains a single type that is similar"
to "Args contains a single type and that type is similar".
</p>



<p id="res-2939"><b>Proposed resolution:</b></p>
<p>This wording is relative to <a href="https://wg21.link/N4988" title=" Working Draft, Programming Languages — C++">N4988</a>.</p>
<blockquote>
<ol>
<li>
In 21.3.6.4 <a href="https://wg21.link/meta.unary.prop">[meta.unary.prop]</a> Table 51,
change the <b>Preconditions</b> text for
<code class='backtick'>is_constructible</code>, <code class='backtick'>is_trivially_constructible</code>, <code class='backtick'>is_nothrow_constructible</code>,
<code class='backtick'>is_convertible</code>, and <code class='backtick'>is_nothrow_convertible</code>,
as indicated.
<blockquote>
<table style="border: 1px solid; border-spacing: 1.5em">
<thead style="text-align: center">
<tr><th>Template</th><th>Condition</th><th>Preconditions</th></tr>
</thead>
<tbody style="vertical-align: top">
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
<tr>
<td>
<pre><code>template&lt;class T, class... Args&gt;
struct is_constructible;</code></pre>
</td>
<td>
For a function type <code class='backtick'>T</code> or
for a <i>cv</i> <code class='backtick'>void</code> type <code class='backtick'>T</code>,
<code>is_constructible_v&lt;T, Args...&gt;</code>
is <code class='backtick'>false</code>,
otherwise <i>see below</i>
<ins>.</ins>
</td>
<td>
<ins>
Either <code class='backtick'>T</code> is a reference type and <code class='backtick'>Args</code> contains a single type
and that type is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;T&gt;</code>, or
</ins>
<code class='backtick'>T</code> and all types in the template parameter pack <code class='backtick'>Args</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
<tr>
<td>
<pre><code>template&lt;class T, class... Args&gt;
struct is_trivially_constructible;</code></pre>
</td>
<td>
<code>is_constructible_v&lt;T, Args...&gt;</code>
is <code class='backtick'>true</code> and the variable definition for <code class='backtick'>is_constructible</code>,
as defined below, is known to call no operation that is not trivial
(6.9.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a>, 11.4.4 <a href="https://wg21.link/special">[special]</a>).
</td>
<td>
<ins>
Either <code class='backtick'>T</code> is a reference type and <code class='backtick'>Args</code> contains a single type
and that type is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;T&gt;</code>, or
</ins>
<code class='backtick'>T</code> and all types in the template parameter pack <code class='backtick'>Args</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
<tr>
<td>
<pre><code>template&lt;class T, class... Args&gt;
struct is_nothrow_constructible;</code></pre>
</td>
<td>
<code>is_constructible_v&lt;T, Args...&gt;</code>
is <code class='backtick'>true</code> and the variable definition for <code class='backtick'>is_constructible</code>,
as defined below, is known not to throw any exceptions
(7.6.2.7 <a href="https://wg21.link/expr.unary.noexcept">[expr.unary.noexcept]</a>).
</td>
<td>
<ins>
Either <code class='backtick'>T</code> is a reference type and <code class='backtick'>Args</code> contains a single type
and that type is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;T&gt;</code>, or
</ins>
<code class='backtick'>T</code> and all types in the template parameter pack <code class='backtick'>Args</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
</tbody>
</table>
</blockquote>
</li>
<li>
In 21.3.8 <a href="https://wg21.link/meta.rel">[meta.rel]</a> Table 53,
change the <b>Comments</b> text for
<code class='backtick'>is_convertible</code> and <code class='backtick'>is_nothrow_convertible</code>
as indicated.
<blockquote>
<table style="border: 1px solid; border-spacing: 1.5em">
<thead style="text-align: center">
<tr><th>Template</th><th>Condition</th><th>Comments</th></tr>
</thead>
<tbody style="vertical-align: top">
<tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr>
<tr>
<td>
<pre><code>template&lt;class From, class To&gt;
struct is_convertible;</code></pre>
</td>
<td>
<i>see below</i>
</td>
<td>
<ins>
Either <code class='backtick'>To</code> is a reference type and <code class='backtick'>From</code>
is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;To&gt;</code>, or
</ins>
<code class='backtick'>From</code> and <code class='backtick'>To</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
<tr>
<td>
<pre><code>template&lt;class From, class To&gt;
struct is_nothrow_convertible;</code></pre>
</td>
<td>
<code>is_convertible_v&lt;From, To&gt;</code>
is <code class='backtick'>true</code> and the conversion, as defined by <code class='backtick'>is_convertible</code>,
is known not to throw any exceptions
(7.6.2.7 <a href="https://wg21.link/expr.unary.noexcept">[expr.unary.noexcept]</a>).
</td>
<td>
<ins>
Either <code class='backtick'>To</code> is a reference type and <code class='backtick'>From</code>
is similar (7.3.6 <a href="https://wg21.link/conv.qual">[conv.qual]</a>) to
<code>remove_reference_t&lt;To&gt;</code>, or
</ins>
<code class='backtick'>From</code> and <code class='backtick'>To</code> shall be complete types,
<i>cv</i> <code class='backtick'>void</code>, or arrays of unknown bound.
</td>
</tr>
</tbody>
</table>
</blockquote>
</li>
</ol>
</blockquote>






</body>
</html>
