使用操作员<<的记录功能

Logging function which uses operator <<

本文关键字:lt 记录 功能 操作员      更新时间:2023-10-16

我想写一个日志记录函数,应该这样使用:

log(__FILE__) << "My message containing integer: " << 123 << " and double: " << 1.2;

这应该打印以下行,添加endl并立即刷新:

main.cpp: My message contains 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;
}

我的问题是,由于运算符<<输出为:

main.cpp: My message contains integer:

123年

和double:

1.2

是否有任何方法如何实现该函数,或者我对其使用的要求是不可实现的?

理想情况下,我想使用普通的c++ 03(即没有c++ 11功能,boost和非标准库)。

L-R结合性与你的问题无关(如果你谈论的是换行)。问题在于每次写入后都使用endl。你不需要它(如果你这样做,那么你不需要flush,因为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";

在这里,您可以很容易地在日志文件中得到一条消息"aabbccnn",这是非常不希望看到的。

为了避免这种情况,您可以在log()函数中设置一个静态互斥对象,并将其传递给Writer构造函数。然后你必须在构造函数中锁定它,在析构函数中解锁它。