【问题标题】:How to pass not variadic values to fmt::format?如何将非可变参数值传递给 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);

有没有办法/解决方法这样做?

【问题讨论】:

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


    【解决方案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_argsfmt::wformat_args 对象,但提供创建 format_argswformat_args 对象的唯一方法是通过另一个可变参数函数,这意味着数量和类型参数必须在编译时已知。

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

        【讨论】:

          猜你喜欢
          • 2023-01-21
          • 2012-05-22
          • 1970-01-01
          • 2022-06-17
          • 2016-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多