C++20 std::format如何实现fmt::dynamic_format_arg_store等效功能
C++20
std::format 动态参数构建方案说明 核心限制
目前C20、C23的标准库没有公开和fmt::dynamic_format_arg_store等效的接口,不依赖编译器私有实现的前提下,无法完全复刻fmt库的动态参数构建逻辑,核心原因有两个:
std::basic_format_args只是参数集合的类型擦除视图,本身不持有参数生命周期,也没有公开的动态添加参数的接口- 标准仅提供了
std::make_format_args用来构造参数视图,它只能接收编译期数量确定的参数,没有提供运行时构造单个std::basic_format_arg的公开方法
可行替代方案
如果一定要用标准库实现动态参数格式化,可根据场景选择以下实现:
方案1:预格式化参数后拼接
这是最通用、完全符合标准要求的实现,适合所有场景,仅性能略低于原生的动态参数构建:
#include <format> #include <vector> #include <string> #include <iostream> int main() { // 动态存储预格式化的参数 std::vector<std::string> dyn_args; dyn_args.push_back(std::format("{}", 42)); dyn_args.push_back(std::format("{}", std::string{"abc1"})); dyn_args.push_back(std::format("{}", 1.5f)); // 若参数数量运行时可确定,直接按索引传入std::format即可 std::cout << std::format("{} this is my {}. This is a number: {}.", dyn_args[0], dyn_args[1], dyn_args[2]) << "\n"; // 若参数数量完全动态,可自行遍历替换格式字符串占位符 const std::string fmt_str = "{} this is my {}. This is a number: {}."; std::string result; size_t arg_idx = 0; size_t pos = 0; while (pos < fmt_str.size()) { if (fmt_str[pos] == '{' && pos + 1 < fmt_str.size() && fmt_str[pos+1] == '}') { if (arg_idx < dyn_args.size()) { result += dyn_args[arg_idx++]; } pos += 2; } else { result += fmt_str[pos++]; } } std::cout << result << "\n"; }
方案2:限定参数类型的轻量实现
如果你的动态参数只有有限几种固定类型,可以自行实现类型擦除包装类,为其特化std::formatter后即可直接存入容器,编译期确定参数数量时可以直接传给std::format。
后续规划
目前已有相关提案计划向C++标准中加入动态格式化参数的公开接口,待后续标准版本落地后就可以用标准接口实现和fmt库一致的功能。
内容的提问来源于stack exchange,提问作者Ody
相关产品推荐
相关产品推荐

