How to specify “all parameterized types” or “all argument lists” for a dynamic_cast?

為{幸葍}努か 提交于 2019-12-12 04:21:38

问题


I'm trying to call a method on a derived class. The derived class has template parameters, but I don't know what they are. How do specify “all parameterized types” or “all argument lists” for a dynamic_cast?

Below is the MCVE, but here's the thrust of the problem:

// 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();
}

The MCVE is not as minimal as I would like, but there's a few moving pieces that need to be modeled. There's also a requirement to maintain an ABI, and I suspect its responsible for a fair amount of the pain.


Example Program

// 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;
}

Compile Result

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

If I change the problem line to:

DerivedTwo<>& derived = dynamic_cast<DerivedTwo<>&>(base);

Then it results:

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

Its as if the compiler is forcing me into a specialization, rather than allowing the call to the method that's present in every DerivedTwo class. Its the reason I am looking for the way to say “all argument lists” (rather than a specialization).


If it helps, the real world code creates a digital signature. All supported signature schemes except one require a random value k. The base class has the code to create a random k. Deterministic signatures require a non-random k, and we are trying to capture it. The DoOp is trying to get the non-random k for the deterministic process.


回答1:


You cannot do what you want to.

Try a different plan.

My suggestion is another virtual method. This method does the task you want if it can be done, and fails otherwise. If there are two ways to do it, instead of failing you do whatever way works.



来源:https://stackoverflow.com/questions/41049526/how-to-specify-all-parameterized-types-or-all-argument-lists-for-a-dynamic-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!