Danra
Danra

Reputation: 9906

Enforcing calling a method in all base classes

How can one implement a method which calls another method recursively for all base classes? Conceptually:

class C {
public:
    magical void recursiveWork() {
         thisClass::doWork();
         if (baseClassExists) {
              baseClass::recursiveWork();
         }
    }

    void doWork() {
        printf("bar");
    }
}

class D : public C {
public:
    void doWork() {
         printf("foo");
    }
}

D d;
d.recursiveWork(); // prints "foobar"

Upvotes: 3

Views: 107

Answers (1)

hlscalon
hlscalon

Reputation: 7552

You could use something to indicate the base class, like base_type below, and then recursively check if DoIt exists. (in this case I checked if base_type is different from self, in case of the most base class). Of course, it won't work with multiple inheritance (it should have something to identify all base_type's), and be careful with object slicing when going up on base classes.

#include <iostream>
#include <utility>

class A1
{
public:
   using base_type = A1;
   virtual ~A1(){}
   virtual void DoIt(){ std::cout << "A1\n"; }
};

class A : public A1
{
public:
   using base_type = A1;
   virtual void DoIt(){
       std::cout << "A\n"; 
   }
};

class B : public A
{    
public:
    using base_type = A;
    virtual void DoIt(){
        std::cout << "B\n"; 
    }
};

template<class...> using void_t = void;

template<class, class = void>
struct has_do_it : std::false_type { constexpr static bool value = false; };

template<class T>
struct has_do_it<T, void_t<decltype(std::declval<T&>().DoIt())>> : std::true_type { constexpr static bool value = true; };

template<typename T>
void DoItRec(T t)
{
    if (has_do_it<T>::value) {
        t.DoIt();
        if(!std::is_same<T, typename T::base_type>::value)
        {
            typename T::base_type& base = t; // get base part (object slicing)
            DoItRec(base); 
        }
    }
}

int main()
{
    B b;
    DoItRec(b);
    return 0;
}

Live example

Upvotes: 3

Related Questions