是否可以将Boost.Format与预分配缓冲区一起使用?

Mar*_* Ba 7 c++ buffer boost boost-format

我想知道Boost.Format是否支持使用固定宽度/预分配缓冲区作为输出而不是lib本身管理的动态缓冲区?

也就是说,通常你会这样做:

boost::format myfmt("arg1: %1% / arg2: %2%");
// e.g.:
cout << (myfmt % 3.14 % 42);
// or
string s = boost::str( myfmt % "hey!" % "there!");
Run Code Online (Sandbox Code Playgroud)

因此Boost:Format lib将自动负责分配足够的空间并为您管理"输出缓冲区".

我想知道是否有任何方法可以使用具有Boost.Format的预定义非动态缓冲区,即:

const size_t buf_sz = 512;
char big_enough[buf_sz];
boost::format myfmt("arg1: %1% / arg2: %2%");
myfmt.attach_buffer(big_enough, buf_sz);
myfmt % "hey!" % "there!"
// big_enough buffer now contains the result string
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过示例,文档和来源进行筛选,但除了缺乏时间.(以及遗漏某些东西的可能性),有趣的是要知道: 如果不可能的话,如果有人可以解释原因(如果有特定的原因)会很好 - 这是故意的吗?它不符合API吗?...?

免责声明: 这个问题与性能无关!

rve*_*rve 5

初步想法

查看源代码,您似乎可以使用自己的分配器,然后由内部流(internal_streambuf_t)使用boost::format.这对你的案子来说是否足够好?

例如,您可以使用类似libstdc ++ array_allocator的东西

不幸的是boost::format还使用了一些std::vector不使用自定义分配器的情况,这可能是你的问题?

怎么boost::format工作

我查看了它的来源,boost::format这是它的工作原理(下面描述的是str(),<<调用str()或使用标准的std::ostream东西):

  • format类存储所有参数并分别格式化字符串,有时使用自定义分配器,有时使用默认分配器
  • str()被调用时创建一个新的std::string,并使其使用自定义分配器的结果足够大
  • 然后它将格式字符串中的所有参数和静态字符串片段附加到结果字符串
  • 最后它按值返回结果字符串

因此,最终结果字符串不会存储在格式类中,而是在需要时创建.

因此,即使您在使用自定义分配器时可以找到结果字符串的位置,它也只能在调用之后/期间使用str().这可以解释为什么不可能:格式化结果永远不会存储在类中的"输出缓冲区"中.

为什么它这样工作

为什么他们这样做我不知道.我认为这是因为你只能在所有参数都已知之后构建结果,它浪费空间来存储结果,你可能只需要一次给定格式/参数组合的结果.因此,在需要时创建它不会导致额外的工作,因为通常str()只调用一次.

解决方案

  • 创建一些包装器str()<<将结果复制到固定缓冲区中
  • 使用a stream_buffer将字符串"流"到缓冲区中(参见下面的示例)
  • 继承该类并添加您自己的str()函数,该函数将结果存储在固定缓冲区中.

使用boost :: iostreams(已测试)的可能解决方案:

#include <iostream>
#include <boost/format.hpp>
#include <boost/iostreams/stream.hpp>

int main()
{
    char buffer[100];

    boost::iostreams::stream<boost::iostreams::array_sink>
        stream(buffer, sizeof(buffer));

    stream << (boost::format("arg1 = %1%") % 12.5);
    stream << '\0';  // make sure buffer contains 0-terminated string

    std::cout << buffer << std::endl;    
}
Run Code Online (Sandbox Code Playgroud)