c++ std::source_location怎么用 c++获取源代码信息【C++20】

20次阅读

std::source_location是c++20引入的编译期源码位置捕获设施,提供file_name()、function_name()、line()、column()等只读接口,通过default参数std::source_location::current()自动填充调用点信息,类型安全且不依赖宏。

c++ std::source_location怎么用 c++获取源代码信息【C++20】

std::source_location 是 C++20 引入的标准设施,用于在编译期捕获调用点的源码位置信息(文件名、函数名、行号、列号),常用于日志、断言、调试和诊断工具中。它不依赖宏(如 __FILE____LINE__),而是通过编译器自动推导,类型安全且可作为函数参数默认构造。

基本用法:作为函数参数自动填充

最常见方式是将 std::source_location 作为函数最后一个参数,并赋予默认值 std::source_location::current()。编译器会在每次调用处自动填入该调用点的位置信息:

示例:

#include  #include  

void log(const char* msg, const std::source_location& loc = std::source_location::current()) { std::cout << "[" << loc.file_name() << ":" << loc.line() << " in " << loc.function_name() << "] " << msg << 'n'; }

int main() { log("Hello from main"); // 输出类似:[main.cpp:12 in main] Hello from main return 0; }

注意:loc 的默认值由编译器在调用点生成,不是在函数定义处求值 —— 所以每个调用都反映真实调用位置。

立即学习C++免费学习笔记(深入)”;

关键成员函数说明

std::source_location 提供以下只读访问接口:

  • file_name():返回 const char*,通常是绝对或相对路径(取决于编译器和构建配置)
  • function_name():返回调用点所在函数的签名(如 "int main()""void foo()"),非标准化,但通常可用
  • line():返回调用语句所在的行号(unsigned int
  • column():返回列号(从 1 开始),支持度因编译器而异(GCC/Clang 一般支持,MSVC 较新版本支持)

使用注意事项与限制

这个类型设计为轻量、不可变、仅编译期生成,因此有几点需留意:

  • 不能手动构造完整信息(如不能写 source_location{"a.cpp", 42, 1}),只能通过 current() 获取调用点快照
  • 不参与运行时反射;函数名和文件路径是字面量字符串,存储在只读段,无动态解析开销
  • 若函数被内联,current() 仍指向原始调用点,不是内联后展开的位置(这是预期行为)
  • 跨编译单元调用也准确 —— 编译器保证每个调用站点独立生成位置信息

进阶技巧:封装日志宏或模板辅助

虽然 std::source_location 本身不依赖宏,但有时需配合宏隐藏参数传递(例如统一日志入口):

#define LOG(msg) log(msg, std::source_location::current()) 

// 使用时无需显式传参 LOG("User login failed"); // 自动捕获此处位置

也可结合模板实现泛型日志器,避免重复声明默认参数:

template void debug_log(const char* fmt, Args&&... args) {     auto loc = std::source_location::current();     // 使用 fmt + args 做格式化(如用 std::format 或 spdlog)     std::printf("[%s:%u] ", loc.file_name(), loc.line());     // ... 实际格式化逻辑 }

不复杂但容易忽略:它让“哪里出的问题”这件事,第一次真正进入了标准库的类型系统。

text=ZqhQzanResources