Delegating to a default C++ constructor

Viewed 127

Assume a C++ class A with members that can all be copied by the their respective copy constructors. We can rely on the default copy constructor for A to copy its members:

class A {
  private:
    A(const A&) = default; // We don't really need this line
    int a;
    B b;
    double c;
}

But now let's assume that I want to "extend" (or annotate) the default constructor of A so that in addition to copying its members, it does something else, e.g. writes a line to a log file.

I.e. I'd like to write something like:

class A {
  public:
    A(const A& a) : A::default(A) {
      print("Constructing A\n");
    }
  private:
    // like before
}

Unfortunately that is not correct C++ syntax.

So is there a syntax which allows delegating to a default C++ constructor while explicitly defining the same constructor?

3 Answers

The simplest is to move all members into a base class and write the message in a derived class:

class A_helper {
  private:
    int a;
    B b;
    double c;
};
class A : public A_helper {
public:
   A() = default;
   A(const A& a) : A_helper(a) {
       print("Constructing A\n");
   }
   A(A&& a) : A_helper(std::move(a)) {
       print("Constructing A\n");
   }
};

You can delegate to the default constructor like you would default-initialize a member variable:

A(const A&) : A()
{
    ...
}

As often, "We can solve any problem by introducing an extra level of indirection." ( "…except for the problem of too many levels of indirection,"):

struct VerboseA
{
   VerboseA() = default;
   VerboseA(const VerboseA&) { print("Constructing A\n"); }
   VerboseA(VerboseA&&) { print("Constructing A\n"); }
};

And then

class A : VerboseA // EBO (Empty Base Optimisation)
{
private:
    A(const A&) = default; // We don't really need this line

    int a;
    B b;
    double c;
};

or in C++20

class A {
private:
    A(const A&) = default; // We don't really need this line

    [[no_unique_address]]VerboseA verbose; // "EBO" equivalent with attribute
    int a;
    B b;
    double c;
};
Related