商城首页欢迎来到中国正版软件门户

您的位置:首页 >C++20 source_location打印行号技巧

C++20 source_location打印行号技巧

  发布于2026-04-14 阅读(0)

扫一扫,手机访问

最常用写法是定义宏LOG_LINE()调用std::source_location::current(),日志函数按值接收默认参数;不可取地址或绑定引用,因返回纯右值;跨平台需校验line()==1且file_name()为空时回退。

C++中std::source_location怎么打印代码行号_C++20日志调试技巧【备忘】

std::source_location 本身不支持直接打印,必须显式调用 line()file_name() 等成员函数才能拿到行号等信息;它只是个轻量值类型,不是格式化工具。

怎么在日志里自动捕获当前行号和文件名

最常用写法是定义一个宏,把 std::source_location::current() 的调用“固定”在调用点展开:

#define LOG_LINE() std::source_location::current()

然后在日志函数中接收该参数(默认值避免每个调用都手动传):

void log(const char* msg, std::source_location loc = std::source_location::current()) {
    printf("[%s:%d] %s\n", loc.file_name(), loc.line(), msg);
}

调用时直接 log("user logged in") 就能打出真实调用处的行号——因为宏没参与,std::source_location::current() 是在调用点编译期求值的。

为什么不能直接传 &std::source_location::current()

常见错误是试图取地址或绑定引用:

  • auto& loc = std::source_location::current(); —— 错,返回的是纯右值,引用绑定失败(GCC/Clang 报错 cannot bind non-const lvalue reference to an rvalue
  • const auto& loc = ... —— 虽然语法通过,但会延长临时对象生命周期,行为不可靠;不同编译器优化下可能捕获到宏展开位置而非真实调用点
  • 正确做法永远是按值传递 std::source_location,它只有 4 个 size_t 成员,开销极小

MSVC、GCC、Clang 对 __builtin_SOURCE_LOCATION 的兼容差异

C++20 标准接口统一,但底层实现依赖编译器扩展:

  • Clang/GCC:基于 __builtin_SOURCE_LOCATION,需开启 -std=c++20 且不加 -fno-builtin
  • MSVC:从 19.30(VS 2022 17.0)起原生支持,但旧版(如 VS 2019)即使开 C++20 也不支持,会静默回退为默认构造值(line() == 1, file_name() == ""
  • 跨平台项目建议加运行时校验:if (loc.line() == 1 && std::string_view(loc.file_name()).empty()) { /* fallback */ }

注意:std::source_location::current() 的值完全由编译器在翻译单元内填充,无法被宏、内联函数或模板推导干扰——但如果你把它藏在中间函数里(比如封装一层再转发),那拿到的就是那一层的行号,不是原始调用点。想保真,就得让 current() 出现在最终日志调用的同一行。这是最容易忽略、也最难调试的点。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注