Reputation: 2648
I have designed the following code snippet that shows my problem (the original one is more complicated):
#include <string>
struct A
{
A(int, int) {}
A(int p1 = 0, std::string p2 = "", int p3 = 0) {} // string for breaking ambiguity with previous ctor
// There are a lot more of constructors for A class
};
struct B : public A
{
using A::A; // I want to inherit many base constructors in order to save work
// But I need this particular constructor and it should override the
// equivalent base constructor
B(int p1 = 0, std::string p2 = "", int p3 = 0) {}
};
int main(int argc, char *argv[])
{
B b(1); // gives "error: call to constructor of 'B' is ambiguous", what
// of course is true, but I would want to inherit the other
// base constructors. If I comment using A::A ==> this line compiles
B b2(2, 3); // But if I comment using A::A ==> this line does not compile
}
So, my question: is there any way to break this ambiguity without hiding the lots of other constructors having the base class?
Thanks in advance
Upvotes: 3
Views: 585
Reputation: 137301
The current inheriting constructors specification is...sort of messed up. Inheriting the A(int p1 = 0, std::string p2 = "", int p3 = 0)
constructor implicitly declares three signatures: B(int)
, B(int, std::string)
, B(int, std::string, int)
, only the last of which is suppressed because of B
's constructor declaration.
N4429, a proposal to fix numerous problems with the current specification, passed design review at the last committee meeting, and, if adopted, would fix your problem.
A workaround is to write a set of delegating constructors in B
rather than use default arguments:
B() : B(0) {}
B(int p1) : B(p1, "") {}
B(int p1, std::string p2) : B(p1, std::move(p2), 0) {}
B(int p1, std::string p2, int p3) {}
This suppresses all three signatures that would have been declared from inheriting that base class constructor.
Upvotes: 6
Reputation: 15824
If you define derived class constructor, you should call base class constructor in initialization list as follows:
struct B : public A
{
// using A::A; // I want to inherit many base constructors in order to save work
// But I need this particular constructor and it should override the
// equivalent base constructor
B(int p1 = 0, int p2 = 0, int p3 = 0):A(p1,p2,p3) {}
};
Please note, you don't need to use using statement to resolve ambiguity in your derived class as using A::A;
. When you derive publicly you will get all public and protected components of base class will be available in derived class.
DEMO: http://coliru.stacked-crooked.com/a/52451127e54c8591
Upvotes: 2