あなたが求めているのは、マルチディスパッチ、別名マルチメソッドと呼ばれるものです。これはC++言語の機能ではありません。
特別な場合の回避策がありますが、自分でいくつかの実装を行うことを避けることはできません。
多重ディスパッチの一般的なパターンの1つは、「再ディスパッチ」、別名「再帰的遅延ディスパッチ」と呼ばれます。基本的に、1つの仮想メソッドは、すべてのパラメーターが解決されるまで、1つのパラメータータイプを解決してから、別の仮想メソッドを呼び出します。外部の関数(存在する場合)は、これらの仮想メソッドの最初のものを呼び出すだけです。
n個の派生クラスがあると仮定すると、最初のパラメーターを解決する1つのメソッド、2番目のパラメーターを解決するn、3番目のパラメーターを解決するn * nというようになります。最悪の場合、とにかく。これはかなりの手作業であり、typeidに基づく条件付きブロックを使用する方が初期開発では簡単かもしれませんが、再ディスパッチを使用する方が保守には堅牢です。
class Base;
class Derived1;
class Derived2;
class Base
{
public:
virtual void Handle (Base* p2);
virtual void Handle (Derived1* p1);
virtual void Handle (Derived2* p1);
};
class Derived1 : public Base
{
public:
void Handle (Base* p2);
void Handle (Derived1* p1);
void Handle (Derived2* p1);
};
void Derived1::Handle (Base* p2)
{
p2->Handle (this);
}
void Derived1::Handle (Derived1* p1)
{
// p1 is Derived1*, this (p2) is Derived1*
}
void Derived1::Handle (Derived2* p1)
{
// p1 is Derived2*, this (p2) is Derived1*
}
// etc
派生クラスのテンプレートを使用してこれを実装することは困難であり、それを処理するためのテンプレートメタプログラミングは、おそらく読み取り不可能で、保守不可能で、非常に壊れやすいでしょう。ただし、非テンプレートメソッドを使用してディスパッチを実装し、次にミックスインテンプレート(基本クラスをテンプレートパラメーターとして受け取るテンプレートクラス)を使用して、追加機能でそれを拡張することはそれほど悪くないかもしれません。
ビジターデザインパターンは、再ディスパッチIIRCと密接に関連しています(基本的にはそれを使用して実装されます)。
もう1つのアプローチは、問題を処理するように設計された言語を使用することです。C++でうまく機能するオプションがいくつかあります。1つは、 treeccを使用することです。これは、ASTノードと多重ディスパッチ操作を処理するためのドメイン固有言語であり、lexやyaccのように、出力として「ソースコード」を生成します。
ディスパッチの決定を処理するために行うのは、ASTノードIDに基づいてswitchステートメントを生成することだけです。これは、動的に型付けされた値クラスIDであるIYSWIMでも同じように簡単に実行できます。ただし、これらは、記述または保守する必要のないswitchステートメントであり、これが重要な違いです。私が抱えている最大の問題は、ASTノードのデストラクタ処理が改ざんされていることです。つまり、特別な努力をしない限り、メンバーデータのデストラクタは呼び出されません。つまり、フィールドのPODタイプで最適に機能します。
もう1つのオプションは、マルチメソッドをサポートする言語プリプロセッサを使用することです。Stroustrupが、ある時点でマルチメソッドをサポートするためのアイデアをかなりよく開発していたこともあり、これらのいくつかがありました。CMMはその1つです。Doublecppは別です。さらにもう1つはフロストプロジェクトです。CMMはStroustrupの説明に最も近いと思いますが、確認していません。
ただし、最終的には、多重ディスパッチは実行時の決定を行うための単なる方法であり、同じ決定を処理する方法は多数あります。スペシャリストDSLはかなりの面倒をもたらすので、通常、多数の多重ディスパッチが必要な場合にのみそれを行います。再ディスパッチとビジターパターンは堅牢なWRTメンテナンスですが、複雑さと煩雑さが犠牲になります。単純な場合には、単純な条件ステートメントの方が適している場合がありますが、コンパイル時に未処理の場合の可能性を検出することは、不可能ではないにしても難しいことに注意してください。
よくあることですが、少なくともC ++では、それを行う正しい方法は1つではありません。