malat
malat

Reputation: 12506

C++11: invalid operands to binary expression ostream and ostringstream

Why is the following no longer a valid C++11 code (compiles fine as C++98):

#include <sstream>
#include <iostream>

int main()
{
  std::ostringstream os;
  os << "Hello World!";
  std::cout << os << std::endl;
  return 0;
}

for reference here is (truncated) what I get with clang:

$ clang++ -stdlib=libc++ -std=c++11 t.cxx
t.cxx:8:13: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'std::ostringstream' (aka 'basic_ostringstream<char>'))
  std::cout << os << std::endl;
  ~~~~~~~~~ ^  ~~
/usr/include/c++/v1/ostream:190:20: note: candidate function not viable: no known conversion from 'std::ostringstream' (aka 'basic_ostringstream<char>') to
      'const void *' for 1st argument; take the address of the argument with &
    basic_ostream& operator<<(const void* __p);

Upvotes: 5

Views: 9171

Answers (2)

Andrew Tomazos
Andrew Tomazos

Reputation: 68648

The code that does what you intended to do is as following:

#include <sstream>
#include <iostream>

int main()
{
  std::ostringstream os;
  os << "Hello World!";
  std::cout << os.str() << std::endl;
  return 0;
}

Upvotes: 3

Sebastian Redl
Sebastian Redl

Reputation: 71989

It may compile in C++03, but it doesn't make one bit of sense. C++11 just used a new feature to make the code that makes no sense, not compile in the first place.

See, std::ostringstream (and all other stream classes) used to have an implicit conversion to void*. What this returned wasn't a proper pointer, though; it was just either null if the stream was in an invalid state, or not null if it was valid. That's what allowed you to write e.g.

std::ofstream ofs("filename");
if (ofs) ...

However, the conversion to void* was problematic, because you do other stupid stuff with a void*. Even before C++11, the safe-bool idiom was discovered that would have been better. But for C++11, explicit conversions were added, which were a lot better. So for C++11, the conversion to void* was replaced by an explicit conversion to bool, which allows the same useful code to compile without allowing useless code (such as yours) to compile. And that's why the code doesn't work anymore in C++11.

This is not a bad thing. It's a good thing. You discovered that the code you had doesn't make sense, without the pains of it misbehaving at runtime.

Upvotes: 13

Related Questions