在C ++中将字符串打印到临时流对象 [英] Printing a string to a temporary stream object in C++

查看:133
本文介绍了在C ++中将字符串打印到临时流对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个特殊类型的ostringstream,我试图输出文本作为一个临时对象,但我有一些麻烦。要明确,这实际上是我想要做的:

  ostringstream()< 对不起! << endl; 

现在在你说:但是Zack,那个代码是完全没有价值!结束了,你怎么知道它是否做了什么?,听我说。我不尝试用纯Ostringstreams这样做,而是一个派生类,其中析构函数实际上为数据提供了一个路径退出对象。所以在现实中,它看起来更像这样:

  specialstringstream()< 对不起! << endl; 

其中specialstringstream有一个析构函数,可以在其他地方转储文本。



我不会深入太多的细节,为什么我这样做。你必须相信我,这对我需要做的事很有意义,它很适合现有的巨大代码库。



这里的问题:当我做这,一切编译和运行,但我得到一个指针地址印在我的输出,而不是缔约方!串。我确定这是发生,因为编译器选择执行流输出的操作符是
ostream&运算符<< (const void * val),而不是 ostream&运算符<< (ostream& out,const char * s)



我有一个模糊的想法为什么,解决它。



这里是一个简短版本的SpecialStringStream对象,它显示的行为:

  class SpecialStringStream:public ostringstream 
{
public:
SpecialStringStream(ostream * regularStream)
{
regularStream_ = regularStream;
}

〜SpecialStringStream()
{
if(regularStream_!= NULL)
(* regularStream_)< str();
}

private:
ostream * regularStream_;
};

当我做类似的操作: SpecialStringStream(someStreamPtr)< 对不起! << endl; ,我在输出中得到一个指针地址,如00444D60,而不是消息。



编辑:因为我太新了一个用户回答我自己的问题,这里是我结算了感谢所有的回应。



我想出了以下解决方案,它工作在Visual C + 8和所有其他编译器,我需要它。我创建了一个模板操作符,它基本上去除了一个常量的const SpecialStringStream,将它转换为一个ostream,并让ostream操作符做他们的事情。在评论中,随意撕裂它,并警告我所有可怕的潜在错误我已经介绍!

 模板< ;类T> 
std :: ostream&运算符<<<(const SpecialStringStream& o,T msg)
{
return static_cast< std :: ostream&>(const_cast< SpecialStringStream&>(o))< msg;
}


解决方案

流动&运算符<< (ostream& out,const char *)不可行,因为您的临时将不会绑定到非const引用 ostream& 。除了声明一个局部变量并使用:



<$ p $你不能真正做到这一点(因为你不能把一个右值赋值给一个左值) p> {
specialstringstream ss;
ss<< Hello world<< std :: endl; // OK,可以绑定到左值
}

可能的解决方案: em>您可以声明另一个重载,接受一个右值引用:

  std :: ostream& operator<<<(specialstringstream& o,const char * s)
{
return o< s; // note:* not *std :: move(o)
}


I have a special type of ostringstream that I am trying to output text to as a temporary object but I'm having some trouble. To be clear, this is essentially what I want to do:

ostringstream() << "PARTY DOWN!" << endl;

Now before you say: "But Zack, that code is totally worthless! The object is destroyed at the end of the line, how would you even know if it did anything?", hear me out. I don't try to do this with plain ostringstreams, but rather a derived class in which the destructor actually provides a path for the data to exit the object. So in reality, it looks a lot more like this:

specialstringstream() << "PARTY DOWN!" << endl;

Where specialstringstream has a destructor which dumps the text elsewhere.

I won't go into too much detail as to why I do this. You'll have to trust me that it makes sense for what I need to do and it fits nicely into an existing, gigantic codebase.

Here's the problem: when I do this, everything compiles and runs, but I get a pointer address printed to my output instead of the "PARTY DOWN!" string. I determined that this is happening because the operator chosen by the compiler to perform the stream output is ostream& operator<< (const void* val), not ostream& operator<< (ostream& out, const char* s ).

I have a vague idea of why but I'm at a loss as to how to work around it. What can I do to get char*s to print into a temporary instance of a stringstream?

Here's a short version of the SpecialStringStream object that exhibits the behavior:

class SpecialStringStream : public ostringstream
{
  public:
    SpecialStringStream(ostream* regularStream)
    {
      regularStream_ = regularStream;
    }

    ~SpecialStringStream()
    {
      if (regularStream_ != NULL)
        (*regularStream_) << str(); 
    }

  private:
    ostream* regularStream_;
};

When I do something like: SpecialStringStream(someStreamPtr) << "PARTY DOWN!" << endl;, I get a pointer address like "00444D60" in my output instead of the message.

EDIT: Since I am too new of a user to answer my own question, here is what I've settled on thanks to all the responses.

I came up with the following solution, which works under Visual C++ 8 and all of the other compilers I needed it to. I created a template operator which basically strips a const SpecialStringStream of its constness, casts it as an ostream, and lets the ostream operators do their thing. Feel free to tear it to shreds in the comments and warn me of all the horrible potential bugs I've introduced!

template <class T>
std::ostream& operator<<(const SpecialStringStream &o, T msg)
{
    return static_cast<std::ostream&>(const_cast<SpecialStringStream&>(o)) << msg;
}

解决方案

The overload ostream& operator<< (ostream& out, const char*) is not viable because your temporary won't bind to the non-const reference ostream&. There isn't really much you can do about that (since you can't cast an rvalue to an lvalue) other than declaring a local variable and using that:

{
  specialstringstream ss;
  ss << "Hello world" << std::endl; // OK, can bind to lvalue
}

Possible solution: You could declare another overload that accepts an rvalue reference:

std::ostream & operator<<(specialstringstream && o, const char * s)
{
  return o << s; // note: *not* "std::move(o)"
}

这篇关于在C ++中将字符串打印到临时流对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆