シリアライゼーションを行うために「グローバルフレンド演算子のオーバーロード」を宣言しなければならないことは、いつも面倒だと思いました。クラスの外でシリアライゼーション演算子を宣言しなければならないことは、基本的なことではないように思われました。だから私はその理由についての確かな答えを探していました。
(注:すでに書かれた良い答えを見つけるために誰かがより良いGoogle-Fuを持っているなら、私はそれを読むことに興味があります。)
私が疑っているのは、技術的に可能であり、表記上の問題にすぎないということです。ライブラリが<<
andのメンバー オーバーロードを行うように設計されてい>>
た場合、左から右ではなく、右から左への一連のストリーミング操作を作成する必要があります。したがって、書く代わりに:
Rational r (1, 2);
cout << "Your rational number is " << r;
出力行を次のように記述する必要があります。
r >> ("Your rational number is " >> cout);
>>
および<<
左から右に関連付けるため、後方連鎖を開始するには括弧が必要です。r >> "Your rational number is "
それらがなければ、 before に一致するものを見つけようとします"Your rational number is " >> cout
。右から左への結合性を持つ演算子が選択されていた場合、これは回避できます。
r >>= "Your rational number is " >>= cout;
(注: ライブラリ内では、文字列リテラルのような非クラス型は、グローバル演算子のオーバーロードで処理する必要があります。)
しかし、それが限界なのでしょうか? クラスにシリアライゼーションをディスパッチする必要がある iostream スタイルの設計では、この逆転はほとんど避けられないのでしょうか? 私は他の問題を見逃していますか?
更新おそらく「問題」のより良い言い回しは、私が次のことを疑うようになったと言うことです:
自分自身をシリアライズしたい非ストリーム オブジェクトの場合、iostream ライブラリは、挿入子と抽出子がグローバル オーバーロードの代わりにクラス メンバーになるように、仮説的に設計されている可能性があります...そしてランタイム プロパティに (大幅に) 影響を与えません。しかし、これは、iostream の作成者がクライアントに右から左へのストリーミング操作を強制することを受け入れる意思がある場合にのみ機能します。
しかし、オペレーターとメンバーをグローバルにオーバーロードすることで、(右から左ではなく) 左から右に自分自身を表現する、それ以外の場合はロック解除可能な機能をロック解除できる理由について、私は直観に欠けています。問題は、後知恵、テンプレート、または C++11 のいくつかの難解な機能が代替手段を提供できるかどうかです。または、「C ++の物理学」には、ある方向に対して別の方向に固有のバイアスがあり、グローバルなオーバーロードは、それをオーバーライドするための本で唯一のコンパイル時のトリックです。