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

MSVC下实现无需宏、自动获取调用者名称的可变参数日志函数

解决方案:利用模板默认参数自动获取调用者位置

在C++20标准下,你可以通过将std::source_location作为模板默认参数的方式,实现无需手动传递参数、也不用宏的自动调用者信息获取,同时保留可变参数的格式化能力。

可行代码示例

#include <iostream>
#include <source_location>
#include <format>

// 将std::source_location作为模板默认参数,在调用点实例化
template<typename... Args, std::source_location Loc = std::source_location::current()>
void log(const char* format_str, Args&&... args) {
    std::string func_name = Loc.function_name();
    std::string message = std::format(format_str, std::forward<Args>(args)...);
    std::cout << "DEBUG: [" << func_name << "] " << message << '\n';
}

void someFunc() {
    log("hello {}!", "world"); // 无需手动传入source_location
}

int main() {
    someFunc(); // 输出:DEBUG: [void someFunc()] hello world!
}

原理说明

当调用log函数时,模板参数Loc会自动使用默认值std::source_location::current(),而这个函数会在调用点(即someFunc内部)获取当前的源代码位置信息,包括调用者的函数名。这种方式避开了函数参数默认值必须位于参数列表末尾的限制,同时完全不需要宏或者手动传递参数。

MSVC支持情况

该方案要求编译器支持C++20标准,MSVC从Visual Studio 2022版本17.0及以上完全支持此特性,你可以在项目属性中开启/std:c++20或更高版本的标准编译选项。

补充说明

如果你的项目无法使用C++20的模板默认参数特性,那目前没有完全无宏的替代方案——函数参数的默认值规则限制了std::source_location必须放在参数列表末尾,但模板参数包无法在默认参数之前被正确推导。此时折衷方案可以用一个极简的宏来封装手动传递的操作(比如#define LOG(...) log(std::source_location::current(), __VA_ARGS__)),但这回到了你提到的宏方案;不过这个宏非常轻量,仅做参数转发,不会影响类封装的灵活性。

内容的提问来源于stack exchange,提问作者H3d9

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:16:18