<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3900: The allocator_arg_t overloads of generator::promise_type::operator new
should not be constrained</title>
<meta property="og:title" content="Issue 3900: The allocator_arg_t overloads of generator::promise_type::operator new
should not be constrained">
<meta property="og:description" content="C++ library issue. Status: WP">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3900.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#WP">WP</a> status.</em></p>
<h3 id="3900"><a href="lwg-defects.html#3900">3900</a>. The <code>allocator_arg_t</code> overloads of <code>generator::promise_type::operator new</code>
should not be constrained</h3>
<p><b>Section:</b> 25.8.5 <a href="https://wg21.link/coro.generator.promise">[coro.generator.promise]</a> <b>Status:</b> <a href="lwg-active.html#WP">WP</a>
 <b>Submitter:</b> Tim Song <b>Opened:</b> 2023-03-04 <b>Last modified:</b> 2024-11-28</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="lwg-index.html#coro.generator.promise">issues</a> in [coro.generator.promise].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#WP">WP</a> status.</p>
<p><b>Discussion:</b></p>
<p>
When the allocator is not type-erased, the <code>allocator_arg_t</code> overloads of
<code>generator::promise_type::operator new</code> are constrained on
<code>convertible_to&lt;const Alloc&amp;, Allocator&gt;</code>. As a result, if the
the allocator is default-constructible (like <code>polymorphic_allocator</code> is)
but the user accidentally provided a wrong type (say, <code>memory_resource&amp;</code>
instead of <code>memory_resource*</code>), their code will silently fall back to
using a default-constructed allocator. It would seem better to take the tag
as definitive evidence of the user's intent to supply an allocator for the coroutine,
and error out if the supplied allocator cannot be used.
<p/>
This change does mean that the user cannot deliberately pass an incompatible
allocator (preceded by an <code>std::allocator_arg_t</code> tag) for their own use
inside the coroutine, but that sort of API seems fragile and confusing at best,
since the usual case is that allocators so passed <i>will</i> be used by
<code>generator</code>.
</p>

<p><i>[2023-03-22; Reflector poll]</i></p>

<p>
Set priority to 3 after reflector poll.
</p>

<p><i>[St. Louis 2024-06-28; move to Ready]</i></p>


<p><i>[Wrocław 2024-11-23; Status changed: Voting &rarr; WP.]</i></p>



<p id="res-3900"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4928" title=" Working Draft, Standard for Programming Language C++">N4928</a>.
</p>

<ol>

<li><p>Modify 25.8.5 <a href="https://wg21.link/coro.generator.promise">[coro.generator.promise]</a> as indicated:</p>

<blockquote>
<blockquote>
<pre>
namespace std {
  template&lt;class Ref, class V, class Allocator&gt;
  class generator&lt;Ref, V, Allocator&gt;::promise_type {
  public:
    [&hellip;]
    void* operator new(size_t size)
      requires same_as&lt;Allocator, void&gt; || default_initializable&lt;Allocator&gt;;

    template&lt;class Alloc, class... Args&gt;
      <del>requires same_as&lt;Allocator, void&gt; || convertible_to&lt;const Alloc&amp;, Allocator&gt;</del>
        void* operator new(size_t size, allocator_arg_t, const Alloc&amp; alloc, const Args&amp;...);

    template&lt;class This, class Alloc, class... Args&gt;
      <del>requires same_as&lt;Allocator, void&gt; || convertible_to&lt;const Alloc&amp;, Allocator&gt;</del>
        void* operator new(size_t size, const This&amp;, allocator_arg_t, const Alloc&amp; alloc,
                           const Args&amp;...);
    [&hellip;]
   };
}
</pre>
</blockquote>
[&hellip;]
<pre>
void* operator new(size_t size)
  requires same_as&lt;Allocator, void&gt; || default_initializable&lt;Allocator&gt;;

template&lt;class Alloc, class... Args&gt;
  <del>requires same_as&lt;Allocator, void&gt; || convertible_to&lt;const Alloc&amp;, Allocator&gt;</del>
  void* operator new(size_t size, allocator_arg_t, const Alloc&amp; alloc, const Args&amp;...);

template&lt;class This, class Alloc, class... Args&gt;
  <del>requires same_as&lt;Allocator, void&gt; || convertible_to&lt;const Alloc&amp;, Allocator&gt;</del>
  void* operator new(size_t size, const This&amp;, allocator_arg_t, const Alloc&amp; alloc,
                     const Args&amp;...);
</pre>
<blockquote>
<p>
-17- Let <code>A</code> be
</p>
<ol style="list-style-type: none">
  <li><p>(17.1) &mdash; <code>Allocator</code>, if it is not <code>void</code>,</p></li>
  <li><p>(17.2) &mdash; <code>Alloc</code> for the overloads with a template parameter <code>Alloc</code>, or</p></li>
  <li><p>(17.3) &mdash; <code>allocator&lt;void&gt;</code> otherwise.</p></li>
</ol>
<p>
Let <code>B</code> be <code>allocator_traits&lt;A&gt;::template rebind_alloc&lt;U&gt;</code>
where <code>U</code> is an unspecified type whose size and alignment are both
<code>__STDCPP_DEFAULT_NEW_ALIGNMENT__</code>.
<p/>
-18- <i>Mandates</i>: <code>allocator_traits&lt;B&gt;::pointer</code> is a pointer type.
<ins>For the overloads with a template parameter <code>Alloc</code>,
<code>same_as&lt;Allocator, void&gt; || convertible_to&lt;const Alloc&amp;, Allocator&gt;</code> is modeled.</ins>
<p/>
-19- <i>Effects</i>: Initializes an allocator <code>b</code> of type <code>B</code> with <code>A(alloc)</code>,
for the overloads with a function parameter <code>alloc</code>, and with <code>A()</code> otherwise.
Uses <code>b</code> to allocate storage for the smallest array of <code>U</code> sufficient
to provide storage for a coroutine state of size <code>size</code>, and unspecified
additional state necessary to ensure that <code>operator delete</code> can later
deallocate this memory block with an allocator equal to <code>b</code>.
<p/>
-20- <i>Returns:</i> A pointer to the allocated storage.
</p>

</blockquote>
</blockquote>


</li>


</ol>





</body>
</html>
