stringstream/osstream 未链接 << 运算符且从不在 std::end 调用刷新的问题
Issue with stringstream/osstream not chaining << operator and never calling flush at std::end
所以我有以下记录class
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
struct asDigest {
explicit asDigest(const void* text, size_t len) : _t(text), _l(len) {}
explicit asDigest(const std::string& text) : _t(text.c_str()), _l(text.size(){}
const void* _t;
size_t _l;
};
struct asPointer {
explicit asPointer(const char* _p) : p(_p) {}
const char* p;
};
class Diagnostics
{
private:
std::stringstream m_stream;
std::string m_tag;
public:
typedef std::ostream& (*ManipFn)(std::ostream&);
typedef std::ios_base& (*FlagsFn)(std::ios_base&);
Diagnostics(const std::string& str) : m_tag(str) {}
template<class T> // int, double, strings, etc
std::ostream& operator<<(const T& output)
{
m_stream << output;
return m_stream;
}
std::ostream& operator<<(ManipFn manip) /// endl, flush, setw, setfill, etc.
{
manip(m_stream);
if (manip == static_cast<ManipFn>(std::flush)
|| manip == static_cast<ManipFn>(std::endl ) ) {
this->flush();
}
return m_stream;
}
Diagnostics& operator<<(FlagsFn manip) /// setiosflags, resetiosflags
{
manip(m_stream);
return *this;
}
Diagnostics& operator()(std::string& e)
{
m_tag = e;
return *this;
}
std::ostream& operator<<(struct asPointer ptr)
{
m_stream << "0x" << std::hex << std::setw(8) << std::setfill('0') << reinterpret_cast<const unsigned long long*>(ptr.p) << std::dec;
return m_stream;
}
std::ostream& operator<<(struct asDigest dgst)
{
m_stream << std::string("Test Digest");
return m_stream;
}
void flush()
{
/*
MAKE CALL TO OS LOG HERE
*/
m_stream.str( std::string() );
m_stream.clear();
}
};
预期用途如下:
Diagnostics("TAG") << "Message" << "MoreMessages" << std::endl
我可以创建一个记录器的实例,设置标签,并在到达 std::ostream& operator<<(const T& output)
上设置的断点后,我可以看到第一个字符串被送入流中。但是我很挣扎,因为似乎没有其他事情发生,后续字符串永远不会调用相同的方法,并且 flush()
永远不会被调用,所以我无法读取整个流。
我觉得我在这里遗漏了一些东西,或者我误解了 API。任何帮助实现我正在寻找的东西都将不胜感激。
问题在于 Diagnostics("TAG") << "Message"
return 是对内部 m_stream
的 ostream&
引用,因此后续 ... << "MoreMessages" << std::endl
将直接转到该流,绕过你所有 class 的逻辑。
要正确链接您的 operator<<
,他们都需要 return Diagnostics&
而不是 ostream&
,将 return m_stream;
替换为 return *this;
(您的 operator<<(FlagsFn)
和 operator()
已经这样做了),例如:
template<class T> // int, double, strings, etc
Diagnostics& operator<<(const T& output)
{
m_stream << output;
return *this;
}
Diagnostics& operator<<(ManipFn manip) /// endl, flush, setw, setfill, etc.
{
manip(m_stream);
if (manip == static_cast<ManipFn>(std::flush)
|| manip == static_cast<ManipFn>(std::endl ) ) {
this->flush();
}
return *this;
}
Diagnostics& operator<<(FlagsFn manip) /// setiosflags, resetiosflags
{
manip(m_stream);
return *this;
}
Diagnostics& operator()(std::string& e)
{
m_tag = e;
return *this;
}
Diagnostics& operator<<(struct asPointer ptr)
{
m_stream << "0x" << std::hex << std::setw(8) << std::setfill('0') << reinterpret_cast<const unsigned long long*>(ptr.p) << std::dec;
return *this;
}
Diagnostics& operator<<(struct asDigest dgst)
{
m_stream << "Test Digest";
return *this;
}
所以我有以下记录class
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
struct asDigest {
explicit asDigest(const void* text, size_t len) : _t(text), _l(len) {}
explicit asDigest(const std::string& text) : _t(text.c_str()), _l(text.size(){}
const void* _t;
size_t _l;
};
struct asPointer {
explicit asPointer(const char* _p) : p(_p) {}
const char* p;
};
class Diagnostics
{
private:
std::stringstream m_stream;
std::string m_tag;
public:
typedef std::ostream& (*ManipFn)(std::ostream&);
typedef std::ios_base& (*FlagsFn)(std::ios_base&);
Diagnostics(const std::string& str) : m_tag(str) {}
template<class T> // int, double, strings, etc
std::ostream& operator<<(const T& output)
{
m_stream << output;
return m_stream;
}
std::ostream& operator<<(ManipFn manip) /// endl, flush, setw, setfill, etc.
{
manip(m_stream);
if (manip == static_cast<ManipFn>(std::flush)
|| manip == static_cast<ManipFn>(std::endl ) ) {
this->flush();
}
return m_stream;
}
Diagnostics& operator<<(FlagsFn manip) /// setiosflags, resetiosflags
{
manip(m_stream);
return *this;
}
Diagnostics& operator()(std::string& e)
{
m_tag = e;
return *this;
}
std::ostream& operator<<(struct asPointer ptr)
{
m_stream << "0x" << std::hex << std::setw(8) << std::setfill('0') << reinterpret_cast<const unsigned long long*>(ptr.p) << std::dec;
return m_stream;
}
std::ostream& operator<<(struct asDigest dgst)
{
m_stream << std::string("Test Digest");
return m_stream;
}
void flush()
{
/*
MAKE CALL TO OS LOG HERE
*/
m_stream.str( std::string() );
m_stream.clear();
}
};
预期用途如下:
Diagnostics("TAG") << "Message" << "MoreMessages" << std::endl
我可以创建一个记录器的实例,设置标签,并在到达 std::ostream& operator<<(const T& output)
上设置的断点后,我可以看到第一个字符串被送入流中。但是我很挣扎,因为似乎没有其他事情发生,后续字符串永远不会调用相同的方法,并且 flush()
永远不会被调用,所以我无法读取整个流。
我觉得我在这里遗漏了一些东西,或者我误解了 API。任何帮助实现我正在寻找的东西都将不胜感激。
问题在于 Diagnostics("TAG") << "Message"
return 是对内部 m_stream
的 ostream&
引用,因此后续 ... << "MoreMessages" << std::endl
将直接转到该流,绕过你所有 class 的逻辑。
要正确链接您的 operator<<
,他们都需要 return Diagnostics&
而不是 ostream&
,将 return m_stream;
替换为 return *this;
(您的 operator<<(FlagsFn)
和 operator()
已经这样做了),例如:
template<class T> // int, double, strings, etc
Diagnostics& operator<<(const T& output)
{
m_stream << output;
return *this;
}
Diagnostics& operator<<(ManipFn manip) /// endl, flush, setw, setfill, etc.
{
manip(m_stream);
if (manip == static_cast<ManipFn>(std::flush)
|| manip == static_cast<ManipFn>(std::endl ) ) {
this->flush();
}
return *this;
}
Diagnostics& operator<<(FlagsFn manip) /// setiosflags, resetiosflags
{
manip(m_stream);
return *this;
}
Diagnostics& operator()(std::string& e)
{
m_tag = e;
return *this;
}
Diagnostics& operator<<(struct asPointer ptr)
{
m_stream << "0x" << std::hex << std::setw(8) << std::setfill('0') << reinterpret_cast<const unsigned long long*>(ptr.p) << std::dec;
return *this;
}
Diagnostics& operator<<(struct asDigest dgst)
{
m_stream << "Test Digest";
return *this;
}