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

+3


source to share


2 answers


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.

+6


source


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.

DEMO: http://coliru.stacked-crooked.com/a/52451127e54c8591

+2


source







All Articles