Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict inheritance to desired number of classes at compile-time

We have a restriction that a class cannot act as a base-class for more than 7 classes. Is there a way to enforce the above rule at compile-time?

I am aware of Andrew Koenig's Usable_Lock technique to prevent a class from being inherited but it would fail only when we try to instantiate the class. Can this not be done when deriving itself?

The base-class is allowed to know who are its children. So i guess we can declare a combination of friend classes and encapsulate them to enforce this rule. Suppose we try something like this

class AA {
   friend class BB;
   private:
      AA() {}
      ~AA() {}
};

class BB : public AA {

};

class CC : public AA 
{};

The derivation of class CC would generate a compiler warning abt inaccessible dtor. We can then flag such warnings as errors using compiler tweaks (like flag all warnings as errors), but i would not like to rely on such techniques.

Another way, but to me looks rather clumsy is:-

class B;

class InheritanceRule{
    class A {
    public:
        A() {}
        ~A() {}
    };
    friend class B;
};

class B {
public:
    class C : public InheritanceRule::A
    {};
};


class D : public InheritanceRule::A{};

The derivation of class D will be flagged as a compiler error, meaning all the classes to be derived should be derived inside class B. This will allow atleast an inspection of the number of classes derived from class A but would not prevent anyone from adding more.

Anyone here who has a way of doing it ? Better still if the base-class need not know who are its children.

NOTE: The class which acts as a base-class can itself be instantiated (it is not abstract).

Thanks in advance,

EDIT-1: As per Comment from jon.h, a slight modification

// create a template class without a body, so all uses of it fail
template < typename D> 
class AllowedInheritance;

class Derived; // forward declaration
// but allow Derived by explicit specialization 
template<> 
class AllowedInheritance< Derived> {};

template<class T>
class Base : private AllowedInheritance<T> {};

// privately inherit Derived from that explicit specialization    
class Derived : public Base<Derived> {};

// Do the same with class Fail Error
// it has no explicit specialization, so it causes a compiler error
class Fail : public Base<Fail> {}; // this is error

int main()
{   
   Derived d;

   return 0;
}
like image 717
Abhay Avatar asked Sep 11 '25 17:09

Abhay


1 Answers

Sorry, I don't know how to enforce any such limit using the compiler.

Personally I wouldn't bother trying to force the rule into the code itself - you are cluttering the code with stuff that has nothing to do with what the code is doing - it's not clean code.

Rather than jumping through hoops, I'd try to get that rule relaxed. Instead it should be a guideline that could be broken if necessary and in agreement with others in the team.

Of course, I lack the knowledge of exactly what you're doing so the rule could be appropriate, but in general it probably isn't.

Any programming "rule" that says you must never do x or you must always do y is almost always wrong! Notice the word "almost" in there.

Sometimes you might need more than 7 derived classes - what do you do then? Jump through more hoops. Also, why 7? Why not 6 or 8? It's just so arbitrary - another sign of a poor rule.

If you must do it, as JP says, static analysis is probably the better way.

like image 127
markh44 Avatar answered Sep 13 '25 07:09

markh44