使用匿名字符串流来构造字符串

时间:2013-10-29 17:42:56

标签: c++ string sstream

我想直接读到一个代码如下的字符串:

std::string myString(( std::ostringstream() << myInt << " "
                                            << myFloat << " "
                                            << std::boolalpha << myBool ).str());

但VS2012正在向我投诉basic_ostream没有str()方法。

有没有办法用匿名字符串流做到这一点?

3 个答案:

答案 0 :(得分:13)

流的operator<<返回std::ostream &,但没有str()成员函数。你需要使用演员。

static_cast<std::ostringstream&>(std::ostringstream() << etc).str()

使用临时流时C ++ 03和C ++ 11之间的差异!

C ++ 03

但要注意(在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"

在线演示:

  • GCC output static_cast<std::ostringstream&>(std::ostringstream() << "XYZ" << "ABC").str()
  • Clang output -std=c++11

C ++ 11

在C ++ 11中,通过添加非成员函数(27.7.3.9)修复了此问题,该函数将第一个参数作为右值引用,然后将调用转发给相应的函数,无论是成员还是非成员。因此,它打印-std=c++11后跟XYZ

答案 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 ;
}