使用模板SFINAE进行条件编译的c ++日志函数 [英] c++ log functions using template SFINAE for conditional compile
问题描述
我正在评估是否有可能利用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屋!