C ++延迟日志记录(没有C ++ 11)

时间:2016-08-24 21:26:46

标签: c++ logging c++03

目前,我们的代码库有很多代码如下所示:

void log(int level, const char *msg) {
    // logLevel is some global int defining which messages to log
    if (level <= logLevel) {
        cout << msg << endl;
    }
}

...

int someNum = 3;
if (1 <= logLevel) {
    char msg[200];
    sprintf(msg, "Some format %d", someNum);
    log(1, msg);
}

我们使用的是Visual Studio 2008,因此无法使用C ++ 11的任何功能。是否有一种干净的方法将闭包传递给log方法,所以我可以删除重复的“if”条件?例如,我在前C ++ 11语法中寻找与以下内容等效的代码:

void log(int level, std::function<std::string ()> getMessage) {
    if (level <= logLevel) {
        cout << getMessage() << endl;
    }
}

...

int someNum = 3;
log(1, [someNum]() -> std::string {
    std::ostringstream sstream;
    sstream << "Some format " << someNum;
    return sstream.str();
});

我能想到的最好的是:

struct LogMessage {
    virtual std::string operator()() const = 0;
};

void log(int level, const LogMessage &getMessage) {
    if (level <= logLevel) {
        cout << getMessage() << endl;
    }
}

...

struct X : public LogMessage {
    X(int num) : myNum(num) { }
    std::string operator()() const {
        std::ostringstream out;
        out << "Some format " << myNum;
        return out.str();
    }
    private: const int myNum;
} a(someNum);
log(1, a);

2 个答案:

答案 0 :(得分:1)

即使通常不建议使用宏,它们也可以在这种特定情况下提供帮助,特别是如果所有文本都可以由流处理。

使您的日志功能成为宏:

#define LOG(level, msg) { if (level <= logLevel) { cout << msg << endl; } }

然后,如果你这样做:

LOG( 1, "Some format " << someNum )

if测试已完成,只有一个,并且只有当日志级别条件为true时才会执行宏的第二个参数中的任何复杂格式化。

注意:对于使用sprintf的现有行,您仍需要声明一个函数......:

inline std::string printNum( int someNum )
{
    char msg[200];
    sprintf(msg, "Some format %d", someNum);
    return msg;
}

LOG( 1, printNum(3) )

答案 1 :(得分:0)

要补充@ jpo38提供的答案,只需添加另一个宏以接受可变参数即可支持printf样式的函数:

#define LOGF(LEVEL, ...)\
    if ((LEVEL) <= logLevel) {\
        char msg[200];\
        sprintf(msg, __VA_ARGS__);\
        log((LEVEL), msg);\
    }

然后以下任何一个调用将产生相同的输出:

LOG(1, "Some format " << someNum);
LOGF(1, "Some format %d", someNum);
相关问题