nodakai
nodakai

Reputation: 8001

C++11 constructor delegation with aggregate initialization

Is it possible to invoke aggregate initialization within my own definition of the default ctor?

GCC complains "error: constructor delegates to itself" with the below code:

struct X {
  int x, y, z, p, q, r;
  X(): x{}, y{}, z{}, p{}, q{}, r{} { }  // cumbersome
//X(): X{} { }  // the idea is nice but doesn't compile
};

I'm using memset(this, 0, sizeof(*this)) in the ctor body at the moment.

Upvotes: 5

Views: 433

Answers (3)

PiotrNycz
PiotrNycz

Reputation: 24347

Use factory pattern - move the body of your constructor to separate class:

struct X {
  int x, y, z, p, q, r;
};

struct XFactory {
  X create();
};

X XFactory::create()
{
   X x{};
   // do needed modification
   return x;
}

Although I'd always prefer factory pattern - there is also other way more aligned to your explicit needs - define default constructor for each of your member data:

template <typename T>
struct DefaultConstructibleData
{
   T data;
   DefaultConstructibleData() data{} {} 
};

And use it:

struct X {
  DefaultConstructibleData<int> x, y, z, p, q, r;
  X() 
  {         
       // do whatever you needs to do
       // all x,y,... are already constructed to their defaults
  }
};

Upvotes: 0

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42889

One way would be to fool overload resolution in the following way:

struct X {
  int x, y, z, p, q, r;
  X(int) : x{}, y{}, z{}, p{}, q{}, r{} { }
  X() : X(0) { }
};

Another way would be to use in-class default member initialization:

struct X {
  int x = 0, y = 0, z = 0, p = 0, q = 0, r = 0;
};

In your specific example you could also do:

struct X {
  std::array<int, 6> vars{};
};

Upvotes: 1

You may use the CRTP to do this.

template<class C>
struct ZeroInitialized
{
    ZeroInitialized() { memset((C*)this, 0, sizeof(C)); }
};


struct A : ZeroInitialized<A>
{
    int x, y, z, p, q, r;
};

But I'm making no guarantees this is safe.

Upvotes: 0

Related Questions