<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2072: Unclear wording about capacity of temporary buffers</title>
<meta property="og:title" content="Issue 2072: Unclear wording about capacity of temporary buffers">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2072.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++17">C++17</a> status.</em></p>
<h3 id="2072"><a href="lwg-defects.html#2072">2072</a>. Unclear wording about capacity of temporary buffers</h3>
<p><b>Section:</b> 99 [depr.temporary.buffer] <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Kazutoshi Satoda <b>Opened:</b> 2011-08-10 <b>Last modified:</b> 2025-03-13</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="lwg-index.html#depr.temporary.buffer">issues</a> in [depr.temporary.buffer].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>

<p>
According to  [temporary.buffer] p1+2:

</p><blockquote><pre>
template &lt;class T&gt;
pair&lt;T*, ptrdiff_t&gt; get_temporary_buffer(ptrdiff_t n) noexcept;
</pre><blockquote><p>
-1- <i>Effects</i>: Obtains a pointer to storage sufficient to store up to <code>n</code> adjacent <code>T</code> 
objects. It is implementation-defined whether over-aligned types are supported (3.11).
<p/>
-2- <i>Returns</i>: A pair containing the buffer's address and capacity (in the units of <code>sizeof(T)</code>), 
or a pair of 0 values if no storage can be obtained or if <code>n &lt;= 0</code>.
</p></blockquote></blockquote>
<p>
I read this as prohibiting to return a buffer of which capacity is less than <code>n</code>, because 
such a buffer is not sufficient to store <code>n</code> objects.
<p/>
The corresponding description in <a href="https://www.boost.org/sgi/stl/get_temporary_buffer.html">SGI STL</a>
is clear on this point, but I think it is a bit too verbose:
</p>

<blockquote class="note"><p>
(for the return value, a pair <code>P</code>) [...] the buffer pointed to by <code>P.first</code> is large enough 
to hold <code>P.second</code> objects of type <code>T</code>. <code>P.second</code> is greater than or equal to 0, 
and less than or equal to <code>len</code>.
</p></blockquote>

<p>
There seems to be two different targets of the "up to n" modification:
The capacity of obtained buffer, and the actual number that the caller
will store into the buffer.
<p/>
First I read as the latter, and got surprised seeing that libstdc++
implementation can return a smaller buffer. I started searching about
<code>get_temporary_buffer()</code>. After reading a quote from TC++PL at
<a href="http://stackoverflow.com/questions/3264299/why-do-i-need-stdget-temporary-buffer">stackoverflow</a>, 
I realized that the former is intended.
<p/>
Such misinterpretation seems common:
</p>
<ul>
<li>The above question is likely started from same misinterpretation.</li>
<li><p>JIS standard (Japanese translation of ISO&#47;IEC standard) says nothing
    like "up to". I think the editor misinterpreted the original wording,
    and omitted words for "up to" as it is redundant. (If a buffer is
    sufficient to store <code>n</code> objects, it is also sufficient to store
    up to <code>n</code> objects.)</p></li>
<li><p>Rogue Wave implementation doesn't return smaller buffer, instead, it
    can return larger buffer on some circumstances. Apache 
	<a href="http://stdcxx.apache.org/">STDCXX</a> is a derived version of that
    implementation, and <a href="https://stdcxx.apache.org/doc/stdlibref/get-temporary-buffer.html">publicly accessible</a>:
</p>
<blockquote class="note"><p>
Specializations of the <code>get_temporary_buffer()</code> function template
attempt to allocate a region of storage sufficiently large to store at
least <code>n</code> adjacent objects of type <code>T</code>.
</p></blockquote>
<p>
I know one commercial compiler package based on Rogue Wave implementation, 
and its implementation is essentially same as the above.
</p>
</li>
</ul>

<p><i>[2014-05-18, Daniel comments and suggests concrete wording]</i></p>


<p>
The provided wording attempts to clarify the discussed capacity freedom, but it also makes it clearer that the returned
memory is just "raw memory", which is currently not really clear. In addition the wording clarifies that the deallocating
<code>return_temporary_buffer</code> function does not throw exceptions, which I believe is the intention when the preconditions
of the functions are satisfied. Then, my understanding is that we can provide to <code>return_temporary_buffer</code> a
null pointer value if that was the value, <code>get_temporary_buffer()</code> had returned. Furthermore, as STL noticed, the current 
wording seemingly allows multiple invocations of <code>return_temporary_buffer</code> with the same value returned by 
<code>get_temporary_buffer</code>; this should be constrained similar to the wording we have for <code>operator delete</code> (unfortunately
we miss such wording for allocators).
</p>

<p><i>[2015-05, Lenexa]</i></p>

<p>
MC: move to ready? in favor: 14, opposed: 0, abstain: 0 
</p>


<p id="res-2072"><b>Proposed resolution:</b></p>
<p>This wording is relative to N3936.</p>

<ol><li><p>Change  [temporary.buffer] as indicated:</p>

<blockquote>
<pre>
template &lt;class T&gt;
  pair&lt;T*, ptrdiff_t&gt; get_temporary_buffer(ptrdiff_t n) noexcept;
</pre>
<blockquote>
<p>
-1- <i>Effects</i>: <ins>Obtains a pointer to uninitialized, contiguous storage for <code><i>N</i></code> adjacent objects of type 
<code>T</code>, for some non-negative number <code><i>N</i></code>.</ins><del>Obtains a pointer to storage sufficient 
to store up to <code>n</code> adjacent <code>T</code> objects.</del> It is implementation-defined whether over-aligned types are supported (3.11).
<p/>
<ins>-?- <i>Remarks</i>: Calling <code>get_temporary_buffer</code> with a positive number <code>n</code> is a non-binding request to return 
storage for <code>n</code> objects of type <code>T</code>. In this case, an implementation is permitted to return instead storage for a 
non-negative number <code><i>N</i></code> of such objects, where <code><i>N</i> != n</code> (including <code><i>N</i> == 0</code>). [<i>Note</i>: The 
request is non-binding to allow latitude for implementation-specific optimizations of its memory management. &mdash; <i>end note</i>].</ins>
<p/>
-2- <i>Returns</i>: <ins>If <code>n &lt;= 0</code> or if no storage could be obtained, returns a pair <code>P</code> such that <code>P.first</code>
is a null pointer value and <code>P.second == 0</code>; otherwise returns a pair <code>P</code> such that <code>P.first</code> refers to the 
address of the uninitialized storage and <code>P.second</code> refers to its capacity <code><i>N</i></code> (in the units of 
<code>sizeof(T)</code>).</ins><del>A <code>pair</code> containing the buffer's address and capacity (in the units of <code>sizeof(T)</code>), or a 
pair of 0 values if no storage can be obtained or if <code>n &lt;= 0</code>.</del>
</p>
</blockquote>

<pre>
template &lt;class T&gt; void return_temporary_buffer(T* p);
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: Deallocates the <del>buffer to which <code>p</code> points</del><ins>storage referenced by <code>p</code></ins>.
<p/>
-4- <i>Requires</i>: <del>The buffer shall have been previously allocated by</del><ins><code>p</code> shall be a pointer value 
returned by an earlier call to</ins> <code>get_temporary_buffer</code> <ins>which has not been invalidated by an intervening call to
<code>return_temporary_buffer(T*)</code></ins>.
<p/>
<ins>-?- <i>Throws</i>: Nothing.</ins>
</p>
</blockquote>

</blockquote>
</li>
</ol>






</body>
</html>
