该示例的时间戳只是一个示例:)。
但如果你喜欢,我们可以尝试实现它。感谢 C++11 及其 STL 的重大改进,我们有一个出色的时间/日期 API:std::chrono
std::chrono
基于三个方面:
此外,chrono 提供三种类型的时钟,std::system_clock
、std::steady_clock
和std::high_resolution_clock
。在我们的例子中,我们使用std::system_clock
(我们想要访问日期时间,而不是测量精确的时间间隔)。
有关 std::chrono 的更多信息,请查看这个可怕的 Bo Qian 的 youtube 教程。
所以如果我们必须为我们的日志头实现一个时间戳,我们可以这样做:
编辑:像其他好东西一样,C++ 模板是很好的工具,直到你过度使用它。
我们的问题是这std::endl
是一个模板函数,所以我们不能将它作为参数直接传递给另一个模板函数(operator<<
在我们的例子中),因为编译器不能直接推断 std::endl 模板参数。那就是经常出现的错误“未解决的重载函数类型”。
但是有一种更简单的方法可以做到这一点:使用operator<<
for std::endl
only 的显式重载,而其他模板则用于其他所有内容:
class Log
{
private:
std::ostream& _out_stream;
bool _next_is_begin;
const std::string _log_header;
using endl_type = decltype( std::endl ); //This is the key: std::endl is a template function, and this is the signature of that function (For std::ostream).
public:
static const std::string default_log_header;
//Constructor: User passes a custom log header and output stream, or uses defaults.
Log(const std::string& log_header = default_log_header , std::ostream& out_stream = std::cout) : _log_header( log_header ) , _out_stream( out_stream ) , _next_is_begin( true ) {}
//Overload for std::endl only:
Log& operator<<(endl_type endl)
{
_next_is_begin = true;
_out_stream << endl;
return *this;
}
//Overload for anything else:
template<typename T>
Log& operator<< (const T& data)
{
auto now = std::chrono::system_clock::now();
auto now_time_t = std::chrono::system_clock::to_time_t( now ); //Uhhg, C APIs...
auto now_tm = std::localtime( &now_time_t ); //More uhhg, C style...
if( _next_is_begin )
_out_stream << _log_header << "(" << now_tm->tm_hour << ":" << now_tm->tm_min << ":" << now_tm->tm_sec << "): " << data;
else
_out_stream << data;
_next_is_begin = false;
return *this;
}
};
const std::string Log::default_log_header = "Log entry";
此代码片段完美运行。我已将完整的实现推送到我的 github 帐户。
参考: