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

如何保留函数参数consteval属性,实现支持fmt编译时格式检查的普通调用语法

解决方案

你可以直接使用fmt库提供的fmt::format_string类型作为构造函数的第一个入参,就能保留编译期格式检查,同时恢复你想要的普通调用语法,完整实现如下:

#include <fmt/format.h>
#include <stdexcept>

struct my_exception : std::runtime_error {
  template<typename... Args>
  my_exception(fmt::format_string<Args...> fmt_str, Args&&... args)
    : std::runtime_error{fmt::format(std::move(fmt_str), std::forward<Args>(args)...)}
  {}
};

实现后你就可以直接使用目标语法调用:

throw my_exception("error: {}", 123);

如果格式字符串和参数类型、数量不匹配,编译期就会直接报错,完全满足你的要求。

原理解释

你最初的朴素实现失败的核心原因是:通用的模板参数推导不会强制格式字符串为编译期常量,丢失了fmt::format要求的consteval属性。
而fmt::format_string是fmt 8.0及以上版本专门为这类场景设计的类型,它的构造函数是consteval的,仅能接受编译期可见的字符串字面量,会在实例化阶段自动完成格式字符串和参数的匹配校验,完全保留编译期检查能力的同时不需要修改调用语法。

如果你的编译环境不支持C20,也可以用兼容C17的写法,调用时用FMT_STRING宏包裹格式字符串即可,同样能保留编译期检查:

// 兼容C++17的实现
struct my_exception : std::runtime_error {
  template<typename... Args>
  my_exception(Args&&... args)
    : std::runtime_error{fmt::format(std::forward<Args>(args)...)}
  {}
};

// 调用方式
throw my_exception(FMT_STRING("error: {}"), 123);

内容的提问来源于stack exchange,提问作者Jean-Michaël Celerier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 15:36:03