Consider the following code:
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;
}
While clang 3.7 accepts the above, gcc 4.8 with -std=c++11
complains about this code:
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
Is the code I wrote valid according to the standard? Is it the best way to achieve what I'm trying, i.e. passing a constructor argument down a multi-inheritance tree to the common base class which actually holds the data? Or can I somehow simplify this or make it work with gcc as well? Am I right to assume that a class which inherits a virtual base class indirectly via multiple parents will always have to explicitely call the constructor of the base directly?
This is GCC bug 58751. Your code should compile as it does in Clang. GCC has had problems with inheriting constructors with virtual inheritance in the past.
A workaround would be to manually write the forwarding constructor.
class B : virtual public A {
public:
B(int i) : A(i) {}
};
class C : virtual public A {
public:
C(int i) : A(i) {}
};