En C ++, los inicializadores de estilo C fueron reemplazados por constructores que, en tiempo de compilación, pueden garantizar que solo se realicen inicializaciones válidas (es decir, después de la inicialización, los miembros del objeto son consistentes).
Es una buena práctica, pero a veces es útil una preinicialización, como en su ejemplo. OOP resuelve esto mediante clases abstractas o patrones de diseño de creación .
En mi opinión, usar esta forma segura mata la simplicidad y, a veces, la compensación de seguridad puede ser demasiado costosa, ya que el código simple no necesita un diseño sofisticado para mantenerse mantenible.
Como solución alternativa, sugiero definir macros usando lambdas para simplificar la inicialización para que se vea casi como el estilo C:
struct address {
int street_no;
const char *street_name;
const char *city;
const char *prov;
const char *postal_code;
};
#define ADDRESS_OPEN [] { address _={};
#define ADDRESS_CLOSE ; return _; }()
#define ADDRESS(x) ADDRESS_OPEN x ADDRESS_CLOSE
La macro DIRECCIÓN se expande a
[] { address _={}; /* definition... */ ; return _; }()
que crea y llama a la lambda. Los parámetros de macro también están separados por comas, por lo que debe poner entre paréntesis el inicializador y llamar como
address temp_address = ADDRESS(( _.city = "Hamilton", _.prov = "Ontario" ));
También podría escribir macro inicializador generalizado
#define INIT_OPEN(type) [] { type _={};
#define INIT_CLOSE ; return _; }()
#define INIT(type,x) INIT_OPEN(type) x INIT_CLOSE
pero entonces la llamada es un poco menos hermosa
address temp_address = INIT(address,( _.city = "Hamilton", _.prov = "Ontario" ));
sin embargo, puede definir la macro DIRECCIÓN usando la macro INIT general fácilmente
#define ADDRESS(x) INIT(address,x)