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

使用std::source_location::current()的模板代码编译失败咨询

关于std::source_location::current()模板代码编译失败的问题解答

问题背景

在探索std::source_location::current()的用法时,我看到Stack Overflow某线程的采纳答案中的代码,使用x86-64 gcc 13.1编译器,搭配-O3 -std=c++20 -Wall -Wextra -Wpedantic编译选项在Godbolt上运行时无法编译,想知道是否操作有误,若不是,为何该代码会被采纳为答案?

原代码如下:

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

template<typename... Targs, auto location = std::source_location::current()>
auto tprintf(char const* format, Targs const&... args) -> void {
    std::cout
        << std::format("{}:{}: ", location.file_name(), location.line())
        << std::format(format, args...);
}

auto main() -> int {
    tprintf("hello {}", "world"); // prints "example.cpp:12: hello world"
}

编译失败原因

你没有操作错误,编译失败是因为GCC 13.1对C++20中std::source_location作为模板默认参数的支持存在兼容性问题。虽然C++20标准允许将std::source_location作为模板非类型参数的默认值,但GCC 13.1在处理auto类型的模板参数推导时,无法正确识别std::source_location::current()的返回类型并完成绑定,导致编译报错。

代码被采纳的原因

这段代码的核心逻辑完全符合C++20标准,在**对该特性支持完善的编译器(如Clang 14+、MSVC 2022+)**下可以正常编译运行。Stack Overflow的答案被采纳,通常是因为其思路正确、贴合标准需求:它利用模板默认参数的特性,在函数调用点自动捕获当前的源位置信息,无需用户手动传递std::source_location参数,这正是std::source_location设计的典型用法之一,能简化日志、调试类代码的编写。

可兼容GCC 13.1的修正代码

有两种方式可以让代码在GCC 13.1上正常编译:

方式1:将source_location作为函数默认参数

把std::source_location从模板参数移到函数参数列表,作为默认参数:

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

template<typename... Targs>
auto tprintf(char const* format, Targs const&... args, 
             const std::source_location& location = std::source_location::current()) -> void {
    std::cout
        << std::format("{}:{}: ", location.file_name(), location.line())
        << std::format(format, args...);
}

auto main() -> int {
    tprintf("hello {}", "world"); // 输出对应文件行号和内容
}

方式2:显式指定模板参数类型

将模板参数的auto替换为明确的std::source_location类型,避免编译器推导:

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

template<typename... Targs, std::source_location location = std::source_location::current()>
auto tprintf(char const* format, Targs const&... args) -> void {
    std::cout
        << std::format("{}:{}: ", location.file_name(), location.line())
        << std::format(format, args...);
}

auto main() -> int {
    tprintf("hello {}", "world");
}

这两种写法都能在GCC 13.1下正常编译,同时保留原代码的核心功能:自动捕获调用点的源文件和行号信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 13:27:34