Reputation: 1020
I am using C++14 (-std=c++1y on both g++ 4.9.1 and clang 3.5).
To start, here is Exhibit A (where the Foo namespace exists):
#include <iostream>
#include <sstream>
namespace Foo
{
struct A
{};
}
void operator<<(std::ostream &os, Foo::A const &a)
{}
int main()
{
Foo::A a;
std::ostringstream() << a;
return 0;
}
Both Clang and g++ barf on this, although for different reasons.
Exhibit B (where there is no Foo namespace):
#include <iostream>
#include <sstream>
struct A
{};
void operator<<(std::ostream &os, A const &a)
{}
int main()
{
A a;
std::ostringstream() << a;
return 0;
}
g++ still barfs, but Clang successfully compiles.
Is this reasonable to expect? What's going on here?
Upvotes: 1
Views: 264
Reputation: 137425
First, the standard supplies a catchall operator<<
for rvalue output streams ([ostream.rvalue])
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
(There's also a matching operator>>
for rvalue input streams - see [istream.rvalue].)
This is the operator<<
that gets called.
Second, as is usual for templates, in the body of this function template, the unqualified lookup for operator<<
in os << x
is done in the template definition context, which doesn't have your operator<<
available. Instead, your overload must be found by ADL, which, in turn, means that it must be in the same namespace as A
.
Your second version should compile, and in both cases the compiler did find your overload just fine. The problem is that libstdc++'s implementation (which boils down to return os << x;
) is non-conforming, because it assumes that os << x
must return os
. There's no such requirement.
Edit: The libstdc++ bug report is here; it has since been fixed in trunk and the fix has been backported to the 4.8 and 4.9 branches.
Upvotes: 1
Reputation: 21803
You are not allowed to bind a temporary object to a non-const reference. In this case std::ostringstream()
creates a temporary object and tries to bind to the non-const reference parameter of operator<<
Upvotes: 0