C++ stringstream inline

不羁的心 提交于 2019-12-23 10:07:41

问题


I would like to use std::stringstream to create formatted strings, but use the class inline so I don't have stringstream local variables flying around. What I mean is this:

#include <iostream>
#include <ostream>
#include <string>
#include <sstream>

int main(int argc, char* argv[])
{
    std::string test = ((std::ostringstream&)
         (std::ostringstream("") << "This is a test: " << 50.1 << "abc")
         ).str();
    std::cout << test << std::endl;
    return 0;
}

This compiles fine in GCC, however the output is the following:

"0x401d0a50.1abc"

So it seems that stringstream treats the first string as a pointer and outputs the address. Subsequent operator<<'s work fine.

How do I fix this? Thanks!


回答1:


The reason is that the << operator is a member for void const*, but a free function taking an std::ostream& as the left hand argument for char const*. Your std::ostringstream( "" ) is a temporary: you can call member functions (even non-const member functions) on it, but a temporary cannot be used to initialize the non-const reference of the global function.

EDIT:

Two points: first, as has been pointed out, g++ does do what you want if you specify -std=c++11. As T.C. points out, this is specified in §27.7.3.9, which provides a template overload for all << with an rvalue reference for the std::istream parameter. And second, the classic work around is to start the expression std::ostringstream( "" ).flush() <<.... flush is a member function (and so can be called on a temporary) which returns an std::ostream& (so everything else chains nicely); it also does nothing on a std::ostringstream.




回答2:


Found it. The C++11 standard special-cases rvalue streams with an extra template operator<< overload. §27.7.3.9 of the standard:

Rvalue stream insertion [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

It's obviously a better match than the member operator<< that takes a const void * and hence is selected by overload resolution in C++11 mode. In C++98 mode this overload doesn't exist (since there are no rvalue references) and the only viable overload is the member operator<< (since, as James Kanze explains in his answer, the temporary can't bind to the non-const lvalue reference in the free operator<< overload that takes a const char *).



来源:https://stackoverflow.com/questions/24494761/c-stringstream-inline

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!