C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Derived class's function invokes base class's function

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sat, 16 Apr 2022 14:22:41 +0100
On Saturday, April 16, 2022, Frederick Virchanza Gotham wrote:
>
> This sample experimental code has two problems:
>
> (1) It invokes the base method twice on the same object
> (2) It doesn't compile because of casting to a virtual base
>
> but I think you see the idea of what I'm trying to do.
>



The following is something along the lines of what my 'precompiler' will
produce. The following self-sufficient source file compiles successfully
and runs properly:

#include <iostream>
using std::cout;
using std::endl;

class Laser {
public:
    virtual bool Trigger(void)
    {
        cout << "Laser" << endl;
        return true;
    }
};

class Laser_Nitrogen : virtual public Laser {
public:
    bool Trigger(void) override
    {
        cout << "Laser_Nitrogen" << endl;
        return false;
    }
};

class Laser_PicoSecond : virtual public Laser {
public:
    bool Trigger(void) override
    {
        cout << "Laser_PicoSecond" << endl;
        return true;
    }
};

class Laser_NitrogenPicoSecond : public Laser_Nitrogen, public
Laser_PicoSecond {
public:
    bool Trigger(void) override;
};

class IMethodInvoker {
protected:

    // All methods have one extra
    // parameter for 'this' as 'void*'
    virtual bool Trigger(void*) = 0;

    friend class Invoker;
};

class Invoker final {
protected:

    IMethodInvoker &_mi;
    void *const _this;

public:

    Invoker(IMethodInvoker &arg_mi, void *const arg_this) : _mi(arg_mi),
_this(arg_this) {}

    // The extra 'this' parameter is no longer needed
    bool Trigger(void) // not virtual
    {
        return _mi.Trigger(_this);
    }
};


template<class Base, class Derived>
class MethodInvoker final : public IMethodInvoker {
protected:

    void (*const _method)(void);

public:

    MethodInvoker(void (*const arg_method)(void)) : _method(arg_method) {}

protected:

    // All methods have one extra
    // parameter for 'this' as 'void*'
    bool Trigger(void *const arg_this) override
    {
        Base *const p = static_cast<Base*>(static_cast<Derived*>(arg_this));

        // I'm using a union here
        // because g++ gives a
        // compiler error for
        // reinterpret_cast
        union {
            void (*f)(void);
            bool (Base::*m)(void);
        } const fm = { _method };

        return (p->*fm.m)();
    }
};

bool Laser_NitrogenPicoSecond::Trigger(void)
{
    static MethodInvoker<Laser,Laser_NitrogenPicoSecond> mi_Laser(
reinterpret_cast<void(*)(void)>(&Laser::Trigger) );

    static MethodInvoker<Laser_Nitrogen,Laser_NitrogenPicoSecond>
mi_Laser_Nitrogen(
reinterpret_cast<void(*)(void)>(&Laser_Nitrogen::Trigger) );

    static MethodInvoker<Laser_PicoSecond,Laser_NitrogenPicoSecond>
mi_Laser_PicoSecond(
reinterpret_cast<void(*)(void)>(&Laser_PicoSecond::Trigger) );

    Invoker methods[] =
    {
        Invoker(mi_Laser, this),
        Invoker(mi_Laser_Nitrogen, this),
        Invoker(mi_Laser_PicoSecond, this),
    };

    for ( auto inv : methods )
    {
        inv.Trigger();

        //if ( inv->Trigger() ) return true;
    }

    cout << "Laser_NitrogenPicoSecond" << endl;

    return false;
}

int main(void)
{
    cout << "=== First Line ===" << endl;
    Laser_NitrogenPicoSecond obj;
    obj.Trigger();
    cout << "=== Last Line ===" << endl;
}

I just need to figure a strategy for how to avoid calling the same method
twice on the same Base object in cases of virtual inheritance.

Received on 2022-04-16 13:22:43