<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Tue, 1 Jul 2025 at 21:27, Alexey Sidorin via Std-Proposals &lt;<a href="mailto:std-proposals@lists.isocpp.org">std-proposals@lists.isocpp.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>

  

    
  
  <div>
    <div lang="x-unicode">
      <p> <font face="monospace">Hello everyone,</font><br>
        <font face="monospace">I would like to propose adding
          extract_top() method to `<a>std::priority_queue</a>` backed
          by a set of freestanding functions in &lt;algorithm&gt;
          header.<br>
        </font><br>
        <font face="monospace">1. Problem statement</font><br>
      </p>
      <p><font face="monospace">In order to extract the top element from
          <code class="gmail-notranslate"><a>std::priority_queue</a></code>,
          we have to write something like this:</font></p>
      <div class="gmail-notranslate"><code class="gmail-notranslate">auto x = queue.top(); // Copy constructor
          or copy assignment.</code></div>
      <div class="gmail-notranslate"><code class="gmail-notranslate">queue.pop(); </code>
        <div> </div>
      </div>
      <br>
      <font face="monospace">Unfortunately, we cannot move a top value
        from the queue because <code class="gmail-notranslate">top()</code>
        is of <code class="gmail-notranslate">const_reference</code> type (<a href="https://eel.is/c++draft/priority.queue#priqueue.members" rel="nofollow" target="_blank">https://eel.is/c++draft/priority.queue#priqueue.members</a>). </font><br>
      <font face="monospace">The first problem is that this can cause a
        performance hit if the value type is expensive to copy (a
        structure containing large strings, etc.).</font><br>
      <font face="monospace">The second problem is that this also makes
        impossible to use priority_queue with move-only types.</font><br>
      <font face="monospace">I&#39;ve made a search in chromium sources
        showing that almost all heap structure usage have a similar
        pattern:<br>
      </font><br>
      <code class="gmail-notranslate"> <a>std::pop_heap(msg_queue.begin()</a>,
        msg_queue.end());<br>
        *event = <a>std::move(msg_queue.back())</a>;<br>
        msg_queue.pop_back();</code><br>
      <font face="monospace">(<a href="https://github.com/search?q=repo%3Achromium%2Fchromium%20pop_heap&amp;type=code" target="_blank">https://github.com/search?q=repo%3Achromium%2Fchromium%20pop_heap&amp;type=code</a>)</font><br>
      <p><font face="monospace">I think this clearly indicates that we
          can have a better interface here.</font></p></div></div></blockquote><div><br></div><div><br></div><div>See  <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3182r1.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3182r1.html</a></div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div lang="x-unicode">
      <p><font face="monospace">2. Proposed changes</font></p>
      <p><font face="monospace">The idea is to provide `extract_top()`
          method behaving like pseudo-code below:</font></p>
      <div class="gmail-notranslate"><code class="gmail-notranslate">T extract_top() {</code></div>
      <div class="gmail-notranslate"><code class="gmail-notranslate"> T val = <a>std::move_if_noexcept(container.front())</a>;</code></div>
      <div class="gmail-notranslate"><code class="gmail-notranslate"> pop();</code></div>
      <div class="gmail-notranslate"><code class="gmail-notranslate"> return val;</code></div>
      <div class="gmail-notranslate"><code class="gmail-notranslate">} </code>
        <div> </div>
      </div>
      <p><font face="monospace">I&#39;ve made a reference implementation in
          my libc++ fork </font><font face="monospace">if anyone is
          interested</font><font face="monospace">: <a href="https://github.com/a-sid/llvm-project/pull/1/files" target="_blank">https://github.com/a-sid/llvm-project/pull/1/files</a>.</font></p>
      <p><font face="monospace">The summary of the changes proposed is
          the following:</font></p>
      <font face="monospace">1. Add a method `extract_top()` to `<a>std::priority_queue</a>`:</font><br>
      <font face="monospace">template &lt;class _Tp, class _Container,
        class _Compare&gt;<br>
        constexpr _Tp priority_queue&lt;_Tp, _Container,
        _Compare&gt;::extract_top();</font><br>
      <p><font face="monospace">This method will return the top value of
          the queue and remove it from the queue with restoring the heap
          property of the data structure.<br>
        </font></p>
      <p><font face="monospace">2. Add symmetric functions to
          &lt;algorithm&gt; header:</font></p>
      <font face="monospace">template &lt;class RandomAccessIterator&gt;<br>
            constexpr
        iterator_traits_t&lt;RandomAccessIterator&gt;::value_type<br>
            extract_heap_top(RandomAccessIterator first,
        RandomAccessIterator last);<br>
        <br>
      </font><font face="monospace">template &lt;class
        RandomAccessIterator, class Compare&gt;<br>
            constexpr
        iterator_traits_t&lt;RandomAccessIterator&gt;::value_type<br>
            extract_heap_top(RandomAccessIterator first,
        RandomAccessIterator last, Compare comp);</font><br>
      <p><font face="monospace">These functions will return the top
          value of the queue and remove it from the queue with restoring
          the heap property of the data structure. Unlike pop_heap,
          these functions will leave the last element in an unspecified
          state.<br>
        </font></p>
      <p><font face="monospace">3. Add corresponding range object
          template:</font></p>
      <font face="monospace">  template&lt;random_access_iterator I,
        sentinel_for&lt;I&gt; S, class Comp = <a>ranges::less</a>,<br>
                  class Proj = identity&gt;<br>
            requires sortable&lt;I, Comp, Proj&gt;<br>
            constexpr iterator_traits&lt;I&gt;::value_type<br>
              <a>ranges::extract_heap_top(I</a>
        first, S last, Comp comp = {}, Proj proj = {});<br>
        <br>
          template&lt;random_access_range R, class Comp = <a>ranges::less</a>,
        class Proj = identity&gt;<br>
            requires sortable&lt;iterator_t&lt;R&gt;, Comp, Proj&gt;<br>
            constexpr
        iterator_traits&lt;iterator_t&lt;R&gt;&gt;::value_type<br>
              <a>ranges::extract_heap_top(R&amp;&amp;</a>
        r, Comp comp = {}, Proj proj = {});<br>
      </font>
      <p><font face="monospace">These functions will return the top
          value of the queue and remove it from the queue with restoring
          the heap property of the data structure. Again, the last
          element is left in an unspecified state.</font></p>
      <p><font face="monospace">3. Related work</font></p>
      <font face="monospace">There was already another proposal which
        pointed that const reference interface makes priority_queue
        unusable for move-only types: <a href="https://lists.isocpp.org/std-proposals/2021/02/2390.php" target="_blank">https://lists.isocpp.org/std-proposals/2021/02/2390.php</a>.
        As I understand, this proposal haven&#39;t met strong objections,
        but it looks like it was abandoned.<br>
      </font>
      <p dir="auto"><font face="monospace">Thank you in advance for any
          feedback.<br>
        </font></p>
      <p dir="auto"><font face="monospace">---<br>
          Best regards,<br>
          Aleksei Sidorin.<br>
        </font></p>
    </div>
    <p></p>
  </div>

-- <br>
Std-Proposals mailing list<br>
<a href="mailto:Std-Proposals@lists.isocpp.org" target="_blank">Std-Proposals@lists.isocpp.org</a><br>
<a href="https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals" rel="noreferrer" target="_blank">https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals</a><br>
</blockquote></div></div>

