This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.

### 1251. move constructing `basic_stringbuf`

Section: 31.8.2.2 [stringbuf.cons] Status: NAD Submitter: Martin Sebor Opened: 2009-10-29 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [stringbuf.cons].

View all issues with NAD status.

Discussion:

I just came across issue 1204 -- Global permission to move, which seems to address the concern raised by the example in c++std-lib-25030.

IIUC, the example violates the permission to assume that arguments bound to rvalue references are unnamed temporaries granted to implementations by the resolution of issue 1204 - Global permission to move.

I.e., the `ostringstream(ostringstream &&rhs)` ctor can leave the `rhs` pointers pointing to the newly constructed object's buffer just as long as the dtor doesn't change or invalidate the buffer. The caller may not make any assumptions about rhs after the move beyond it being safe to destroy or reassign.

So unless I misunderstood something, I still think the `basic_stringbuf` move ctor is overspecified. Specifically, I think the third sentence in the Effects clause and the last 6 bullets in the Postconditions clause can, and IMO should, be stricken.

[ 2010-01-31 Moved to Tentatively NAD after 5 positive votes on c++std-lib. Rationale added below. ]

Rationale:

The sense of 1251 appears to be that the `basic_stringbuf` move constructor offers more guarantees than the minimum. This is true, and quite correct. The additional words guarantee that the internal buffer has genuinely transferred from one object to another, and further operations on the original will not affect the buffer of the newly created object. This is a very important guarantee, much as we see that a moved-from `unique_ptr` is guaranteed to be empty.

Proposed resolution:

Strike from 31.8.2.2 [stringbuf.cons]:

>     basic_stringbuf(basic_stringbuf&& rhs);

> > Effects: Move constructs from the rvalue `rhs`. It is implementation-defined whether the sequence pointers in `*this` (`eback()`, `gptr()`, `egptr()`, `pbase()`, `pptr()`, `epptr()`) obtain the values which `rhs` had. Whether they do or not, `*this` and `rhs` reference separate buffers (if any at all) after the construction. The openmode, locale and any other state of `rhs` is also copied.

> > Postconditions: Let `rhs_p` refer to the state of `rhs` just prior to this construction and let `rhs_a` referto the state of `rhs` just after this construction.

> > - `str() == rhs_p.str()`
> > - `gptr() - eback() == rhs_p.gptr() - rhs_p.eback()`
> > - `egptr() - eback() == rhs_p.egptr() - rhs_p.eback()`
> > - `pptr() - pbase() == rhs_p.pptr() - rhs_p.pbase()`
> > - `epptr() - pbase() == rhs_p.epptr() - rhs_p.pbase()`
> > - if `(eback()) eback() != rhs_a.eback()`
> > - if `(gptr()) gptr() != rhs_a.gptr()`
> > - if `(egptr()) egptr() != rhs_a.egptr()`
> > - if `(pbase()) pbase() != rhs_a.pbase()`
> > - if `(pptr()) pptr() != rhs_a.pptr()`
> > - if `(epptr()) epptr() != rhs_a.epptr()`