thassan
thassan

Reputation: 401

C++ At runtime check whether function signature exists?

The current situation is this: I am going through some code re factoring

enter image description here

If you look at the image the current situation is that I have a virtual method setData(int ID); now we want to change that to a virtual method setData(dataObj aObj);

But doing so, is a long process since, our foo object has been inherited by tons of classes. So, we want to gradually make the code change.

As such, what I need to do is to check if one of the inherited classes has implemented setData(dataObj aObj) call that class, else call the other previous function signature setData(int ID); The problem is further complicated by the fact that, FOO class provides a default setData(int ID) previously and not all classes that inherit from FOO thus may/may not need to implement setData and their implementations do vary wildly.

I have already looked at How to Check if the function exists in C/C++ unfortunately, that does not answer my questions.

In some of the posts I have seen people use templates, that's not an option for me, since this needs to be done at runtime. The other options seems to suggest linking /mangling tricks with GCC etc. I need to build my code to be platform and compiler independent. So that's not an option either.

Any more suggestions, the only possible close solution seems to be https://stackoverflow.com/a/8814800/1376317 But I am really not sure how to implement this in my workflow, or whether this is even relevant to my problem.

Upvotes: 1

Views: 782

Answers (2)

rakeshdn
rakeshdn

Reputation: 135

If modifying dataObj class is an option, and creating and destroying dataObj objects are not too expensive, then you can consider the following. I don't particularly like it but as far as short term hacks go, I have seen worse...

class dataObj
{
int x;
public:
    int getID(void) const { 
        std::cout << "dataObj::getID " << std::endl;
        return x;
    }
    dataObj() : x(0){}
    ~dataObj(){}

};
class Foo
{
public:
    // Old interface
    virtual void setData(int ID) {
        /* Old default implementation */
        std::cout << "Foo::setData int" << std::endl;
    }

    // New interface
    virtual void setData(const dataObj& aObj) {
        /* New default implementation */
        std::cout << "Foo::setData dataObj" << std::endl;
        setData(aObj.getID());
    }

};

class A : public Foo
{
public:
    virtual void setData(int ID) {
        /* Old default implementation */
        std::cout << "A:: setData int" << std::endl;
    }

};

class B : public Foo
{
public:
    virtual void setData(const dataObj& aObj) {
        /* Old default implementation */
        std::cout << "B:: setData dataObj" << std::endl;
    }

};

int main(int argc, char* argv[])
{
    A a;
    B b;
    dataObj d;
    Foo* pa, * pb;
    pa = &a;
    pb = &b;
    pa->setData(d);
    pb->setData(d);
return 0;
}

Upvotes: 1

Jarod42
Jarod42

Reputation: 217398

You may do something like:

class Foo
{
public:
    // Old interface
    virtual void setData(int ID) { /* Old default implementation */ }

    // New interface
    virtual void setData(dataObj aObj) { /* New default implementation */ }

    void init() {
        if (useOldInterface()) {
            setData(ID);
        } else {
            setData(aObj);
        }
    }

private:
    // temporary method to be removed once all derived classes return false.
    virtual bool useOldInterface() const { return true; }
};

And change progressively derived classes by adding

virtual bool useOldInterface() const override { return false; }

and appropriate void setData(dataObj aObj).

Upvotes: 2

Related Questions