だから私はC++で仮想ストリーミングインターフェースを持っています
class KxStream
{
public:
virtual KxStream& operator<< ( u32 num ) = 0;
};
すべての組み込み型に対して多数の基本的な << 演算子があります。1つだけ挙げてみました。
次に、ストリーミング インターフェイスを実装するクラスをいくつか用意します。このような:
class KxCbuf : public KxStream
{
public:
KxStream& operator<<( u32 num );
}
そのため、KxCbuf にはストリーミング インターフェイスの実装があります。ここまでは順調ですね。次に、ストリーム インターフェイスをオーバーロードするいくつかのクラスがあります。
class KxSymbol
{
operator u32() const;
friend KxStream& operator<<( KxStream& os, KxSymbol sym );
};
このクラスには組み込み型へのキャスト演算子があることに注意してください。これらのクラスの 1 つを、ストリーミング インターフェイスを実装するクラスの 1 つにストリーミングしようとすると、エラーが発生します。
KxCbuf buf;
KxSymbol sym;
buf << sym; // error!
コンパイラは、使用する関数について混乱します。Gcc は正常にコンパイルされますが、これを行う方法は複数あると言われています。MSVC は、複数のオーバーロードがあると言ってコンパイルしません。
src/variable.cpp(524) : error C2666: 'KxCbuf::operator <<' : 15 overloads have similar conversions
何が起こっているのかはわかっていますが、それを満足に解決する方法はわかりません。したがって、コンパイラは KxCbuf -> KxStream をキャストしてから、フレンド関数を呼び出すことができます。これは正しいことです。または、KxSymbol -> u32 をキャストし、KxStream から継承された KxCbuf で u32 << 演算子を呼び出すことができます。
私はそれを2つの(悪い)方法で解決できます。
明確なものでストリーミングすることから始めることができます。
buf << "" << sym;
このように、"" の最初のストリーム演算子の戻り値は KxStream を返し、すべて問題ありません。または、実装クラスに冗長なストリーム演算子を実装できます。たとえば、以下を KxSymbol に追加できます。
friend KxStream& operator<<( KxCbuf& os, KxSymbol sym );
最初の答えは常に機能しますが、確かに醜いです。2 番目の答えも、冗長なストリーム オペレーターを作成する必要があり、新しいストリーム オペレーターを定義する必要がある場所で KxStream の実装が常に表示されるとは限らないという点で、醜いものです。
理想的には、KxStream インターフェイスの実装が KxStream オブジェクトのように機能し、あいまいな変換を引き起こす暗黙のキャストを回避したいと考えています。
これを解決するにはどうすればよいですか?
(ps。ライブラリのカスタムシリアライゼーションスキーム用に独自のストリーミングオペレーターを作成する必要があります。独自のシリアライゼーションクラスを持つブーストまたは同様のサードパーティライブラリを使用できません)
@Edit: KxSymbol -> u32 への変換など、コンパイラによる暗黙的な変換の使用を制御することに関連するいくつかの良い答えがありますが、残念ながら暗黙的な変換はコードにとって重要です。たとえば、KxSymbol は、文字列をテーブルに格納し、それらを数値として返すクラスで、文字列を数値として比較できるようにします。たとえば、2 つの記号が等しくない場合、文字列は同じではありません。また、一部のデータ構造ではシンボルを数値として格納します。
これを反対側から解決する方法はありますか?どうにかして、KxStream の実装を他の暗黙のキャストよりも優先して KxStream オブジェクトにキャストする必要があることをコンパイラに理解させますか?
たとえば、組み込み型に operator<< を使用する前に、まず KxCbuf を KxStream にキャストするようにコンパイラに強制するとどうなるでしょうか。これにより、KxStream よりもオーバーロード operator<< が常に優先されます。- オーバーロードには 1 つのキャストが必要で、KxStream には 2 つのキャストが必要です。