2015-10-19 64 views
0

我想写日志记录功能应该这样使用:记录功能<<

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

这应该打印以下行,添加ENDL立即冲洗:

main.cpp中:我的消息包含整数:123和双: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; 
} 

我的问题是,由于操作者的LR关联的< <输出为:含有整数我的消息::

的main.cpp

和双:

1.2

有没有办法如何实现该功能,或者是我的使用不可实现的要求?

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

+0

只是要清楚:什么时候需要刷新什么,什么应该在哪一行?例如:在你的第一个例子中,“double ...”部分在哪里? –

+0

@BaummitAugen对不起,编辑,修复。 – bedrorom

回答

3

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构造函数。然后你必须将它锁定在构造函数中并在析构函数中解锁它。它将保证不同条目的并发写入同步。

+1

围绕这个析构函数代码尝试一下,我会给你一个+1 –

+0

为什么你需要try/catch? –

+0

从技术上讲,理查德是正确的:cout << endl可以抛出异常,但从析构函数抛出异常是一个完全错误的想法(你可以在Internet中找到很多关于这个的)。所以必须让所有的析构函数都不抛出。我不想混淆代码,所以我尽量缩短范例,但现在我认为在我的剪辑中特别注意这个问题是很好的,因为不是每个人都意识到这一点的重要性。所以我添加了异常检查。 –