记录,如何获得命令结束?

时间:2011-08-17 21:31:48

标签: c++ templates logging stl std

所以我使用了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;是另一个。

它会输出下一条消息:

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;

怎么做这样的事情?

2 个答案:

答案 0 :(得分: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;
    }
};

答案 1 :(得分: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;
}