我有一种特殊类型的ostringstream,我试图将文本作为临时对象输出,但我遇到了一些麻烦。要清楚,这基本上就是我想做的事情:
ostringstream() << "PARTY DOWN!" << endl;
现在在你说:“但是Zack,那个代码完全没用!在线的最后,对象被破坏了,你怎么知道它是否做了什么?”,听我说。我不会尝试使用普通的ostringstreams,而是尝试使用析构函数实际提供数据退出对象的路径的派生类。所以实际上,它看起来更像是这样:
specialstringstream() << "PARTY DOWN!" << endl;
其中specialstringstream有一个析构函数,可以将文本转储到别处。
我不会详细说明为什么要这样做。你必须相信我对我需要做的事情有意义,它很适合现有的巨大代码库。
这就是问题所在:当我这样做时,所有内容都会编译并运行,但是我得到一个指针地址打印到我的输出而不是“PARTY DOWN!”串。我确定发生了这种情况,因为编译器选择执行流输出的运算符是
ostream& operator<< (const void* val)
,而非ostream& operator<< (ostream& out, const char* s )
。
我对于为什么有一个模糊的想法,但我不知道如何解决它。如何将char * s打印到字符串流的临时实例中?
这是展示行为的SpecialStringStream对象的简短版本:
class SpecialStringStream : public ostringstream
{
public:
SpecialStringStream(ostream* regularStream)
{
regularStream_ = regularStream;
}
~SpecialStringStream()
{
if (regularStream_ != NULL)
(*regularStream_) << str();
}
private:
ostream* regularStream_;
};
当我执行类似:SpecialStringStream(someStreamPtr) << "PARTY DOWN!" << endl;
的操作时,我在输出中得到一个指针地址,如“00444D60”,而不是消息。
编辑:由于我是一个太新的用户来回答我自己的问题,这是我已经解决的所有答案。
我提出了以下解决方案,它在Visual C ++ 8和我需要的所有其他编译器下工作。我创建了一个模板操作符,它基本上剥离了const的Const的SpecialStringStream,将其转换为ostream,并让ostream操作符完成它们的操作。请在评论中随意撕碎它,并警告我所引入的所有可怕的潜在错误!
template <class T>
std::ostream& operator<<(const SpecialStringStream &o, T msg)
{
return static_cast<std::ostream&>(const_cast<SpecialStringStream&>(o)) << msg;
}
答案 0 :(得分:4)
重载ostream& operator<< (ostream& out, const char*)
不可行,因为临时不会绑定到非const引用ostream&
。除了声明一个局部变量并使用它之外,没有什么可以做的(因为你不能将左值转换为左值):
{
specialstringstream ss;
ss << "Hello world" << std::endl; // OK, can bind to lvalue
}
可能的解决方案:您可以声明另一个接受右值引用的重载:
std::ostream & operator<<(specialstringstream && o, const char * s)
{
return o << s; // note: *not* "std::move(o)"
}
答案 1 :(得分:2)
您不想实现stringstream。你想实现一个写入你的特殊字符串的basic_streambuf。
流本身负责格式化和类似功能; streambufs负责最终成为数据的接收器。
毕竟,所有的字符串流都是iostream,附带了basic_stringbuf。
答案 2 :(得分:2)
也许有更好的方法,但我想出了另一个解决方案:
#include <iostream>
#include <sstream>
class LogClass
{
template <typename T>
friend const LogClass& operator << (const LogClass& lc, const T& v);
public:
LogClass()
: str(new std::ostringstream())
, refCount(new int(1))
{}
LogClass(const LogClass& other)
: str(other.str)
{
++(*refCount);
}
~LogClass()
{
--(*refCount);
if (!*refCount)
{
delete refCount;
std::cout << str->str() << std::endl;
delete str;
}
}
private:
mutable std::ostringstream *str;
int *refCount;
LogClass& operator = (const LogClass&);
};
template <typename T>
const LogClass& operator << (const LogClass& lc, const T& v)
{
(*lc.str) << v;
return lc;
}
int main(int , char**)
{
for (size_t i = 0; i < 10 ; ++i)
{
LogClass() << "PARTY DOWN! " << i;
}
}
valgrind --tool = memcheck --leak-check = full ./LogClass
== 16197 == Memcheck,内存错误检测器
== 16197 ==版权所有(C)2002-2010,以及Julian Seward等人的GNU GPL,
== 16197 ==使用Valgrind-3.7.0.SVN和LibVEX;用-h重新运行版权信息
== 16197 ==命令:./ LogClass
== 16197 ==
派对下来! 0
派对下来! 1
派对下来! 2
派对下来! 3
派对下来! 4
派对下来! 5
派对下来! 6
派对下来! 7
派对下来! 8
派对下来! 9
== 16197 ==
== 16197 == HEAP SUMMARY:
== 16197 ==在退出时使用:0块中的0字节
== 16197 ==总堆使用量:40个分配,40个释放,7,350个字节分配
== 16197 ==
== 16197 ==所有堆块都被释放 - 没有泄漏可能
== 16197 ==
== 16197 ==对于检测到的和抑制的错误计数,请重新运行:-v
== 16197 ==错误摘要:来自0个上下文的0个错误(被抑制:15个来自8个)
这就是我想要的,但不是线程安全的。使用boost中的shared_ptr来实现它。
答案 3 :(得分:0)
这是我正在使用的解决方法:
#define STRM2STR(x) (dynamic_cast<std::ostringstream &>(std::ostringstream() << std::dec << x).str())
插入std :: dec将导致调用ostream :: operator&lt;&lt; (ios_base&amp;(* pf)(ios_base&amp;))返回可用的ostream&amp;