我正在编写自己的Logger。我知道那里有很多,但我想自己写。它具有在离开范围时记录的消息。因此,如果我调用Logger::Error(__FILE__,__LINE__) << "some error"
,它会被直接记录,因为没有对变量的赋值。
但我希望有一条消息记录范围的时间。因此它会影响自创建以来的时间以及删除后的时间。因此我需要将它分配给范围中的变量,例如此marko:#define LOG_SCOPE_TIME LogTimer ___t = Logger::Timer(__FILE__,__LINE__)
它可以像这样使用:
int main()
{
{
LOG_SCOPE_TIME << "Some scope";
//do something to mesure
}
}
示例输出:
[timer][File:main.cpp][Line:19][thread:8024][21-05-2015][13:15:11] Some scope[0µs]
[timer][File:main.cpp][Line:19][thread:8788][21-05-2015][13:15:11] Some scope[118879µs]
但这实际上会导致2个日志。第一个临时创建的LogTime对象(时间为0μs),第二个为实际范围时间。
我如何防止这种情况?有什么建议?这是一个简化的例子:
#include <iostream>
#include <chrono>
class LogTimer {
std::string str;
std::chrono::high_resolution_clock::time_point m_start;
public:
LogTimer(const std::string& file, int i)
: m_start(std::chrono::high_resolution_clock::now())
{
str = file + ':' + std::to_string(i);
}
~LogTimer() {
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>
(end - m_start).count();
std::cout << str << " [" << duration << "µs]\n";
}
LogTimer& operator<<(const std::string& p) {
str += '[' + p + ']';
return *this;
}
};
namespace Logger {
LogTimer Timer(const std::string& f, int i) {
return LogTimer(f, i);
}
}
#define LOG_SCOPE_TIME LogTimer ___t = Logger::Timer(__FILE__,__LINE__)
int main()
{
LOG_SCOPE_TIME << "something"; // logs two lines
}
答案 0 :(得分:2)
您正在遇到运营商优先级问题。当您使用宏时:
LOG_SCOPE_TIME << "Some scope";
扩展为:
LogTimer ___t = Logger::Timer(__FILE__,__LINE__) << "Some scope";
评估为:
LogTimer ___t = (Logger::Timer(__FILE__,__LINE__) << "Some scope");
因为<<
的优先级高于=
。因此,您要阻止复制省略,因为编译器现在必须创建一个临时Timer
来执行<< "Some Scope"
,然后将复制到___t
(这在技术上是一个保留名称)。附加副本意味着添加析构函数,在您的情况下意味着记录额外的行。
您需要确保复制省略。我能想到的最简单的方法是改变宏来做:
#define LOG_SCOPE_TIME LogTimer ___t = Logger::Timer(__FILE__,__LINE__); ___t
这样,您的原始示例扩展为:
LogTimer ___t = Logger::Timer(__FILE__,__LINE__); ___t << "Some scope";
那里没有问题。