5

È possibile richiamare l'inizializzazione di aggregazione all'interno della mia definizione del ctor predefinito?Delega costruttore C++ 11 con inizializzazione aggregata

GCC si lamenta "errore: i delegati costruttore per sé" con il codice qui sotto:

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

sto usando memset(this, 0, sizeof(*this)) nel corpo ctor al momento.

+1

Se 'X' non deve essere un aggregato stesso, è possibile spostare' x, y, z ... 'in una classe base e aggregare-inizializzare la classe base su un elenco di inizializzazione del membro –

+0

@ PiotrSkotnicki Interessante idea anche se i miei colleghi lo disapprovano se lo faccio in un codice di produzione. – nodakai

+1

memset (questo, 0, sizeof (* this)) sta facendo male alla mia pace interiore ... –

risposta

1

Un modo sarebbe quello di ingannare la risoluzione di sovraccarico nel seguente modo:

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

Un altro modo sarebbe quello di utilizzare l'inizializzazione membro predefinito in-class:

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

Nel tuo esempio specifico che si poteva anche fare:

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

Penso che OP intendesse rimuovere il 'x {}, y {}, z {}, p {}, q {}, r {} 'parte del tutto –

+0

@PiotrSkotnicki l'OP dice che lui/lei sta usando ora' memset (this, 0, sizeof (* this)) ' – 101010

+0

No, OP chiede fondamentalmente come replicare la chiamata condructor di Java (in C++) – Arkadiy

0

È possibile utilizzare il CRTP per eseguire questa operazione.

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


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

Ma non sto garantendo che questo sia sicuro.

+1

non è quello che intendevo :(. Con l'inizializzazione di aggregazione intendevo 'struct A: B {A(): B {} {}};' con 'struct B {int x, y, z;};' –

+0

@ PiotrSkotnicki, intendevi spingere i membri alla base, ma non risolve i problemi dell'OP, rinomina solo la classe in cui appare, ho unito i due approcci: – StoryTeller

+0

@PiotrSkotnicki, nessuna menzione di te viene fatta su questo abominio :) – StoryTeller

0

Usa factory pattern - spostare il corpo del costruttore per classe separata:

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

struct XFactory { 
    X create(); 
}; 

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

Anche se ho sempre preferisco modello di fabbrica - c'è anche altro modo più allineati alle vostre esigenze esplicite - definire di default costruttore per ciascuno dei vostri dati utente:

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

e usarlo:

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

Copia ridondante a bizzeffe. E non rimuove il codice ingombrante che l'OP si è lamentato, ma lo sposta fuori dall'intervista. – StoryTeller

+0

@StoryTeller RVO - https://en.wikipedia.org/wiki/Return_value_optimization - impedisce la copia ridondante ... – PiotrNycz

+0

RVO è un'ottimizzazione (non una garanzia), e deve esserci ancora almeno in copia se lo si fa assegnazioni. Per non parlare, è impossibile creare oggetti const. – StoryTeller