复用 ostream 实现日志类

Bjarne 老爷子教导我们:要忘记 stdio.h,改用 iostream。于是,有了我这个日志类。主要站在了 ostream 的肩膀上,所以代码并不多:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <atlbase.h>
#include <sstream>
#include <string>
 
class DebugBuffer : public std::stringbuf
{
protected:
    virtual int sync(void)
    {
        std::string dbg = str();
        if (!dbg.empty()) {
            ::OutputDebugStringA(dbg.c_str());
            dbg.clear();
            str(dbg);
        }
        return 0;
    }
};
 
class Logger : public std::basic_ostream<char>
{
public:
    Logger(void) : std::basic_ostream<char>(&m_buf)
    {
        // Nothing
    }
protected:
    DebugBuffer m_buf;
};

示例:

1
2
Logger logger;
logger << "Hello, World!" << endl;

考虑到 Logger 是对 basic_ostream<char> 的继承,而有时又需要输出宽字符串,所以可以增加一个 operator << 的实现:

1
2
3
4
5
6
7
8
inline std::basic_ostream<char>& operator << (std::basic_ostream<char>& stm,
    const std::wstring& ws)
{
    USES_CONVERSION;
    std::string str(W2CA(ws.c_str()));
    stm << str;
    return stm;
}

当然,大多数时候我们希望只在 Debug 配置时输出日志。那么可以这么修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifdef _DEBUG
 
#define DBGLOG(x)  x
#define LogEndl    (std::endl)
 
#else
 
class EmptyLogger
{
};
 
extern __declspec(selectany) EmptyLogger theEmptyLoger;
 
template <typename T>
inline EmptyLogger& operator<<(EmptyLogger& logger, const T& obj)
{
    return logger;
}
 
#define DBGLOG(x)   theEmptyLoger
#define LogEndl     0
 
#endif

示例:

DBGLOG(logger) << "Hello, World!" << LogEndl;

什么?还是钟情于类 printf 的格式控制符?也没问题,再加一个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Formatter
{
public:
    explicit Formatter(const char *format, ...)
    {
        va_list args;
        va_start(args, format);
        size_t len = _vscprintf(format, args);
        m_str.resize(len);
        vsprintf_s(const_cast<char *>(m_str.c_str()), len + 1, format, args);
        va_end(args);
    }
private:
    friend std::basic_ostream<char>& operator << (std::basic_ostream<char>&,
        const Formatter&);
    std::string m_str;
};
 
inline std::basic_ostream<char>& operator << (std::basic_ostream<char>& stm,
    const Formatter& fmt)
{
    stm << fmt.m_str;
    return stm;
}

示例:

DBGLOG(logger) << Formatter("%x", 123) << LogEndl;
Categories: 技术的角落 | Tags: | 1 Comment

一句话(38)

#与老和尚喝茶# 六点登鼓山与一老和尚喝茶。我对和尚说:我放不下一些事,放不下一些人。他说:滚!今天邪门了简直,多少人上山来,全 TMD 这句!我跟他说:让他们说去吧,这个世界上没有什么事是放不下的。痛了,你自然就会放下。#

Categories: 随感录 | Tags: | Leave a comment

一句话(37)

狗分三等:上等的叼飞盘,赏肉吃;中等的咬人,给骨头;下等的乱吠,有干粮的自带,没干粮的吃屎。#

Categories: 随感录 | Tags: | Leave a comment

一句话(36)

东野圭吾的《分身》阅毕。不得不从心中感叹东野是越来越会讲故事了,这个故事的情感内容几乎达到了《白夜行》的水平。——但是,说好的悬疑推理呢?这完全是本科幻伦理小说啊少年!只够得上《科幻世界》的水平啊亲!#

Categories: 随感录 | Tags: , | Leave a comment

一句话(35)

我要这天,再遮不住我眼!要这地,再埋不了我心!要那众生,都明白我意!要那诸佛,都烟消云散!那时,那日,那真相,@今何在 !姓孙的,有种的你站出来!#

Categories: 随感录 | Tags: | Leave a comment