是否可以使用Boost.使用预分配的缓冲区格式化



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

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

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

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

我想知道是否有任何方法可以使用Boost的预定义非动态缓冲区。格式,即类似于:

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

我知道我可以只是筛选例子,文档和源代码,但除了缺乏时间。(而且很有可能会遗漏一些东西)知道以下这些会很有趣:如果这是不可能的,如果有人能解释为什么(如果有具体的原因),那就太好了——这是故意的吗?它和API匹配得不好吗?…?

免责声明:这个问题是关于而不是性能的!

初步构思

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

例如,您可以使用libstdc++ array_allocator

不幸的是,boost::format也使用一对不使用自定义分配器的std::vector,这可能是您的情况下的问题?

boost::format如何工作

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

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

因此,最终结果字符串不存储在format类中,而是在需要时创建。

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

为什么会这样

我不知道他们为什么这样做。我认为这是因为您只能在所有参数都已知之后构建结果,这浪费了存储结果的空间,并且对于给定的格式/参数组合,您可能只需要一次结果。因此,在需要时创建它不会导致额外的工作,因为通常str()只被调用一次。 <标题> 解决方案
  • str()<<周围创建一些包装器,并将结果复制到固定缓冲区
  • 使用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 << '';  // make sure buffer contains 0-terminated string
    std::cout << buffer << std::endl;    
}

最新更新