如何在表达式中使用 ostringstream

How to use an ostringstream in just an expression

我使用 std::ostringstream 来格式化字符串,它从 ostream 继承了它的 << 运算符,因此它们 return 是 ostream 而不是 ostringstream,这意味着我无法对结果调用 ostringstream::str。这通常不是问题,因为我通常可以这样做:

ostringstream stream;
stream << whatever;
string str = stream.str();

但偶尔我需要*只在一个表达式中使用它,这比较困难。我可以

string str = ((ostringstream&) (ostringstream() << whatever)).str();

但如果 << 超载 return 一些 ostream 不是 ostringstream,就会发生不好的事情。我唯一能想到的另一件事就是

string str = ([&] () -> string {ostringstream stream; stream << whatever; return stream.str();})();

但这不可能是高效的,而且肯定是非常糟糕的 c++ 代码。


*好吧,我不需要,但这样会方便很多。

The only other thing I can think to do is something like

string str = ([&] () -> string {ostringstream stream; stream << whatever; return stream.str();})();

but this can't possibly be efficient, and is certainly very bad c++ code.

实际上,没有。一旦优化器查看了它,它就会和原始代码一样快。它不是 "very bad c++ code"。它被称为立即调用的 Lambda 表达式或 IILE。这是一个成语,实际上是相当不错的做法。

虽然格式更像这样会更好:

// One of the benefits of IILEs is that `const` can be used more frequently
string const str = [&] {
    ostringstream stream;
    stream << whatever;
    return stream.str();
}();

有些人更喜欢使用 std::invoke 来调用 lambda:

string const str = std::invoke([&] {
    ostringstream stream;
    stream << whatever;
    return stream.str();
});

使用

string str = ([&] () -> string
             {
               ostringstream stream;
               stream << whatever;
               return stream.str();
              })();

没问题。但是,我认为最好为该操作命名,创建一个具有该名称的函数,然后调用该函数。

namespace MyApp
{
    template <typename T>
    std::string to_string(T const& t)
    {
        ostringstream stream;
        stream << t;
        return stream.str();
    }
}

然后使用

string str = MyApp::to_string(whatever);

假设你有

std::string get_str(std::ostream& out) {
    retrun static_cast<std::stringbuf*>(out.rdbuf())->str();
}

你可以使用

std:: string s = get_str(std::ostringstream{} << ...);