Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does writing to temporary stream fail?

Consider the following code:

#include <sstream>
#include <iostream>

class Foo : public std::stringstream {
public:
    ~Foo() { std::cout << str(); }
};

int main()
{
    Foo foo;
    foo << "Test1" << std::endl;

    Foo() << "Test2" << std::endl;

    return 0;
}

When I execute this, it gives me:

004177FC
Test1

I do not understand why the second example gives me gibberish. The temporary should live until the entire expression is evaluated, so why does it not behave the same as the first example?

like image 541
Björn Pollex Avatar asked Mar 03 '11 10:03

Björn Pollex


1 Answers

I tested it.

I can guess that operator<< cannot bind a temporary to a non-const reference, so any externally defined operator<< functions will not work on the Foo temporary, but any class member ones will so if ostream or ostringstream has any internal operator<< members they will work.

Therefore it may be that the overload to a pointer is a member function whilst the special one for const char * is externally declared.

The non-temporary can bind to the non-const reference for the more specialist overload.

If you really need this you can workaround with a wrapper

class Foo :
{
    mutable std::ostringstream oss;
public:
  ~Foo()
  {
    std::cout << oss.str();
  }

  template<typename T>
  std::ostream&
  operator<<( const T& t ) const
  {
      return oss << t;
  }
};

Tested and works. The first operator<< will return you the underlying stream.

I tried this too but it coredumped:

class Foo : std::ostringstream
{
    Foo & nonconstref;
public:
   Foo() : nonconstref( *this ) {}
  ~Foo()
  {
    std::cout << str();
  }

  template<typename T>
  std::ostream&
  operator<<( const T& t ) const
  {
      return nonconstref << t;
  }
};

This also works:

class Foo : public std::ostringstream
{
public:
   Foo()  {}
  ~Foo()
  {
    std::cout << str();
  }

  Foo& ncref()
  {
       return *this;
  }
};

int main()
{
    Foo foo;
    foo << "Test1" << std::endl;

    Foo().ncref() << "Test2" << std::endl;

}
like image 78
CashCow Avatar answered Sep 28 '22 09:09

CashCow