5

Ist es möglich, Aggregat-Initialisierung innerhalb meiner eigenen Definition der Standard-Ctor aufzurufen?C++ 11 Konstruktor Delegation mit Aggregat-Initialisierung

GCC beschwert "Fehler: Konstruktor Delegierten selbst" mit dem folgenden 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 
}; 

ich im Moment memset(this, 0, sizeof(*this)) im Ctor Körper bin mit.

+1

Wenn 'X' nicht selbst ein Aggregat sein muss, können Sie' x, y, z ... 'in eine Basisklasse verschieben und diese Basisklasse in einer Elementinitialisierungsliste initialisieren –

+0

@ PiotrSkotnicki Interessante Idee, obwohl meine Kollegen es missbilligen, wenn ich es in einem Produktionscode mache. – nodakai

+1

memset (this, 0, sizeof (* this)) verletzt meinen inneren Frieden ... –

Antwort

1

Eine Möglichkeit wäre, die Überladungsauflösung in folgenden Weise zu täuschen:

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

Eine weitere Möglichkeit, in seiner Klasse zu verwenden, wäre die Initialisierung Standardelement:

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

In Ihrem speziellen Beispiel könnten Sie auch tun:

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

Ich denke, OP wollte die 'x {}, y {}, z {}, p {}, q {}, r {} 'Teil insgesamt –

+0

@PiotrSkotnicki das OP sagt, dass er/sie jetzt' memset verwendet (this, 0, sizeof (* this)) ' – 101010

+0

Nein, OP im Grunde gefragt, wie Java diesen() -Konstruktor Aufruf in C++ zu replizieren – Arkadiy

0

Sie können das CRTP dazu verwenden.

Aber ich mache keine Garantien, dass dies sicher ist.

+1

das ist nicht was ich meinte :(. Mit Aggregat-Initialisierung meinte ich 'struct A: B {A(): B {} {}};' mit 'struct B {int x, y, z;};' –

+0

@ PiotrSkotnicki, du wolltest die Mitglieder an die Basis schieben, aber es löst nicht die Probleme des OPs, benennt nur die Klasse um, in der es erscheint.Ich habe die beiden Ansätze zusammengeführt. – StoryTeller

+0

@PiotrSkotnicki, gut, keine Erwähnung von dir ist auf dieser Abscheulichkeit gemacht :) – StoryTeller

0

Verwendung factory pattern - der Körper Ihrer Konstruktor eigene Klasse verschieben:

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

struct XFactory { 
    X create(); 
}; 

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

Obwohl ich immer Fabrik Muster bevorzugen würde - es gibt auch andere Art und Weise auf Ihre expliziten Bedürfnisse ausgerichtet ist mehr - definieren Standard Konstruktor für jedes Ihrer Mitgliedsdaten:

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

und es verwenden:

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 
    } 
}; 
+0

Redundantes Kopieren in Hülle und Fülle. Und es entfernt nicht den umständlichen Code, über den sich das OP beschwert hat, sondern verschiebt es einfach außerhalb des C'tors. – StoryTeller

+0

@StoryTeller RVO - https://en.wikipedia.org/wiki/Return_value_optimization - verhindert redundantes Kopieren ... – PiotrNycz

+0

RVO ist eine Optimierung (keine Garantie), und es muss immer noch mindestens auf Kopie gemacht werden, wenn Sie dies tun Zuordnungen. Ganz zu schweigen davon, dass Sie es unmöglich machen, konstante Objekte zu erstellen. – StoryTeller