7

是否可以编写一个采用字符串流的方法并让它看起来像这样,

void method(string str)
void printStringStream( StringStream& ss)
{
    method(ss.str());
}

并且可以这样称呼

stringstream var;
printStringStream( var << "Text" << intVar << "More text"<<floatvar);

我查找了 << 运算符,它看起来像返回一个ostream&对象,但我可能读this错了,或者只是没有正确实现它。

我真正想要的只是一种干净的方式将东西连接在一起作为一个字符串并将其传递给一个函数。我能找到的最干净的东西是一个 stringstream 对象,但这仍然有很多不足之处。

笔记:

我不能使用太多c++11答案,因为我在 Visual Studio 2010 上运行(违背我的意愿,但仍然如此)

我可以访问Boost所以疯了。

只要它可以清理这个烂摊子,我就不会反对自定义方法。

编辑:

将@Mooing Duck 的答案与@PiotrNycz 语法混合在一起,我实现了编写这样的代码的目标,

try{

    //code

}catch(exception e)
{   
    printStringStream( stringstream() << "An exception has occurred.\n"
                            <<"    Error: " << e.message 
                            <<"\n If this persists please contact "<< contactInfo
                            <<"\n Sorry for the inconvenience");
}

这是我所希望的那样干净和可读。

希望这可以帮助其他人清理书写消息。

4

5 回答 5

8

啊,花了我一分钟。由于operator<<是为所有ostream 类型重载的自由函数,因此它不会返回 a std::stringstream,而是std::ostream像您说的那样返回 a 。

void printStringStream(std::ostream& ss)

现在很明显,generalostream没有.str()成员,但他们确实有一种神奇的方法可以将整个流复制到另一个流:

std::cout << ss.rdbuf();

这是完整代码的链接,显示它可以正常编译和运行http://ideone.com/DgL5V

编辑

如果你真的需要函数中的字符串,我可以想到几个解决方案:

首先,单独进行流式传输:

stringstream var;
var << "Text" << intVar << "More text"<<floatvar;
printStringStream(var);

第二:将流复制到字符串(可能的性能问题)

void printStringStream( ostream& t)
{
    std::stringstream ss;
    ss << t.rdbuf();
    method(ss.str());
}

第三:使其他功能也采取流

于 2012-09-20T19:55:40.947 回答
3

在 std::stringstream 上制作你的包装器。在这个新类中,您可以定义operator <<您需要的任何内容:

class SSB {
public:
   operator std::stringstream& () { return ss; }

   template <class T>
   SSB& operator << (const T& v) { ss << v; return *this; }
   template <class T>
   SSB& operator << (const T* v) { ss << v; return *this; }
   SSB& operator << (std::ostream& (*v)(std::ostream&)) { ss << v; return *this; }
   // Be aware - I am not sure I cover all <<'s       
private:
   std::stringstream ss;
};

void print(std::stringstream& ss)
{
    std::cout << ss.str() << std::endl;
}

int main() {
  SSB ssb;
  print (ssb << "Hello" << " world in " << 2012 << std::endl);
  print (SSB() << "Hello" << " world in " << 2012 << std::endl);
}
于 2012-09-20T20:24:55.937 回答
3

为了便于编写可以插入到流中的对象,所有这些类都operator<<ostream&. (如果不存在更接近的匹配,子类可以使用运算符重载。)这些operator<<重载都返回ostream&

您可以做的是使函数采用 anostream&并将dynamic_cast<>其转换为stringstream&. 如果传入了错误的类型,bad_cast则抛出。

void printStringStream(ostream& os) {
    stringstream &ss = dynamic_cast<stringstream&>(os);
    cout << ss.str();
}

注意:static_cast<>可以使用,它会更快,但在您传递的东西不是stringstream.

于 2012-09-20T19:54:49.120 回答
2

既然你知道你有一个stringstream,只需转换返回值:

stringstream var;
printStringStream(static_cast<stringstream&>(var << whatever));
于 2012-09-20T20:04:23.650 回答
0

只是为了添加:就个人而言,我会创建一个流,它调用我需要在销毁时调用的任何函数:

#include <sstream>
#include <iostream>

void someFunction(std::string const& value)
{
    std::cout << "someFunction(" << value << ")\n";
}

void method(std::string const& value)
{
    std::cout << "method(" << value << ")\n";
}

class FunctionStream
    : private virtual std::stringbuf
    , public std::ostream
{
public:
    FunctionStream()
        : std::ostream(this)
        , d_function(&method)
    {
    }
    FunctionStream(void (*function)(std::string const&))
    : std::ostream(this)
    , d_function(function)
    {
    }
    ~FunctionStream()
    {
        this->d_function(this->str());
    }
private:
    void (*d_function)(std::string const&);
};

int main(int ac, char* av[])
{
    FunctionStream() << "Hello, world: " << ac;
    FunctionStream(&someFunction) << "Goodbye, world: " << ac;
}

值得注意的是,发送到临时对象的第一个对象必须是一组特定的类型,即类std::ostream知道的类型之一: 通常,移位运算符将一个std::ostream&作为第一个参数,但一个临时对象不能绑定到 this类型。但是,有许多成员运算符,作为成员,不需要绑定到引用!如果要首先使用用户定义的类型,则需要提取一个临时引用,这可以通过使用成员输入运算符之一来完成。

于 2012-09-20T23:05:39.753 回答