3992. basic_stringbuf::str()&& should enforce 𝒪(1)

Section: 31.8.2.4 [stringbuf.members] Status: New Submitter: Peter Sommerlad Opened: 2023-10-05 Last modified: 2023-10-14

Priority: Not Prioritized

View all other issues in [stringbuf.members].

View all issues with New status.

Discussion:

Recent discussions on llvm-64644 came to the conclusion that basic_stringbuf() && introduced by P0408 might just copy the underlying buffer into a string object and not actually move the allocated space. While the wording tried to encourage that, especially with the postcondition that the buffer must be empty afterwards, it failed to specify that the move is never a copy.

I suggest to amend the specification to enforce implementors to do the 𝒪(1) thing. There might be ABI issues for those who still copy.

Some investigation into 23.2.2.2 [container.reqmts] p.16 and 27.4.3.1 [basic.string.general] shows that a basic_string as a standard container should move with 𝒪(1).

Unfortunately, we cannot say

str().data() == buf.data() before calling str()

as a postcondition due to SSO. Maybe a note could be added to eliminate the confusion.

Proposed resolution:

This wording is relative to N4958.

  1. Modify 31.8.2.4 [stringbuf.members] as indicated:

    basic_string<charT, traits, Allocator> str() &&;
    

    -9- Postconditions: The underlying character sequence buf is empty and pbase(), pptr(), epptr(), eback(), gptr(), and egptr() are initialized as if by calling init_buf_ptrs() with an empty buf.

    -10- Returns: A basic_string<charT, traits, Allocator> object move constructed from the basic_stringbuf's underlying character sequence in buf. This can be achieved by first adjusting buf to have the same content as view().

    [Note: — 23.2.2.2 [container.reqmts] require the move construction of the return value to be 𝒪(1) end note]