Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional virtual override in c++

I have two classes B, C with pure virtual f,g functions respectively:

class B {
public:
    virtual void f() = 0;
};

class C {
public:
    virtual void g() = 0;
};

I want to create a child class A which conditionally inherits B or C. I know how to inherit from a different base class based on template parameter (let's say non-type bool template parameter):

template<bool test>
class A : public std::conditional<test, B, C>::type {
...
};

How to conditionally override f or g with respect to template parameter? Something like:

template<bool test>
class A : public std::conditional<test, B, C>::type {
public:
if constexpr (test) {
void f() override;
}
else {
void g() override;
}
}

Bonus question: is this even a good design? Should I avoid conditional inheritance? My application is far too big to use composition or some other design pattern, it would require drastic refactoring.

like image 395
toxic Avatar asked Nov 05 '25 02:11

toxic


2 Answers

What you ask for is questionable design. Suppose you get what you ask for, then all code using A also needs to branch on depending whether A has a method called f or a method called g. I am sure there is a better way to solve your actual issue. However, you don't tell us why you want A to conditionally inherit so I will turn to your question as stated...

You cannot do this directly. You can however place the conditional at a different level:

struct AB : B {
    void f() override;
}
struct AC : C {
    void g() override;
}

template <bool test>
using A = std::conditional<test, AB, AC>::type;

Alternatively specialize the whole class A for test==true and for test==false.


Why one templated class rather than two classes (like above) ?

because I have common code (bunch of private functions) which is used inside the class. If I instantiate two plain classes A_true A_false i need to copy/paste all of the private functions and have duplicate code.

No. You do not have to copy any code. Just move the common code elsewhere:

struct A_common { /* ... */ };

struct AB : B, A_common {
    void f() override;
}
struct AC : C, A_common {
    void g() override;
}

The same can be done when specializing a template class A. Generally you want to have all methods not depending on a template parameter outside of the template.

like image 187
463035818_is_not_a_number Avatar answered Nov 07 '25 14:11

463035818_is_not_a_number


I would use old fashioned way of class specialization:

template<bool test>
class A : public B {
    void f() override;
};

template<>
class A<false> : public C {
    void g() override;
};

Pros:

  • it is simple and clean

  • will work with quite old C++ standard

Cons:

  • it there is more common code this could lead to code repetition. This could be address by adding extra layer of inheritance

There is even simpler, solution. Just drop override keyword and let compiler create none virtual member function if there is no virtual equivalent in parent class.

like image 33
Marek R Avatar answered Nov 07 '25 16:11

Marek R



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!