15

I noticed something when trying to use the stringstream object. Here is a useless example to explain this:

stringstream ss ;
ss << "my string" ;
cout << ss.str() << endl ;

Is not equivalent to

cout << (stringstream() << "my string").str() << endl ;

This leads to a compilation error complaining that ‘class std::basic_ostream’ has no member named ‘str’.

I can't easily explain this. This is not critical for my application but I'm pretty sure this is hiding a c++ trick interesting to be understood.

Note: i'm using gcc with c++14

Antonio
  • 19,451
  • 13
  • 99
  • 197
Falco
  • 277
  • 5
  • 12

2 Answers2

22

The operator<< is not defined for std::stringstream, but for its base class std::ostream, hence it does not return a reference to the std::stringstream and therefore the method str() (which is a method of std::stringstream) is not found.

Technically, the above is actually std::basic_stringstream<CharT,Traits> and std::basic_ostream<CharT,Traits>, but you get the idea :)

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
6

The problem with this:

cout << (stringstream() << "my string").str() << endl;

It is that the expression stringstream() << "my string" returns a std::ostream& object, not a std::stringstream.

You can rectify this by defining some appropriate overloads:

template<typename Type>
std::stringstream& operator<<(std::stringstream& ss, const Type& type)
{
    static_cast<std::ostream&>(ss) << type;
    return ss;
}

template<typename Type>
std::stringstream& operator<<(std::stringstream&& ss, const Type& type)
{
    static_cast<std::ostream&>(ss) << type;
    return ss;
}

template<typename Type>
std::stringstream& operator>>(std::stringstream& ss, Type& type)
{
    static_cast<std::istream&>(ss) >> type;
    return ss;
}

template<typename Type>
std::stringstream& operator>>(std::stringstream&& ss, Type& type)
{
    static_cast<std::istream&>(ss) >> type;
    return ss;
}

Now, when you use the << and >> operators on a std::stringstream object, it will call these overloads and they will return a std::stringstream& so you can use its interface directly.

Galik
  • 47,303
  • 4
  • 80
  • 117