Why do compilers now accept to call str() member on a returned std::ostream& from std::stringstream::operator<<()?

Viewed 1674

Consider the following line:

std::string s = (std::stringstream() << "foo").str();

This should not compile because std::stringstream::operator<<() is inherited by std::ostream and returns a std::ostream& which does not have an str() member.

It seems the main compilers are now accepting this code where they didn't in the past. What standard change happened to make this compile?

I made some tests with GCC, Clang and MSVC and I could find the version where the change happened:

Compiler Rejects until (version) Accepts from (version)
GCC 11.1 11.2
Clang 12.0.1 13.0.0
MSVC v19.14 v19.15

You can find the test here

1 Answers

They all added the rvalue overload (see here) at around the same time.

The rvalue overload was introduced in added to C++11 and returns the same type of stream as its left-hand operand.

As has been noted in the comments, the reason for it being added to the compilers seemingly after a whole decade is that it was added to C++11 retroactively and very recently, probably after being approved for inclusion in C++20.

I'm turning this into a community wiki in case anyone has the inclination and patience to search for the reasoning behind the retroactive addition and amend the answer.

Related