如何在C++14模板函数中自动获取调用者代码行号实现日志?
C++14下实现自动记录调用行号的日志函数
可行,核心思路是用预处理宏封装底层日志函数,利用宏在预处理阶段展开的特性,自动捕获调用处的__LINE__和__FILE__,完全不需要用户手动传入行号或修改日志格式串。
具体实现步骤:
- 实现底层日志函数,负责接收行号、文件名、用户格式串及可变参数,并完成最终输出:
#include <cstdio> #include <cstdarg> void log_error_impl(int line_num, const char* file_name, const char* fmt, ...) { va_list args; va_start(args, fmt); // 先输出行号和文件前缀,再输出用户日志内容 fprintf(stderr, "[%s:%d] ERROR: ", file_name, line_num); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); }
- 用宏封装底层函数,自动注入
__LINE__和__FILE__:
#define log_error(fmt, ...) log_error_impl(__LINE__, __FILE__, fmt, ##__VA_ARGS__)
这里的##__VA_ARGS__是为了兼容用户不传可变参数的场景(比如log_error("Empty error message")),主流C++14编译器(GCC、Clang、MSVC)都支持这个扩展语法。
为什么之前的方案不行?
- 模板函数方案:模板参数的实例化发生在编译阶段后期,
__builtin_LINE()会绑定到模板定义的行号,而非调用处的行号,因为模板实例化时无法回溯到调用点的预处理信息。 - 手动传
__LINE__方案:虽然能拿到正确行号,但增加了用户调用成本,不符合“无额外负担”的需求。
使用示例
用户只需像普通函数一样调用:
float f1 = 3.14f; log_error("Sample error, signal value is %f", f1);
输出效果类似:
[main.cpp:10] ERROR: Sample error, signal value is 3.140000
内容的提问来源于stack exchange,提问作者GShaik
相关产品推荐
相关产品推荐

