如何将非可变参数的值传递给fmt :: format?

5
我正在使用优秀的fmt C++库来更加优雅地格式化字符串。
我想将非变量参数列表传递给fmt::format。它可以是std::vectorstd::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);

有没有什么办法/解决方法呢?
4个回答

9

您可以自己从 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);

4
添加额外的层,例如:
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
在当前版本(8.1.1)中,可以实现以下功能;
fmt::dynamic_format_arg_store<fmt::format_context> ds;

ds.push_back(42);
ds.push_back("PANIC");

std::string msg = fmt::vformat("The answer is {} so don't {}", ds);

1
看起来如果不对 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` 等执行相同的操作,因为这些容器的大小可以在运行时变化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接