从组件构造字符串的最佳方法,iostream 样式

Best way to construct a string from components, iostream style

在我的代码中的许多地方,我需要构造可理解的错误消息,但始终创建​​字符串流是乏味的,尤其是当您必须在构造函数的初始化列表中创建字符串时。如果这可以用一个简单的函数来完成,它将使代码的可读性大大提高。

给定以下众多示例用例之一,实现以下 createString 功能的优雅方式是什么?

struct Base {
    std::string msg;
    Base(const std::string& msg) : msg(msg) { }
};

struct Derived: public Base {
    Derived(int value)
    // Parent constructor requires a string so we have to create it inline
    : Base(createString("This is class " << value))
    { }
};

int main(void)
{
    int i = 5; // some number obtained at runtime
    Derived d(i);
    std::cout << d.msg << "\n";
    return 0;
}

到目前为止我已经想出了这个 C++11 版本,但它有一些缺点(需要预处理器宏,有时字符串必须包含在 std::string() 中,等等)所以我'我想知道是否有人提出了更好的选择?

#include <sstream>
#define createString(a) \
    (static_cast<const std::ostringstream&>(std::ostringstream() << a).str())

围绕 std::stringstream 提供一个包装器,并使其可以隐式转换为 std::string。它稍微改变了语法:

class WrapSStream
{
public:
  template <typename T>
  WrapSStream& operator<<(const T& val)
  {
    ss << val;
    return *this;
  }

  operator string(){return ss.str();}

private: 
  stringstream ss;
};

struct Base {
    string msg;
    Base(const string& msg) : msg(msg) { }
};

struct Derived: public Base {
    Derived(int value)
    // Parent constructor requires a string so we have to create it inline
      : Base(WrapSStream() << "This is class " << value)
    { }
};

int main(void)
{
    int i = 5; // some number obtained at runtime
    Derived d(i);
    cout << d.msg << "\n";
    return 0;
}

输出 This is class 5.

Live demo