Ведение журнала, как получить команду end? - PullRequest
1 голос
/ 18 августа 2011

Поэтому я использую такой Класс журнала :

#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;, я хочу, чтобы он был в состоянии получить, что это наше лог-сообщение, а a << "here's one with a number: " << 5; - другое.

постоянно выдает следующее сообщение:

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

Iхотите сохранить его синтаксис (неограниченное количество <<, большой диапазон типов значений, нет ( и ) в api), но выведите его:

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

Как это сделать

Ответы [ 2 ]

5 голосов
/ 18 августа 2011

Make 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;
    }
};
2 голосов
/ 18 августа 2011

Вы можете определить специальный объект, который при вставке указывает конец записи в журнале.Я знаю, что это не совсем то, что вы хотите, но это действительно легко реализовать.Это также дает вам возможность распределять записи журнала по нескольким операторам (что полезно, например, для создания частей записи журнала в цикле).

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...