Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Virtual Inheritance with Constructor Inheritance

I have a class hierarchy which boils down to

class Module { };

struct Port {
    Module& owner;
    Port(Module& owner) : owner(owner) {}
};

struct InPort    : virtual Port    { using Port::Port; };
struct OutPort   : virtual Port    { using Port::Port; };
struct InOutPort : InPort, OutPort { using Port::Port; };

As you can see, I would prefer to create some base functionality, and inherit it in a classic diamond pattern. I also would like to use constructor inheritance to make it as future proof as possible...

However, this does not work as written down above

prog.cpp: In function 'int main()':
prog.cpp:14:15: error: use of deleted function 'InOutPort::InOutPort(Module&)'
  InOutPort p(m);

Even replacing the definition of InOutPort with a more explicit version is not enough:

struct InOutPort : InPort, OutPort { InOutPort(Module& m) : Port(m), InPort(m), OutPort(m) { } };

Instead I seem to have to write down everything explicitly for it to work::

struct InPort    : virtual Port    { InPort(Module& m) : Port(m) { } };
struct OutPort   : virtual Port    { OutPort(Module& m) : Port(m) { } };
struct InOutPort : InPort, OutPort { InOutPort(Module& m) : Port(m), InPort(m), OutPort(m) { } };

Is there a way to combine constuctor inheritance with virtual inheritance that I am overlooking?
If not, what alternative would you use?
Maybe variadic template constructors that perfectly forwards its arguments to all bases?

like image 271
gha.st Avatar asked Apr 15 '15 14:04

gha.st


People also ask

Can we use virtual keyword with constructor?

Constructor can not be virtual, because when constructor of a class is executed there is no vtable in the memory, means no virtual pointer defined yet. Hence the constructor should always be non-virtual.

Does inheritance inherit constructors?

In inheritance, the derived class inherits all the members(fields, methods) of the base class, but derived class cannot inherit the constructor of the base class because constructors are not the members of the class.

Can we include virtual classes in multiple inheritance?

Virtual base classes are used in virtual inheritance in a way of preventing multiple “instances” of a given class appearing in an inheritance hierarchy when using multiple inheritances.

Which is virtual inheritance?

Virtual inheritance is a C++ technique that ensures only one copy of a base class's member variables are inherited by grandchild derived classes.


1 Answers

It doesn't appear that there is any way to do such a thing. In 12.9/8:

...An implicitly-defined inheriting constructor performs the set of initializations of the class that would be performed by a user-written inline constructor for that class with a mem-initializer-list whose only mem-initializer has a mem-initializer-id that names the base class denoted in the nested-name-specifier of the using-declaration and an expression-list as specified below...

In other words, the class whose constructor you inherit is the only base class that gets arguments forwarded to it. All other base classes need to have default constructors. Since you hid those default constructors in the intermediate classes by inheriting the parent constructor, you can't call them once you explicitly inherit the parent constructor.

I think you should be able to use inherited constructors for both intermediate classes and only write the explicit version for the most derived class [I didn't see that you already tried this - it does seem like a compiler bug from my understanding of the standard]. I'll update if I think of another better approach.

like image 80
Mark B Avatar answered Oct 20 '22 20:10

Mark B