如何为dynamic_cast指定“所有参数化类型”或“所有参数列表”?

时间:2016-12-08 21:55:40

标签: c++ inheritance c++03 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类中存在的方法。这就是我寻找说“所有参数列表”(而不是专业化)的方式的原因。

如果有帮助,真实世界代码会创建数字签名。除了一个需要随机值k之外,所有支持的签名方案。基类具有创建随机k的代码。确定性签名需要非随机k,我们正试图捕获它。 DoOp正试图获得确定性过程的非随机k

1 个答案:

答案 0 :(得分:1)

你无法做你想做的事。

尝试不同的计划。

我的建议是另一种虚拟方法。如果可以完成,则此方法执行您想要的任务,否则将失败。如果有两种方法可以做到,而不是失败,你做任何有效的方法。