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

时间:2011-11-02 13:33:49

标签: c++ boost buffer 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!");

所以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

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

免责声明:此问题关于效果!

1 个答案:

答案 0 :(得分:5)

初步想法

查看source,您似乎可以使用自己的分配器,然后由internal_streambuf_t的内部流(boost::format)使用。这对你的情况是否足够好?

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

的内容

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

boost::format如何运作

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

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

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

因此,即使您在使用自定义分配器时可以找到结果字符串的位置,也只能在调用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 << '\0';  // make sure buffer contains 0-terminated string

    std::cout << buffer << std::endl;    
}