如何将非可变参数值传递给 fmt::format?
Posted
技术标签:
【中文标题】如何将非可变参数值传递给 fmt::format?【英文标题】:How to pass not variadic values to fmt::format? 【发布时间】:2018-02-19 23:02:52 【问题描述】:我正在使用伟大的fmt C++ library 来更优雅地格式化字符串。
我想将一个非变量参数列表传递给fmt::format
。它可以是std::vector
,或std::string
,或其他任何内容,但它始终与格式字符串匹配。
所以fmt::format
的工作方式如下:
std::string message = fmt::format("The answer is so don't ", "42", "PANIC!");
但我想要的是这样的:
std::vector<std::string> arr;
arr.push_back("42");
arr.push_back("PANIC!");
std::string message = fmt::format("The answer is so don't ", arr);
有没有办法/解决方法这样做?
【问题讨论】:
【参考方案1】:您可以从您的vector
自行构建vformat
的参数。这似乎有效:
std::string format_vector(std::string_view format,
std::vector<std::string> const& args)
using ctx = fmt::format_context;
std::vector<fmt::basic_format_arg<ctx>> fmt_args;
for (auto const& a : args)
fmt_args.push_back(
fmt::internal::make_arg<ctx>(a));
return fmt::vformat(format,
fmt::basic_format_args<ctx>(
fmt_args.data(), fmt_args.size()));
std::vector<std::string> args = "42", "PANIC!";
std::string message = format_vector("The answer is so don't ", args);
【讨论】:
【参考方案2】:添加一个额外的层,例如:
template <std::size_t ... Is>
std::string my_format(const std::string& format,
const std::vector<std::string>& v,
std::index_sequence<Is...>)
return fmt::format(format, v[Is]...);
template <std::size_t N>
std::string my_format(const std::string& format,
const std::vector<std::string>& v)
return my_format(format, v, std::make_index_sequence<N>());
用法如下:
std::vector<std::string> arr = "42", "PANIC!";
my_format<2>("The answer is so don't ", arr);
使用operator ""_format
,您可能会在编译时获得有关预期大小的信息
【讨论】:
【参考方案3】:如果不对 fmt 库进行更改,这似乎是不可能的。 fmt::format
调用 fmt::vformat
接受一个代表多个参数的 fmt::format_args
或 fmt::wformat_args
对象,但提供创建 format_args
或 wformat_args
对象的唯一方法是通过另一个可变参数函数,这意味着数量和类型参数必须在编译时已知。
因此您可以编写一个包装器来解压缩std::tuple
或std::array
并将其元素传递给fmt::format
,因为其中元素的数量和类型在编译时是已知的。但是你不能对std::vector
、std::list
等做同样的事情,因为这些容器的大小在运行时会有所不同。
【讨论】:
以上是关于如何将非可变参数值传递给 fmt::format?的主要内容,如果未能解决你的问题,请参考以下文章