Подтвердить что ты не робот

Виртуальное наследование с наследованием конструктора

У меня есть иерархия классов, которая сводится к

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; };

Как вы можете видеть, я бы предпочел создать некоторую базовую функциональность и наследовать ее в классическом алмазном узоре. Я также хотел бы использовать наследование конструктора, чтобы сделать его возможным как можно более вероятным...

Однако это не работает, как указано выше

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

Даже заменить определение InOutPort на более явную версию недостаточно):

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

Вместо Мне кажется, что я должен явно записать все, чтобы он работал::

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) { } };

Есть ли способ объединить наследование constuctor с виртуальным наследованием, которое я игнорирую?
Если нет, какую альтернативу вы бы использовали?
Может быть, конструкторы вариационных шаблонов, которые отлично пересылают свои аргументы во все базы?

4b9b3361

Ответ 1

Не кажется, что есть какой-то способ сделать такую ​​вещь. В 12.9/8:

... Неявно определенный наследующий конструктор выполняет набор инициализации класса, который будет выполняться с помощью написанного пользователем встроенный конструктор для этого класса с mem-initializer-list, чей только mem-initializer имеет mem-initializer-id, который называет базу класс, обозначенный в вложенном имени-спецификаторе декларации использования и список выражений, как указано ниже...

Другими словами, класс, конструктор которого вы наследуете, является единственным базовым классом, который получает аргументы, переданные ему. Все остальные базовые классы должны иметь конструкторы по умолчанию. Поскольку вы скрывали эти конструкторы по умолчанию в промежуточных классах, наследуя родительский конструктор, вы не можете вызывать их, как только вы явно наследуете родительский конструктор.

Я думаю, что вы должны иметь возможность использовать наследуемые конструкторы для обоих промежуточных классов и писать только явную версию для самого производного класса. [Я не видел, что вы уже пробовали это - это похоже на ошибку компилятора из моего понимания стандарта]. Я обновлю, если подумаю о другом лучшем подходе.