当年排查线上问题。
最值钱的东西。
不是日志多。
是日志里有位置。
你看到文件名。
看到行号。
你就知道从哪儿挖。
当年:全靠宏
我们一直用这套。
#define LOG(msg) log_impl(__FILE__, __LINE__, msg)
能用。
但它有两个味道。
第一。
宏不好调试。
第二。
你一层封装多了。
行号就不一定是“真实调用点”。
线上啪一下:你封装了三层日志,行号全指向封装内部
你写了个小项目。
想让日志更好看。
你封装了几层。
最后线上出事。
你打开日志。
发现每条日志的行号都一样。
都指向你封装库里的某一行。
这对排障几乎没帮助。
C++20:std::source_location
它是一个类型。
能拿到。
文件。
行号。
函数名。
更关键的是。
它可以用默认参数捕获“调用点”。
一个最小用法
#include <source_location>
void log(std::string_view msg,
const std::source_location& loc = std::source_location::current());
这里的 current()。
会在调用处求值。
所以你写。
log("oops");
loc 里记录的。
是 log("oops") 那一行。
不是 log 函数内部。
打出来
#include <iostream>
void log(std::string_view msg, const std::source_location& loc) {
std::cout << loc.file_name() << ":" << loc.line() << " " << msg << "\n";
}
每段代码都很短。
但组合起来。
就能让日志自己带路。
关键结论
source_location 最大的价值。
是让“封装”和“定位”不再互相伤害。
小结
宏也能做。
但类型化的来源信息。
更像现代 C++。
也更少坑。