C ++在<<之后使用stringstream作为参数

时间:2012-09-20 19:46:24

标签: c++ concatenation stringstream

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

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

可以像这样调用

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

我抬头看了&lt;&lt;运算符,看起来它返回一个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");
}

这是我所希望的那样清洁和可读。

希望这有助于其他人清理写信息。

5 个答案:

答案 0 :(得分:8)

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

void printStringStream(std::ostream& ss)

现在显然,普通ostream没有.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());
}

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

答案 1 :(得分:3)

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

您可以做的是让该功能将ostream&dynamic_cast<>带到stringstream&。如果传入了错误的类型,则抛出bad_cast

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

注意:可以使用static_cast<>,它会更快,但如果您传递的内容不是stringstream,则不会出现错误。

答案 2 :(得分: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);
}

答案 3 :(得分:2)

由于您知道自己有stringstream,因此只需转换返回值:

stringstream var;
printStringStream(static_cast<stringstream&>(var << whatever));

答案 4 :(得分: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知道:通常,移位运算符需要{{1作为第一个参数,但临时不能绑定到此类型。但是,有许多成员运算符,作为成员,不需要绑定到引用!如果要首先使用用户定义的类型,则需要提取可以使用其中一个成员输入运算符完成的引用临时。