<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3076: basic_string CTAD ambiguity</title>
<meta property="og:title" content="Issue 3076: basic_string CTAD ambiguity">
<meta property="og:description" content="C++ library issue. Status: C++20">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3076.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#C++20">C++20</a> status.</em></p>
<h3 id="3076"><a href="lwg-defects.html#3076">3076</a>. <code>basic_string</code> CTAD ambiguity</h3>
<p><b>Section:</b> 27.4.3.3 <a href="https://wg21.link/string.cons">[string.cons]</a> <b>Status:</b> <a href="lwg-active.html#C++20">C++20</a>
 <b>Submitter:</b> Stephan T. Lavavej <b>Opened:</b> 2018-03-03 <b>Last modified:</b> 2021-02-25</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#string.cons">issues</a> in [string.cons].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++20">C++20</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The following code fails to compile for surprising reasons.
</p>
<blockquote><pre>
#include &lt;string&gt;
#include &lt;string_view&gt;

using namespace std;

int main() 
{
   string s0;
   basic_string s1(s0, 1, 1);
   // WANT: basic_string(const basic_string&amp;, size_type, size_type, const Allocator&amp; = Allocator())
   // CONFLICT: basic_string(size_type, charT, const Allocator&amp;)

   basic_string s2("cat"sv, 1, 1);
   // WANT: basic_string(const T&amp;, size_type, size_type, const Allocator&amp; = Allocator())
   // CONFLICT: basic_string(size_type, charT, const Allocator&amp;)

   basic_string s3("cat", 1);
   // WANT: basic_string(const charT *, size_type, const Allocator&amp; = Allocator())
   // CONFLICT: basic_string(const charT *, const Allocator&amp;)
}
</pre></blockquote>
<p>
For <code>s1</code> and <code>s2</code>, the signature <code>basic_string(size_type, charT, const Allocator&amp;)</code> participates in CTAD. <code>size_type</code> is non-deduced (it will be substituted later, so the compiler 
can't immediately realize that <code>s0</code> or <code>"cat"sv</code> are totally non-viable arguments). 
<code>charT</code> is deduced to be <code>int</code> (weird, but not the problem). Finally, <code>Allocator</code> 
is deduced to be <code>int</code>. Then the compiler tries to substitute for <code>size_type</code>, but 
this ends up giving int to <code>allocator_traits</code> in a non-SFINAE context, so compilation fails.
<p/>
<code>s3</code> fails for a slightly different reason. <code>basic_string(const charT *, const Allocator&amp;)</code> participates in CTAD, deducing <code>charT</code> to be <code>char</code> (good) and <code>Allocator</code> to be 
<code>int</code>. This is an exact match, which is better than the constructor that the user actually wants 
(where <code>int</code> would need to be converted to <code>size_type</code>, which is unsigned). So CTAD deduces <code>basic_string&lt;char, char_traits&lt;char&gt;, int&gt;</code>, which is the wrong type.
<p/>
This problem appears to be unique to <code>basic_string</code> and its heavily overloaded set of constructors. 
I haven't figured out how to fix it by adding (non-greedy) deduction guides. The conflicting constructors 
are always considered during CTAD, regardless of whether deduction guides are provided that correspond 
to the desired or conflicting constructors. (That's because deduction guides are preferred as a late 
tiebreaker in overload resolution; if a constructor provides a better match it will be chosen before 
tiebreaking.) It appears that we need to constrain the conflicting constructors themselves; this will 
have no effect on actual usage (where <code>Allocator</code> will be an allocator) but will prevent CTAD 
from considering them for non-allocators. As this is unusual, I believe it deserves a <i>Note</i>. 
This has been implemented in MSVC.
</p>

<p><i>[2018-3-14 Wednesday evening issues processing; move to Ready]</i></p>


<p><i>[2018-06 Rapperswil: Adopted]</i></p>



<p id="res-3076"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4727">N4727</a>.
</p>

<ol>
<li>
<p>Edit 27.4.3.3 <a href="https://wg21.link/string.cons">[string.cons]</a> as indicated:</p>
<blockquote>
<pre>
basic_string(const charT* s, const Allocator&amp; a = Allocator());
</pre>
<blockquote>
<p>
-14- <i>Requires:</i> <code>s</code> points to an array of at least <code>traits::length(s) + 1</code> elements of 
<code>charT</code>.
<p/>
-15- <i>Effects:</i> Constructs an object of class <code>basic_string</code> and determines its initial 
string value from the array of <code>charT</code> of length <code>traits::length(s)</code> whose first element 
is designated by <code>s</code>.
<p/>
-16- <i>Postconditions:</i> <code>data()</code> points at the first element of an allocated copy of the 
array whose first element is pointed at by <code>s</code>, <code>size()</code> is equal to <code>traits::length(s)</code>, 
and <code>capacity()</code> is a value at least as large as <code>size()</code>.
<p/>
<ins>-?- <i>Remarks:</i> Shall not participate in overload resolution if <code>Allocator</code> is a type 
that does not qualify as an allocator (23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>). [<i>Note:</i> 
This affects class template argument deduction. &mdash; <i>end note</i>]</ins>
</p>
</blockquote>
<pre>
basic_string(size_type n, charT c, const Allocator&amp; a = Allocator());
</pre>
<blockquote>
<p>
-17- <i>Requires:</i> <code>n &lt; npos</code>.
<p/>
-18- <i>Effects:</i> Constructs an object of class <code>basic_string</code> and determines its initial string 
value by repeating the char-like object <code>c</code> for all <code>n</code> elements.
<p/>
-19- <i>Postconditions:</i> <code>data()</code> points at the first element of an allocated array of <code>n</code>
elements, each storing the initial value <code>c</code>, <code>size()</code> is equal to <code>n</code>, and 
<code>capacity()</code> is a value at least as large as <code>size()</code>.
<p/>
<ins>-?- <i>Remarks:</i> Shall not participate in overload resolution if <code>Allocator</code> is a type that 
does not qualify as an allocator (23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>). [<i>Note:</i> This 
affects class template argument deduction. &mdash; <i>end note</i>]</ins>
</p>
</blockquote>
</blockquote>
</li>

</ol>





</body>
</html>
