8

私はostreamいくつかの数学クラス (行列、ベクトルなど) の演算子をostream提供することを検討していstd::complexます。実際ostream:

///  Insertion operator for complex values.
template<typename _Tp, typename _CharT, class _Traits>
  basic_ostream<_CharT, _Traits>&
  operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x)
{
  basic_ostringstream<_CharT, _Traits> __s;
  __s.flags(__os.flags());
  __s.imbue(__os.getloc());
  __s.precision(__os.precision());
  __s << '(' << __x.real() << ',' << __x.imag() << ')';
  return __os << __s.str();
}

このパターンはブーストでも見られます。これが従う価値のあるパターンであるかどうかを判断しようとしています. 文字列ストリームに余分なヘッダーを含める必要があり、文字列ストリーム内に追加のヒープ割り当てが必要になる可能性があるという懸念がありました。

クライアントがその機能を必要とする場合、文字列ストリームを作成し、事前パスを自分で実行できることが最も合理的に提案されています。

なぜこれが良い習慣と見なされるのか、そしてそれを採用すべきかどうかを理解するのを手伝ってくれる人はいますか?

4

3 に答える 3

6

ostream で出力幅を設定し、それに std::complex を書き込むとどうなるかを考えてみてください。幅が最初の出力操作 (つまり、'('文字)だけに影響するのは望ましくありません。

std::complex i(0, 1);
std::cout << std::setw(10) << std::left << i;

これは印刷されるべきでは"(0,1)     "ありません"(         0,1)"

出力全体を 1 つの文字列として形成し、それを書き出すことで、出力はストリームに設定されたフィールド幅とその他のフォーマット フラグを尊重します。

于 2012-10-15T21:23:13.767 に答える
4

別の応答で引用されているスレッド化の理由は実際にはうまくいきません。複数のスレッドから呼び出された場合、これらの操作はアトミックではないため、文字列はストリーム バッファー レベルで分割される可能性があります。

ただし、関連する考慮事項が 2 つあります。

  1. 特定の出力について、フォーマット フラグの設定を一時的に変更したい場合。たとえば、特定の文字列が 16 進表記を使用して表示されるようにし、他の 10 進表記ではストリームを元の状態に復元する必要があるとします。
  2. さらに重要なことに、出力の意味は、width()フォーマット文字列全体が少なくとも占有する必要がある文字数です。出力演算子を別の出力演算子の内部で使用すると、複数のコンポーネントで構成される結果の文字列全体ではなく、最初の要素が幅を占めるようになります。たとえば、複素数の場合、width()実数要素、コンマ、および虚数要素の組み合わせではなく、実数要素が占めます。
于 2012-10-15T21:26:42.540 に答える
2

このパターンの主な目的の 1 つは、元のストリームのマニピュレーター/フラグを保持し、戻る前にそれらをリセットすることを避けることです。Boost.IoStateSaversはこれの必要性を排除するので、上記のライブラリを使用する方が良い方法だと思います。

于 2012-10-15T21:22:09.723 に答える