使用模板SFINAE进行条件编译的c ++日志函数 [英] c++ log functions using template SFINAE for conditional compile

查看:53
本文介绍了使用模板SFINAE进行条件编译的c ++日志函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在评估是否有可能利用C ++ 11功能来替换日志记录宏,而不会产生任何运行时额外费用.

I am evaluating if it is possible to leverage C++11 features to replace logging Macros without any run-time additional cost.

我展示了这个演示:

enum class LogLevel {
    Fatal = 0,
    DFatal = 1,
    Error = 2,
    Normal = 3,
    Verbose = 4,
    Debug = 5
};

constexpr LogLevel log_compiled = LogLevel::Normal;
LogLevel log_runtime = LogLevel::Error;

#ifdef NDEBUG
constexpr LogLevel log_fatal = LogLevel::Fatal;
#else
constexpr LogLevel log_fatal = LogLevel::DFatal;
#endif


template <LogLevel L, typename std::enable_if<(L <= log_fatal)>::type* = nullptr>
void Log(std::string message) {

    std::cout << "Fatal level: " << (int) L << " Message: " << message << std::endl;
    exit(0);
}

template <LogLevel L, typename std::enable_if<(L>log_fatal && L <= log_compiled)>::type* = nullptr>
void Log(std::string message) {

    if (L <= log_runtime) {
        std::cout << "Level: " << (int) L << " Message: " << message << std::endl;
    }

}

template <LogLevel L, typename std::enable_if<(L > log_compiled)>::type* = nullptr>
void Log(std::string message) {
}

int main(int argc, char *argv[]) {

    //not compiled
    Log<LogLevel::Verbose>("Something to much usual");

    //compiled, not printed
    Log<LogLevel::Normal>("Something usual");

    //compiled, printed
    Log<LogLevel::Error>("No disk space");

    //compiled, printed, terminate in Debug mode
    Log<LogLevel::DFatal>("Unexpected contition, recoverable");

    //compiled, printed, terminate always
    Log<LogLevel::Fatal>("Unexpected contition, unrecoverable");

    return 0;
}

通过这种方式,我可以非常一致地处理编译时间排除,运行时日志级别和致命条件.

This way I handle the compile time exclusion, the runtime log level and the fatal conditions in a very consistent way.

它可能适用于<<运算符.

It would probably be adapted for streams with the << operator.

我的问题:

//not compiled
Log<LogLevel::Verbose>("Something to much usual");

大多数编译器实际上会导致NOOP吗?字符串会存在于代码中吗?

Will this actually result in a NOOP by most compilers? Will the string exist in the code?

这种方法不好吗?

推荐答案

按照编写,编译器无法优化

As written, the compiler cannot optimize away

Log<LogLevel::Verbose>("Something to much usual");

因为它构造然后破坏了 std :: string ,这可能会有副作用(例如,使用可能替换的 :: operator new 分配然后释放内存)和 :: operator delete ).

because it constructs and then destructs a std::string, which may have side effects (e.g., allocating and then freeing memory using possibly-replaced ::operator new and ::operator delete).

但是,如果编写 Log 模板以采用 const char * 代替,则可以完全优化该调用.给定

If you write your Log templates to take a const char * instead, however, then the call can be fully optimized out. Given

template <LogLevel L, typename std::enable_if<(L > log_compiled)>::type* = nullptr>
void Log(const char * ) {
}

int main() {
    Log<LogLevel::Verbose>("Something to much usual");
    return 0;
}

-O2 上的

g ++ 4.9 将其编译以简单

xorl    %eax, %eax
ret

这篇关于使用模板SFINAE进行条件编译的c ++日志函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆