2017-09-30 41 views
7

operator<<の多くのデフォルトのオーバーロードは、ostreamのC++で提供されていますが、すべて同じように定義されているわけではありません。std :: operator <<とstd :: ostream :: operator <<

charタイプ、string種類、及び右辺ストリームのoverloadsのようなフリーnamespace -scope関数として定義される:算術タイプ、streambuf、ストリームマニピュレータ用overloadsをメンバーとして定義されているが

namespace std { 
ostream &operator<<(ostream &os, char c); 
} 

namespace std { 
ostream &ostream::operator<<(int val); 
} 

私の質問

次のような std::ostreamの機能

この区別の理由はありますか?これらの演算子のオーバーロードの呼び出しはわずかに異なります(すなわち、無料のnamespaceのADL)。したがって、最適化のために特定のタイプの演算子オーバーロードが優先される可能性があると思います。しかし、ここではstd::ostreamは、異なるタイプの両方のタイプの定義を使用します。これが意味するこの意味論的または実装の最適化に利点がありますか?

答えて

5

ノー、最適化のためのオペレータのオーバーロードの特定のタイプを優先まあ

があるかもしれない想像。 1日の終わりには、両方とも関数呼び出しとして実行されます。解決自体を過負荷にすることは明らかではありません。標準は[over.match]で指示しているので、段落26は:いずれかのオペランドがクラスまたは列挙されるタイプを有する場合

、 ユーザ定義演算子関数は、この 実装と宣言されるかもしれません演算子またはユーザー定義の変換は、 オペランドをビルトイン演算子に適した型に変換する必要があります。この のケースでは、演算子を実装するためにどの演算子関数 または組み込み演算子を呼び出すかを決定するために、オーバーロード解決が使用されます。

オーバーロード解決のための候補関数の集合は、 のメンバー候補、非メンバー候補、および組み込みの 候補の和集合である。引数リストには、演算子 のすべてのオペランドが含まれています。候補関数のセットからの最良の関数は、[over.match.viable]および[over.match.best]に従って選択された です。

これらのオペレータオーバーロードはすべて一緒に解決されます。意味の違いは、ostreamから派生したクラスはを選択することがあります。特定のメンバーが過負荷になることがあります。これは、派生クラスでオーバーロードがどのように機能するかによって行われます。明示的に宣言された過負荷のみが適用されます。これらのメンバーとは異なり、フリー関数のオーバーロードは、ostreamから派生したクラスであっても、常にオーバーロードの解決に関与します。

フリー関数オーバーロードを選択するには、派生クラスをostream&に変換する必要があるため、暗黙的な変換シーケンスのランク付けが必要です。また、すべてのオーバーロードがフリー関数である場合、あいまいさを引き起こす可能性があります。

したがって、曖昧さ(ポインタと算術型)の原因となる可能性のある型を、常に利用可能な有用な型(C-文字列と個々の文字へのポインタ)から分離することが非常にうまくいくかもしれません。そして、あまりあまり役に立たないものを隠すことで、あいまいさを避けることができます。


W.F。 ostreamは実際にはbasic_ostream<char>です。無料の機能は、ストリーミングだけを必要とするデータのために起こります。ストリーム内の文字または文字列のネイティブ「アルファベット」。したがって、basic_ostream<wchar_t>の場合、無料の関数はwchar_twchar_t*を受け入れます。シンプルなストリーミングではストリームのプライベートセクションへのアクセスは必要ありません。

その他のオーバーロードは、ストリーミングする前にシリアル化が必要なデータ用です。この直列化はストリームの内部状態と密接に結びついているため、これらのオーバーロードをメンバーにすることははるかに理にかなっています。

+0

"これらのメンバーとは異なり、フリー・ファンクションのオーバーロードは、ostreamから派生したクラスであっても、常にオーバーロード解決に関与します。 しかし、ADLのより具体的なスコープで一致する他のフリー関数でフリー関数を隠すことはできません。 –

+0

また、 'ostream'から派生したクラスからの' ostream& 'への暗黙的な変換が、フリー関数を解決する際のあいまいさを引き起こす可能性についてはっきりしていませんか?ごめんなさい! –

+1

@definecindyconst - 非表示にしません。それらに過負荷しかかかりません。メンバーは本当に隠されています(https://ideone.com/d7XLZh)。 – StoryTeller