You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++14模板函数中自动获取调用者代码行号实现日志?

C++14下实现自动记录调用行号的日志函数

可行,核心思路是用预处理宏封装底层日志函数,利用宏在预处理阶段展开的特性,自动捕获调用处的__LINE__和__FILE__,完全不需要用户手动传入行号或修改日志格式串。

具体实现步骤:

  1. 实现底层日志函数,负责接收行号、文件名、用户格式串及可变参数,并完成最终输出:
#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);
}
  1. 用宏封装底层函数,自动注入__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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 12:02:39