Here is a reproducible example taken from question about using temporary stringstream object:
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
std::string transform(std::string);
int main()
{
int i{};
cout << transform( static_cast<stringstream &>(stringstream() << i).str() );
}
When trying to compile with clang version 9.0.0 under MacOS High Sierra I got following error:
$ clang++ -std=c++11 x.cc -c
x.cc:12:24: error: non-const lvalue reference to type 'basic_stringstream<...>' cannot bind to a temporary of type 'basic_stringstream<...>'
cout << transform( static_cast<stringstream &>(stringstream() << i).str() );
^ ~~~~~~~~~~~~~~~~~~~
1 error generated.
When g++ 9.2.0 is used on same machine (also on Linux) everything compiles fine.
Seems that changing cast from stringstream &
to const stringstream &
or to stringstream &&
solves problem.
The question is if this is compiler bug or maybe clang is more strict about some standard rules?
Yes, I think that is a bug in libc++.
According to [ostream.rvalue] there is an overload:
template<class charT, class traits, class T>
basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&& os, const T& x);
But libc++ implements this similar to:
template <class _Stream, class _Tp>
enable_if_t</*...*/, _Stream&&>
operator<<(_Stream&& __os, const _Tp& __x)
{
// ...
}
The implementation makes this overload a better candidate than the in-class operator<<
of ostream
in overload resolution if a stream rvalue is used with <<
, while the signature in the standard wouldn't be, and it also returns a rvalue reference, when it should return a lvalue reference. It also returns a reference of same type as was passed to it, while it should return a reference to its ostream
base class, according to the standard quote.
The rvalue reference can not be bound to a non-const lvalue reference, hence the error.
The bug has already been reported here and there is an open LWG issue regarding the behavior here, which seems to suggest that in the future the standard might be adjusted to mandate libc++'s current behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With