Аргументы конструктора для виртуальных базовых классов

Рассмотрим следующий код:

class A {
int i;
public:
A(int index) : i(index) {}
int get() { return i; }
};

class B : virtual public A {
public:
using A::A;
};

class C : virtual public A {
public:
using A::A;
};

class D : public B, public C {
public:
D(int i) : A(i), B(i), C(i) {}
};

int main() {
D d(1);
return 0;
}

В то время как clang 3.7 принимает вышеизложенное, gcc 4.8 с -std=c++11 жалуется на этот код:

 In constructor 'D::D(int)':
20:29: error: use of deleted function 'B::B(int)'
D(int i) : A(i), B(i), C(i) {}
^
10:12: note: 'B::B(int)' is implicitly deleted because the default definition would be ill-formed:
using A::A;
^
10:12: error: no matching function for call to 'A::A()'
10:12: note: candidates are:
4:3: note: A::A(int)
A(int index) : i(index) {}
^
4:3: note:   candidate expects 1 argument, 0 provided
1:7: note: constexpr A::A(const A&)
class A {
^
1:7: note:   candidate expects 1 argument, 0 provided
1:7: note: constexpr A::A(A&&)
1:7: note:   candidate expects 1 argument, 0 provided
20:29: error: use of deleted function 'C::C(int)'
D(int i) : A(i), B(i), C(i) {}
^
15:12: note: 'C::C(int)' is implicitly deleted because the default definition would be ill-formed:
using A::A;
^
15:12: error: no matching function for call to 'A::A()'
15:12: note: candidates are:
4:3: note: A::A(int)
A(int index) : i(index) {}
^
4:3: note:   candidate expects 1 argument, 0 provided
1:7: note: constexpr A::A(const A&)
class A {
^
1:7: note:   candidate expects 1 argument, 0 provided
1:7: note: constexpr A::A(A&&)
1:7: note:   candidate expects 1 argument, 0 provided

Код, который я написал, действителен в соответствии со стандартом? Это лучший способ добиться того, что я пытаюсь, то есть передать аргумент конструктора по дереву множественного наследования в общий базовый класс, который фактически содержит данные? Или я могу как-то упростить это или заставить его работать с gcc? Правильно ли я предполагаю, что класс, который наследует виртуальный базовый класс косвенно через нескольких родителей, всегда должен будет явно вызывать конструктор базы напрямую?

1

Решение

Это ошибка GCC 58751. Ваш код должен компилироваться так же, как в Clang. В прошлом у GCC были проблемы с наследованием конструкторов с виртуальным наследованием.

Обходной путь должен был бы написать конструктор пересылки вручную.

class B : virtual public A {
public:
B(int i) : A(i) {}
};

class C : virtual public A {
public:
C(int i) : A(i) {}
};
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]