是否可以使用预分配缓冲区的Boost.Format?
我想知道Boost.Format是否支持使用固定宽度/预分配的缓冲区作为输出,而不是由lib本身管理的动态缓冲区?是否可以使用预分配缓冲区的Boost.Format?
也就是说,正常情况下你会怎么做:
boost::format myfmt("arg1: %1%/arg2: %2%");
// e.g.:
cout << (myfmt % 3.14 % 42);
// or
string s = boost::str(myfmt % "hey!" % "there!");
所以升压:格式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
我知道我可以通过例子只是筛选,该文档和来源,但除了缺乏时间atm。 (以及错过某些东西的可能性)知道以下内容会很有趣: 如果不可能,如果有人能解释为什么(如果存在/具体的是什么) - 这是故意的吗?它不符合API吗? ...?
声明:这个问题是不是关于性能!
初步设想
望着source看来你可以用你自己的分配器,然后使用的boost::format
内部流(internal_streambuf_t
)。这对你的情况足够好吗?
例如,你可以使用类似的libstdC++ array_allocator
不幸的是boost::format
还使用了几个std::vector
不使用它可以在你的情况下,问题的自定义分配器?
如何boost::format
工作
我看着的boost::format
的来源,这是它如何工作(以下描述为str()
,<<
电话要么str()
或使用标准std::ostream
东西):
- 格式类有时使用自定义分配器,有时使用默认分配器
- 当所有参数和格式字符串分开时,将
str()
称为它cr eates新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 << '\0'; // make sure buffer contains 0-terminated string
std::cout << buffer << std::endl;
}
有用的信息。我认为分配器的一个小问题是,他们只能通过bad_alloc报告失败,对吗? –
@Martin:我认为你是对的。另外,我研究了格式的来源,我认为使用分配器很难做到。我用我发现的东西更新了我的答案。 – rve
干得好!我是否正确理解你:每次调用'.str()'时都会重新构建输出字符串? –
你要什么,当你运行的空间会发生什么?对于一个固定的buff,我会使用snprintf,但这就是我:) – nhed
@nhed如果它不合适,库可以/可以抛出一个异常或只是停止填充缓冲区(类似于[选项](http:///www.boost.org/doc/libs/1_47_0/libs/format/doc/format.html#exceptions)已提供) –
我不确定那些例外情况适用于目标缓冲区 – nhed