如何将不可变值传递给fmt :: format?

时间:2018-02-19 23:02:52

标签: c++ formatting variadic-functions variadic fmt

我正在使用优秀的fmt C++ library来更优雅地格式化字符串。

我想将一个非变量参数列表传递给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);

有没有方法/解决方法呢?

3 个答案:

答案 0 :(得分:3)

添加额外的图层,例如:

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,您可能在编译时获得有关预期大小的信息

答案 1 :(得分:2)

您可以自行从vformat来构建vector的参数。这似乎可行:

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 :(得分:0)

如果不对fmt库进行更改,则看起来不可能。 fmt::format调用fmt::vformat,其中fmt::format_argsfmt::wformat_args对象代表多个参数,但创建format_argswformat_args个对象的唯一方法是通过另一个可变参数函数,这意味着必须在编译时知道参数的数量和类型。

因此,您可以编写一个包装器来解压缩std::tuplestd::array并将其元素传递给fmt::format,因为这些元素的数量和类型在编译时是已知的。但是你不能对std::vectorstd::list等做同样的事情,因为这些容器的大小在运行时会有所不同。