如何编写带可变参数且捕获调用方源码位置的C++日志函数
解决带可变参数与源码位置的日志函数编译错误
错误原因
C++中,可变模板参数必须放在函数参数列表的末尾,同时带有默认值的参数若放在可变参数之后,编译器无法区分可变参数的结束位置与默认参数的位置。你原代码中将std::source_location参数放在Args&&... args之后,导致编译器把调用时的第二个实参42尝试转换为std::source_location,触发编译错误。
正确实现方案
调整参数顺序,将带默认值的std::source_location放在函数参数列表的最前面,后续依次是格式字符串和可变参数。这样编译器会自动使用std::source_location::current()的默认值,同时正确匹配格式字符串与可变参数。
完整代码示例(需C++20及以上支持):
#include <iostream> #include <format> #include <source_location> template <typename... Args> inline static void LOG_MSG(const std::source_location location = std::source_location::current(), const std::string& str, Args&&... args) { // 格式化日志内容 std::string log_content = std::format(str, std::forward<Args>(args)...); // 输出带源码位置的日志 std::cout << "[ " << location.file_name() << ":" << location.line() << " ] " << log_content << std::endl; } // 调用示例 int main() { LOG_MSG("test {}", 42); LOG_MSG("value {} is greater than {}", 100, 50); return 0; }
补充说明
std::source_location::current()会自动捕获调用方的源码文件名、行号等信息,无需手动传递- 使用
std::forward<Args>(args)...保证可变参数的完美转发,避免不必要的拷贝 - 若项目未使用C++20的
std::format,可替换为其他格式化库(如fmtlib)或自定义格式化逻辑
内容的提问来源于stack exchange,提问作者intrigued_66
相关产品推荐
相关产品推荐

