2011-08-17 58 views
1

于是我就用这样的Log class日志记录,如何获得命令结束?

#include <stdio.h> 
#include <iostream> 

class Log 
{ 
public: 
    int i; 
    Log() 
    { 
     i = 0; 
    } 

    template <class T> 
    Log &operator<<(const T &v) 
    { 
     i++; 
     std::cout << i << ":" << v << ";" <<std::endl; 
     return *this; 
    } 
    Log &operator<<(std::ostream&(*f)(std::ostream&)) 
    { 
     i++; 
     std::cout << i << ":" << *f << ";" <<std::endl; 
     return *this; 
    } 

    ~Log() 
    { 
     std::cout << " [end of message]" << std::endl; 
    } 
}; 

,我用这样的:

#include <log.h> 

int main() 
{ 
    Log a; 
    a << "here's a message" << std::endl; 
    a << "here's one with a number: " << 5; 
    std::cin.get(); 
} 

我想我的日志类来获得,当我把 “;”意思是如果我有a << "here's a message" << std::endl;我希望它能够得到它是oune日志消息和a << "here's one with a number: " << 5;是另一个。

crently它输出一条消息:

1:here's a message; 
2: 
; 
3:here's one with a number: ; 
4:5; 

我想保持其sintax(的<<无限数量的,大范围的值类型,没有()在API周围),但使它输出:

1:here's a message 
; 
2:here's one with a number: 5; 

如何做这种事?

回答

5

使operator<<返回一个临时值,这将在销毁时放置endl并将所有operator<<调用转发给主要对象。这样,endl保证只被调用一次。

class Log 
{ 
struct EndlOnDeath { 
    Log* log; 
    EndlOnDeath(Log* ptr) 
     : log(ptr) {} 
    template<typename T> EndlOnDeath& operator<<(const T& val) { 
     (*log) << val; 
    } 
    ~EndlOnDeath() { 
     (*log) << std::endl; 
    } 
}; 

public: 
    int i; 
    Log() 
    { 
     i = 0; 
    } 

    template <class T> 
    EndlOnDeath operator<<(const T &v) 
    { 
     i++; 
     std::cout << i << ":" << v << ";"; 
     return this; 
    } 
    Log &operator<<(std::ostream&(*f)(std::ostream&)) 
    { 
     i++; 
     std::cout << i << ":" << *f << ";" <<std::endl; 
     return *this; 
    } 

    ~Log() 
    { 
     std::cout << " [end of message]" << std::endl; 
    } 
}; 
+0

+1这就是聪明! –

+0

确定性破坏是德Epix的WinRAR的™ – Puppy

+0

@DeadMG:要点是让它可以分割不'一个文本line'消息,但'一个代码行messages'因此,例如'一个<<的std :: ENDL << STD: :endl << std :: endl << std :: endl;'将是一条消息。 – Rella

2

您可以定义一个特殊的物体,插入时,指示日志条目的结束。我知道这不完全是你想要的,但它很容易实现。它还使您能够灵活地将日志条目分散到多个语句中(例如,在循环中生成部分日志条目非常有用)。

struct LogEnd {}; 
const LogEnd logend; 

class Log 
{ 
public: 
    Log() : number_(0) {} 

    template <typename T> Log& operator<<(const T& x) 
    { 
     ss_ << x; 
    } 

    Log& operator<<(const LogEnd& aLogEnd) 
    { 
     // Dump the stringstream string to output with desired decorations. 
     std::cout << number_ << ": " << ss_.str() << std::endl; 

     // Clear the stringstream 
     ss_.str(""); 

     ++number_; 
    } 

private: 
    std::ostringstream ss_; 
    int number_; 

}; 

int main() 
{ 
    Log log; 
    log << "This is " << 1 << " log entry" << logend; 
} 
+0

这是怎么回事什么不同,只是'endl'直接? – Puppy

+0

我认为OP希望每个日志消息有一个号码前缀。这不仅仅是在每条日志消息结尾附加一个换行符的问题。编辑答案和编号的日志消息功能。 –