c++ log functions using template SFINAE for conditional compile -
i evaluating if possible leverage c++11 features replace logging macros without run-time additional cost.
i come out demo:
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 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 log<loglevel::fatal>("unexpected contition, unrecoverable"); return 0; }
this way handle compile time exclusion, runtime log level , fatal conditions in consistent way.
it adapted streams << operator.
my questions:
//not compiled log<loglevel::verbose>("something usual");
will result in noop compilers? string exist in code?
is approach bad idea?
as written, compiler cannot optimize away
log<loglevel::verbose>("something usual");
because constructs , destructs std::string
, may have side effects (e.g., allocating , freeing memory using possibly-replaced ::operator new
, ::operator delete
).
if write log
templates take const char *
instead, however, call can 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 usual"); return 0; }
g++ 4.9 @ -o2
compiles it simply
xorl %eax, %eax ret
Comments
Post a Comment