3

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?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Dov Grobgeld
  • 4,783
  • 1
  • 25
  • 36
  • 1
    Related: [Call default copy constructor from within overloaded copy constructor](https://stackoverflow.com/questions/7297024/call-default-copy-constructor-from-within-overloaded-copy-constructor). – dxiv Mar 08 '21 at 07:25

3 Answers3

4

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");
   }
};
j6t
  • 9,150
  • 1
  • 15
  • 35
  • I would do the reverse :) making a class `LoggerA` with its special copy constructor, and then that class might be a regular member (or a parent for EBO). – Jarod42 Mar 08 '21 at 09:25
1

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

A(const A&) : A()
{
    ...
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 5
    I don't think that is what is wanted. They want the copy to happen like the compiler-generated copy constructor does, but then on top also emit a message. – j6t Mar 08 '21 at 07:04
1

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;
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302