5

我想用这样的代码直接读入一个字符串:

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

但是VS2012给了我一个basic_ostream没有str()方法的投诉。

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

4

3 回答 3

13

for流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&

这意味着,以下内容将为您提供address而不是string

static_cast<std::ostringstream&>(std::ostringstream() << "XYZ").str()

因为char const*作为参数的重载是一个非成员函数,不能被调用,所以上面的代码最终调用了void const*作为参数的成员函数,因此"XYZ"被隐式转换为void const*,打印字符串文字的地址

一旦临时调用成员函数,剩余的链接<< 可能会调用非成员重载,因为成员函数返回std::ostream&现在可以绑定到非成员重载的第一个参数operator<<。所以下面的代码将打印一个地址(而不是"XYZ"),然后是字符串"ABC"

static_cast<std::ostringstream&>(std::ostringstream() << "XYZ" << "ABC").str()

在线演示:

C++11

在 C++11 中,此问题已通过添加一个非成员函数 (27.7.3.9) 得到解决,该函数将第一个参数作为右值引用,然后将调用转发给适当的函数,无论是成员还是非成员。所以它打印XYZ后跟ABC

  • GCC 输出-std=c++11
  • 铿锵 输出 -std=c++11
于 2013-10-29T17:50:05.253 回答
7

basic_osstream::operator<<返回 a basic_ostream,而不是 a 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 中也有类似的设备——如果您可以使用这些设备,您最好使用这些设备。

于 2013-10-29T17:50:07.780 回答
0

我也有这个问题,约翰的回答似乎很好,非常感谢!- 我尝试通过在 'stringstream' 上使用运算符'<<' 来构建一个字符串,它在 macOS 上使用 'clang' 编译并运行良好,但在 ubuntu 上使用 'gcc' 编译并运行良好,(使用 -std=c 编译++11 在现代更新的编译器上),看起来在 Mac 机器上,操作员返回的是 stringstream 而不是 basic_ostream ......

这是一个不使用 g++ 编译但使用 clang(实验概念)编译的最小程序,在 Compiler Explorer (godbolt.org) 中进行了测试:

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

int main()
{
   using namespace std;
   cout << ((stringstream() << "hola").str()) << endl ;
}
于 2019-10-25T14:48:53.497 回答