有可能,但你需要弄清楚你真正想要什么接口。一种选择是让您的Logger 成为std::ostream(继承),然后事情就会开箱即用。另一种方法是维护一个与std::ostream 无关(无继承)的记录器,但是您需要为要记录的任何和所有类型T 提供Logger& operator<<(Logger&,T const &)。对于std::string 的特殊情况,您可以这样做:
Logger& operator<<(Logger& logger, std::string const& msg) {
logger.log(msg); // need not be, and problably should be static
return logger;
}
使这个泛型与 C++ 中的大多数泛型代码一样涉及模板的使用:
template <typename T>
Logger& operator<<(Logger& logger, T const & obj) {
// do specific work based on the type, or a completely generic approach:
std::ostringstream st;
st << obj;
logger.log(st.str());
return logger;
}
此时,您可能需要考虑添加对操纵器的支持,并且...好吧,如果您从这条路径开始,那么不要在每个函数中创建 std::ostringstream 可能更有意义,而是创建一个作为一个成员,然后将所有数据转储到该流中并使用一些操纵器来提取字符串并写入它(例如在std::flush 或std::ends...上)
template <typename T>
Logger& operator<<(Logger& logger, T const& obj) {
logger.stream << obj;
return logger;
}
Logger& operator<<(Logger& logger, std::ostream& (*manip)(std::ostream&)) {
logger.stream << manip;
if (manip == static_cast<std::ostream& (*)(std::ostream&)>(std::flush)) {
logger.write(); // flush to disk
}
return logger;
}
// add support for other manipulators...
然后你可能又开始想知道,将一些现成的日志库拉出来并直接使用它会不会更容易。