Ambiguity between base and derived constructors
I have developed the following piece of code that shows my problem (the original one is harder):
#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, is there a way to break this ambiguity without hiding a bunch of other constructors that have a base class?
Thank you in advance
source to share
The current specification for inheriting constructors ... seems to be messed up. Designer inheritance A(int p1 = 0, std::string p2 = "", int p3 = 0)
implicitly declares three signatures: B(int)
, B(int, std::string)
, B(int, std::string, int)
, only the latter of which is suppressed due to the ad designer B
.
N4429 , a proposal to fix numerous issues with the current specification, has been reviewed by the last committee meeting and, if adopted, will fix your issue.
A workaround is to write a set of delegating constructors in B
instead of using the 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 be declared from inheriting from this base class constructor.
source to share
If you are defining a derived class constructor, you must call the base class constructor on the initialization list like this:
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) {}
};
Note that you do not need to use a using statement to remove ambiguity in a derived class like using A::A;
. When you publicly learn, you will have all the public and protected components of the base class available in the derived class.
source to share