使用运算符 << 的日志记录功能
Logging function which uses operator <<
我想编写一个日志记录函数,应该像这样使用:
log(__FILE__) << "My message containing integer: " << 123 << " and double: " << 1.2;
这应该打印以下行,立即添加 endl 和刷新:
main.cpp: My message containing integer: 123 and double: 1.2
我(简化)实现该功能的尝试:
class Writer
{
public:
template<typename T>
Writer & operator<<(T t)
{
cout << t << endl;
cout.flush();
return (*this);
}
};
Writer log(const char* fileName)
{
cout << fileName << ": ";
return Writer();
}
int main(int argc, const char *argv[])
{
log(__FILE__) << "My message containing integer: " << 123 << "and double: " << 1.2;
return 0;
}
我的问题是,由于运算符的 L-R 结合性<<,输出为:
main.cpp: My message containing integer:
123
and double:
1.2
有什么方法可以实现这个功能,或者我的使用需求是不是实现不了?
理想情况下,我想使用纯 C++03(即没有 C++11 功能、boost 和非标准库)。
L-R 关联性与您的问题无关(如果您谈论换行符)。问题是因为您在每次写入后都使用 endl 。你不需要它(如果你这样做,那么你就不需要刷新,因为 endl 已经刷新了输出)。
您的问题的简单解决方案:
class Writer
{
public:
template<typename T>
Writer & operator<<(T t)
{
cout << t;
return (*this);
}
~Writer()
{
try {
cout << endl;
}
catch (...) {
// You have to make sure that no
// exception leaves destructor
}
}
};
同样值得注意的是,您的方法并不是真正可扩展的:不可能在多线程环境中使用您的代码。假设有两个线程正在写入您的日志记录:
Thread 1: log(__FILE__) << "a" << "b" << "c";
Thread 2: log(__FILE__) << "a" << "b" << "c";
在这里您可以很容易地在您的日志文件中得到一条消息 "aabbcc\n\n",这是非常不受欢迎的。
为了避免这种情况,您可以在 log() 函数中有一个静态互斥对象,并将其传递给 Writer 构造函数。然后你必须在构造函数中锁定它并在析构函数中解锁它。它将保证不同条目并发写入的同步。
我想编写一个日志记录函数,应该像这样使用:
log(__FILE__) << "My message containing integer: " << 123 << " and double: " << 1.2;
这应该打印以下行,立即添加 endl 和刷新:
main.cpp: My message containing integer: 123 and double: 1.2
我(简化)实现该功能的尝试:
class Writer
{
public:
template<typename T>
Writer & operator<<(T t)
{
cout << t << endl;
cout.flush();
return (*this);
}
};
Writer log(const char* fileName)
{
cout << fileName << ": ";
return Writer();
}
int main(int argc, const char *argv[])
{
log(__FILE__) << "My message containing integer: " << 123 << "and double: " << 1.2;
return 0;
}
我的问题是,由于运算符的 L-R 结合性<<,输出为:
main.cpp: My message containing integer:
123
and double:
1.2
有什么方法可以实现这个功能,或者我的使用需求是不是实现不了?
理想情况下,我想使用纯 C++03(即没有 C++11 功能、boost 和非标准库)。
L-R 关联性与您的问题无关(如果您谈论换行符)。问题是因为您在每次写入后都使用 endl 。你不需要它(如果你这样做,那么你就不需要刷新,因为 endl 已经刷新了输出)。
您的问题的简单解决方案:
class Writer
{
public:
template<typename T>
Writer & operator<<(T t)
{
cout << t;
return (*this);
}
~Writer()
{
try {
cout << endl;
}
catch (...) {
// You have to make sure that no
// exception leaves destructor
}
}
};
同样值得注意的是,您的方法并不是真正可扩展的:不可能在多线程环境中使用您的代码。假设有两个线程正在写入您的日志记录:
Thread 1: log(__FILE__) << "a" << "b" << "c";
Thread 2: log(__FILE__) << "a" << "b" << "c";
在这里您可以很容易地在您的日志文件中得到一条消息 "aabbcc\n\n",这是非常不受欢迎的。
为了避免这种情况,您可以在 log() 函数中有一个静态互斥对象,并将其传递给 Writer 构造函数。然后你必须在构造函数中锁定它并在析构函数中解锁它。它将保证不同条目并发写入的同步。