您的代码不起作用的原因是您没有为要传递给它的所有内容实现operator<<。
此声明:
Logger l;
l << "Event with object : " << obj << " while in context : " << context;
基本上是这样做的(假设operator<< 是Logger 的成员,您的实现暗示它是):
Logger l;
l.operator<<("Event with object : ").operator<<(obj).operaator<<(" while in context : ").operator<<(context);
因此,您需要为字符串、obj、上下文等单独重载operator<<。并且您需要一种方法来指示何时将完整的日志消息刷新到std::cout。
我会建议更像这样的东西:
struct LoggerStream
{
std::ostringstream strm;
struct Timestamp
{
};
~LoggerStream()
{
std::string s = strm.str();
if (!s.empty())
std::cout << s << std::flush;
}
LoggerStream& operator<< (const Timestamp &t)
{
strm << "[timestamp] "; // format this however you need
return *this;
}
LoggerStream& operator<< (const object &obj)
{
strm << "[obj_desc]"; // format this however you need
return *this;
}
LoggerStream& operator<< (const context &ctx)
{
strm << "[this context]"; // format this however you need
return *this;
}
LoggerStream& operator<< (std::ostream&(*f)(std::ostream&))
{
if (f == (std::basic_ostream<char>& (*)(std::basic_ostream<char>&)) &std::flush)
{
std::string s = strm.str();
if (!s.empty())
std::cout << s << std::flush;
strm.str("");
strm.clear();
}
else
strm << f;
return *this;
}
template<typename T>
LoggerStream& operator<< (const T& value)
{
strm << value;
return *this;
}
};
class Logger
{
LoggerStream getStream()
{
LoggerStream strm;
strm << Timestamp;
return strm;
}
};
然后你可以这样做:
Logger l;
l.getStream() << "Event with object : " << obj << " while in context : " << context;
...
l.getStream() << "Event with object : " << obj << " while in context : " << context;
...
Logger l;
LoggerStream strm = l.getStream();
strm << "Event with object : " << obj << " while in context : " << context << std::flush;
...
strm << Logger::Timestamp << "Event with object : " << obj << " while in context : " << context << std::flush;
...
或者:
struct Logger
{
std::ostringstream strm;
~Logger()
{
std::string s = strm.str();
if (!s.empty())
std::cout << "[timestamp] " << s << std::flush;
}
Logger& operator<< (const object &obj)
{
strm << "[obj_desc]"; // format this however you need
return *this;
}
Logger& operator<< (const context &ctx)
{
strm << "[this context]"; // format this however you need
return *this;
}
Logger& operator<< (std::ostream&(*f)(std::ostream&))
{
if (f == (std::basic_ostream<char>& (*)(std::basic_ostream<char>&)) &std::flush)
{
std::string s = strm.str();
if (!s.empty())
std::cout << "[timestamp] " << s << std::flush;
strm.str("");
strm.clear();
}
else
strm << f;
return *this;
}
template<typename T>
Logger& operator<< (const T& value)
{
strm << value;
return *this;
}
};
Logger() << "Event with object : " << obj << " while in context : " << context;
...
Logger() << "Event with object : " << obj << " while in context : " << context;
...
Logger l;
l << "Event with object : " << obj << " while in context : " << context << std::flush;
...
l << "Event with object : " << obj << " while in context : " << context << std::flush;
...