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 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とよく合っていませんか?...?

免責事項: この質問はパフォーマンスに関するものではありません。

4

1 に答える 1

5

最初のアイデア

ソースを見ると、独自のアロケータを使用できるようです。これは、 の内部ストリーム ( internal_streambuf_t)によって使用されboost::formatます。それはあなたの場合に十分でしょうか?

たとえば、 libstdc++ array_allocatorのようなものを使用できます

残念ながら、あなたのケースで問題になる可能性のあるカスタムアロケーターを使用しないものもboost::formatいくつか使用していますか?std::vector

仕組みboost::format_

のソースを調べたところboost::format、これがどのように機能するかです(以下で説明されているのはstr()、標準のものを<<呼び出すか、使用することです):str()std::ostream

  • フォーマット クラスは、すべての引数とフォーマット文字列を別々に格納します。カスタム アロケータを使用する場合もあれば、デフォルト アロケータを使用する場合もあります。
  • str()呼び出されると、新しいアロケータが作成std::stringされ、カスタム アロケータを使用して結果に十分な大きさになります。
  • 次に、フォーマット文字列のすべての引数と静的文字列の断片を結果文字列に追加します
  • 最後に、結果の文字列を値で返します

そのため、最終結果の文字列はフォーマット クラス内に保存されず、必要に応じて作成されます。

そのため、カスタム アロケータを使用しているときに結果文字列の場所を見つけることができたとしても、それは の呼び出し後または呼び出し中にしか利用できませんstr()。これは、それが不可能な理由を説明するはずです。フォーマットされた結果は、クラスの「出力バッファー」内に決して格納されません。

なぜこのように機能するのか

なぜ彼らがこのようにしたのか、私にはわかりません。すべての引数がわかっている場合にのみ結果を作成できるため、結果を格納するためにスペースが無駄になり、特定の形式/引数の組み合わせに対して結果が必要になるのはおそらく1回だけだからだと思います。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;    
}
于 2011-11-03T07:52:04.587 に答える