The member functions I was hoping to see were the following
/**
* str() returns a copy of the string contained in the sstream and
* remove_str() moves the string into a temporary string which then
* is treated as a prvalue in the calling expression and will therefore
* be moveable or elidable
*/
std::basic_string<CharT, Traits, Allocator> str() const;
std::basic_string<CharT, Traits, Allocator> remove_str() noexcept;
/**
* Move and copy assigning a string into a stringstream
*/
void str(const std::basic_string<CharT, Traits, Allocator>& other);
void str(std::basic_string<CharT, Traits, Allocator>&& other);
If another class which allows moving to/from a stringstream seems unnecessary, another option is to make std::stringstream accept one or two more template parameters, one of which is the internal storage type that will be used to store the characters and another which is a traits class that encapsulates how the implementation will interact with the storage object. And then rdbuf() could just return a pointer to the internally stored storage object (be it a std::basic_streambuf or a std::basic_string), this would be backwards compatible with other uses of stringstreams since the other two template parameters would default to the ones used right now.