§27.7.3.9
defines the following overload for operator<<
:
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
Effects: os << x
Returns: os
(§27.7.2.6
defines the rvalue overload for operator>>
.)
Basically, it just forwards to an lvalue overload. I consider this overload to be pretty dangerous (the istream
one even more so than the ostream
one, actually), consider the following:
#include <sstream>
#include <iostream>
int main(){
auto& s = (std::stringstream() << "hi there!
");
std::cout << s.rdbuf(); // oops
}
Live example on Ideone (perfect example of undefined behaviour. Prints nothing for me on MSVC10).
The above example might look contrived, but it shouldn't be too hard to get into this situation in generic code or when passing the (std::stringstream() << "text")
to a function that provides an lvalue and an rvalue overload and stores the std::ostream
or std::istream
in different ways according to the overload.
Now, what would be an argument agains returning a basic_ostream<charT, traits>&&
and specifying the following?
Returns: move(os)
(And the same for basic_istream
.)
Is there anything I'm overlooking? At the current state, in my eyes, it just looks dangerous and like a defect. I skimmed through the LWG issue list and found this proposal (hi @HowardHinnant!). It indeed returns an rvalue, however only for the added benefit of being able to chain this special operator, not specifically addressing the safety issue I described above (though it certainly does solve it). Additionally, it's marked as closed and for reconsideration for the next standard. As such, I thought I'd ask here:
Is there any good reason why the above mentioned overload returns an lvalue reference?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…