2011-08-17 59 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希望每個日誌消息有一個號碼前綴。這不僅僅是在每條日誌消息結尾附加一個換行符的問題。編輯答案和編號的日誌消息功能。 –