我想直接读到一个代码如下的字符串:
std::string myString(( std::ostringstream() << myInt << " "
<< myFloat << " "
<< std::boolalpha << myBool ).str());
但VS2012正在向我投诉basic_ostream
没有str()
方法。
有没有办法用匿名字符串流做到这一点?
答案 0 :(得分:13)
流的operator<<
返回std::ostream &
,但没有str()
成员函数。你需要使用演员。
static_cast<std::ostringstream&>(std::ostringstream() << etc).str()
但要注意(在C ++ 03中)std::ostringstream()
创建一个临时对象,这意味着第一个operator<<
的非成员重载不能被调用<<
因为它们都接受第一个参数std::ostream&
,它不能绑定到临时对象。临时对象将能够仅调用成员函数。
这意味着,以下内容将为您提供地址而非字符串:
static_cast<std::ostringstream&>(std::ostringstream() << "XYZ").str()
因为以char const*
作为参数的重载是非成员函数,无法调用,所以上面的代码最终调用了成员函数{{1} }作为参数,因此void const*
被隐式转换为"XYZ"
,它打印字符串文字的地址。
一旦临时调用成员函数,剩余的链式void const*
可能会调用非成员重载,因为成员函数返回<<
now 可以绑定到std::ostream&
的非成员重载的第一个参数。因此,以下代码将打印地址(而非operator<<
),后跟字符串"XYZ"
:
"ABC"
在线演示:
static_cast<std::ostringstream&>(std::ostringstream() << "XYZ" << "ABC").str()
-std=c++11
在C ++ 11中,通过添加非成员函数(27.7.3.9)修复了此问题,该函数将第一个参数作为右值引用,然后将调用转发给相应的函数,无论是成员还是非成员。因此,它打印-std=c++11
后跟XYZ
:
ABC
-std=c++11
答案 1 :(得分:6)
basic_osstream::operator<<
会返回basic_ostream
,而非ostringstream
。编译器不是骗你的。
我宁愿创建一个StringBuilder类型的设备。
class StringBuilder
{
public:
template <typename T> inline StringBuilder& operator<<(const T& t)
{
mStream << t;
return * this;
}
inline std::string get() const
{
return mStream.str();
}
inline operator std::string () const
{
return get();
}
private:
std::stringstream mStream;
};
现在你可以:
std::string myString (StringBuilder() << myInt << " " << myFloat /*...*/);
Boost中也有类似的设备 - 如果您可以使用它们,那么您最好使用它们。
答案 2 :(得分:0)
我也遇到了这个问题,John的回答似乎还不错,非常感谢! -我尝试使用运算符'<<'到'stringstream'上构建字符串,并且确实在macOS上使用'clang'进行了编译并正常工作,但在ubuntu上使用'gcc'进行了正常工作((与-std = c一起编译) ++ 11在现代更新的编译器上),看起来像在Mac机器上,操作员正在返回字符串流而不是basic_ostream……
这是一个最小的程序,它不使用g ++进行编译,而是使用clang(实验性概念)进行编译,如在Compiler Explorer(godbolt.org)中测试的那样:
#include <iostream>
#include <sstream>
#include <string>
int main()
{
using namespace std;
cout << ((stringstream() << "hola").str()) << endl ;
}