派生クラスのメソッドを呼び出そうとしています。派生クラスはテンプレートパラメータを持っていますが、私はそれらが何であるか分かりません。 dynamic_cast
の「すべてのパラメータ化された型」または「すべての引数リスト」を指定するにはどうすればよいですか?以下はdynamic_castに「すべてのパラメータ化された型」または「すべての引数リスト」を指定する方法は?
MCVEであるが、ここで問題の推力です:
// Contrived, but close approximation
DerivedOne<X> one;
// Another one
DerivedTwo<X,Y> two;
// Maybe another one somewhere...
DerivedTwo<X,Z> three;
// Here's the problem
Base& base = dynamic_cast<Base&>(two);
if (base.HasOp())
{
// By the time we get back to its a "DerivedTwo", we don't know
// or care what the template parameters are. All we know is it has
// the DoOp() method and we want to call it.
DerivedTwo& derived = dynamic_cast<DerivedTwo&>(base);
derived.DoOp();
}
MCVEは私が望むほど最小限ではありませんが、モデル化する必要があるいくつかの移動の作品があります。また、ABIを維持するという要件もあり、かなりの量の痛みに責任があると思われます。
プログラム例
// Base interface/contract
struct Base {
virtual bool HasOp() const {
return false;
}
};
// structs to use a template parameters for derived classes
struct X {}; struct Y {}; struct Z {};
// First derived class with first requirement
template <class One>
struct DerivedOne : public Base {
// Does not have DoOp()
};
// Second derived class with second requirement
template <class One, class Two>
struct DerivedTwo : public Base {
virtual bool HasOp() const {
return true;
}
virtual void DoOp() const {
// ...
}
};
int main(int argc, char* argv[])
{
// Contrived, but close approximation
DerivedTwo<X,Y> two;
// Maybe another one somewhere...
DerivedTwo<X,Z> three;
// Here's the problem
Base& base = dynamic_cast<Base&>(two);
if (base.HasOp())
{
// By the time we get back to its a "DerivedTwo", we don't know
// or care what the template parameters are. All we know is it has
// the DoOp() method and we want to call it.
DerivedTwo& derived = dynamic_cast<DerivedTwo&>(base);
derived.DoOp();
}
return 0;
}
コンパイル私は、問題の行を変更した場合
C:\test>cl.exe /TP test.cxx
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86
test.cxx
test.cxx(42) : error C2955: 'DerivedTwo' : use of class template requires template argument list
test.cxx(19) : see declaration of 'DerivedTwo'
test.cxx(45) : error C2662: 'DerivedTwo<One,Two>::DoOp' : cannot convert 'this' pointer from 'DerivedTwo' to 'const DerivedTwo<One,Two> &'
Reason: cannot convert from 'DerivedTwo' to 'const DerivedTwo<One,Two>'
Conversion requires a second user-defined-conversion operator or constructor
を結果:
DerivedTwo<>& derived = dynamic_cast<DerivedTwo<>&>(base);
は、その後、それは結果:
test.cxx
test.cxx(44) : error C2976: 'DerivedTwo' : too few template arguments
test.cxx(19) : see declaration of 'DerivedTwo'
test.cxx(19) : see declaration of 'DerivedTwo'
test.cxx(45) : error C2662: 'DerivedTwo<One,Two>::DoOp' : cannot convert 'this' pointer from 'DerivedTwo' to 'const DerivedTwo<One,Two> &'
Reason: cannot convert from 'DerivedTwo' to 'const DerivedTwo<One,Two>'
Conversion requires a second user-defined-conversion operator or constructor
そのコンパイラは専門に私を強制するのではなく、すべてのDerivedTwo
クラスの存在だメソッドの呼び出しを許可されるかのように。その理由は、私が(専門分野ではなく)「すべての議論一覧」を言う方法を探している理由です。
実際のコードでは、デジタル署名が作成されます。 1つを除くすべてのサポートされている署名方式は、ランダム値k
を必要とします。基本クラスには、ランダムk
を作成するコードがあります。確定性のある署名には、ランダムでないものが必要ですk
、これをキャプチャしようとしています。 DoOp
は、確定的プロセスのために非ランダムk
を取得しようとしています。
テンプレートの特殊化のいくつかがメソッドを省略することができるので、どのテンプレートインスタンス化にもキャストすることはできないと思います...あなたができることは、 'Base'と' DerivedTwo'の間に中間抽象クラスを作成できます... –
'DoOp'をベースに仮想として定義し、' HasOp'がそこにあると言っていない場合は呼び出さないでください。これを行う1つの方法は 'DoOp'をプライベートにして、それを呼び出す前に存在するかどうかをチェックするパブリック関数を追加することです。別の方法は、基本クラスに空の実装を提供することです。派生型がそれをオーバーライドしない場合に呼び出されます。 –
@jww [例](http://melpon.org/wandbox/permlink/Cn5jDMxFPSuyUUk1) –