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

使用FMT库编译期检查格式化参数及默认参数问题求助

解决自定义日志器的两个FMT与source_location问题

问题1:"call to immediate function is not a constant" 编译错误

FMT_STRING要求传入编译期常量字符串,而std::string_view是运行时类型,无法作为常量表达式传递给FMT_STRING。解决方法是将格式化字符串作为模板非类型参数传入,确保它是编译期常量。

问题2:可变模板与source_location默认参数无法结合

C++中,若可变参数模板参数位于有默认值的参数之前,编译器无法区分哪些参数属于可变参数、哪些是默认参数的补位,导致无法省略std::source_location::current()。解决方法是调整参数顺序,将std::source_location参数放在可变参数之前,并保留默认值。

修正后的完整代码

#include <fmt/format.h>
#include <string>
#include <source_location>

class LoggerTask
{
public:
    // 调整参数顺序:将source_location放在可变参数前,带默认值
    template <std::size_t N, typename... Args>
    static void log(
        const char(&format_str)[N],
        const std::source_location loc = std::source_location::current(),
        const Args&... args
    );
private:
    static void log(
        std::string&& formatted_message,
        const std::source_location loc
    );
};

template <std::size_t N, typename... Args>
void LoggerTask::log(
    const char(&format_str)[N],
    const std::source_location loc,
    const Args&... args
)
{
    // 用FMT_STRING包装编译期常量字符串
    std::string formatted_message = fmt::format(FMT_STRING(format_str), args...);
    log(std::move(formatted_message), loc);
}

void LoggerTask::log(
    std::string&& formatted_message,
    const std::source_location loc
)
{
    // 实际日志写入逻辑,示例:打印位置信息和日志内容
    fmt::print("[{}:{}] {}\n", loc.file_name(), loc.line(), formatted_message);
}

int main() {
    fmt::print("The answer is {}.\n", 42);
    // 现在可以省略source_location参数
    LoggerTask::log("foo {}", 1);
    // 也可以手动指定位置(比如在封装函数中调用时)
    LoggerTask::log("bar {}{}", std::source_location::current(), 2, 3);
}

关键修改说明

  1. 编译期字符串处理:

    • 将格式化字符串改为模板非类型参数const char(&format_str)[N],确保它是编译期常量数组,满足FMT_STRING的常量表达式要求。
    • 这样FMT_STRING(format_str)可以在编译期完成格式检查,避免运行时错误。
  2. 参数顺序调整:

    • 将std::source_location参数移至可变参数Args...之前,并保留默认值std::source_location::current()。
    • 调用时,编译器可以明确推断可变参数的边界,允许省略source_location参数,符合预期用法。
  3. 优化日志传递:

    • 将私有log函数的参数改为std::string&&,避免不必要的字符串拷贝,提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 10:20:25