7

我想知道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 库会自动为您分配足够的空间并管理“输出缓冲区”。

我想知道是否有任何方法可以将预定义的非动态缓冲区与 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

我知道我可以筛选示例、文档和源代码,但除了缺乏时间 atm。(以及遗漏某些东西的可能性)知道会很有趣: 如果不可能,如果有人能解释为什么(如果有/有具体的原因),那就太好了——这是故意的吗?它与 API 不匹配吗?...?

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

4

1 回答 1

5

最初的想法

查看源代码,您似乎可以使用自己的分配器,然后internal_streambuf_tboost::format. 这对你的情况足够好吗?

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

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

boost::format工作原理

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

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

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

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

为什么它会这样工作

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

解决方案

  • str()在or周围创建一些包装器<<并将结果复制到固定缓冲区中
  • 使用 astream_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;    
}
于 2011-11-03T07:52:04.587 回答