2016-06-30 12 views
36

uno potrebbe desiderare per dichiarare una funzione con un argomento, e specificare che il valore predefinito per l'argomento è il risultato del costruttore di default del tipo:Nicer sintassi per impostare il valore argomento di default di costruttore di default

void foo(a::really::long::type::name arg = a::really::long::type::name()); 

Is esiste una sintassi migliore per questo che non comporta l'inserimento del nome del tipo due volte? Qualcosa di simile:

void foo(a::really::long::type::name arg = default); 

mi rendo conto che posso typedef il nome del tipo per renderla più bella, ma io sono curioso di sapere se esiste un tale sintassi.

risposta

54

Sì:

void foo(a::really::long::type::name arg = {}); 

Per riassumere le seguenti definizioni standard:

Questa è la lista di inizializzazione. A seconda del tipo, viene eseguita l'inizializzazione aggregata o viene inizializzato il valore dell'oggetto, che a sua volta implica l'inizializzazione predefinita o l'inizializzazione zero.

Alcuni casi "corner" sono quando il tipo è una specializzazione di std::initializer_list o quando il tipo ha un costruttore std::initializer_list (si chiama se non ha costruttore di default)


Le citazioni tipo pertinenti (in ordine incontriamo definizioni):

argomenti §8.3.6 predefinite [dcl.fct.default]

1 Se un inizializzatore clausola viene specificato in un parametro-de claration questo inizializzatore clausola viene usato come argomento di default

5 L'argomento predefinito ha gli stessi vincoli semantici come inizializzatore in una dichiarazione di una variabile del tipo di parametro, utilizzando la semantica copy-inizializzazione (8.5)

§8.5.4 lista inizializzazione [dcl.init.list]

1 list-inizializzazione è l'inizializzazione di un oggetto o di riferimento da a-init-list rinforzato. Tale inizializzatore è chiamato un elenco di inizializzazione , [...]. Un elenco di inizializzazione potrebbe essere vuoto. L'inizializzazione dell'elenco può verificarsi in contesto di inizializzazione diretta o copia di inizializzazione; [..] l'inizializzazione della lista in un contesto di inizializzazione della copia si chiama inizializzazione della lista di copia.

3 Elenco-inizializzazione di un oggetto o di riferimento di tipo T è definito come segue:

  • Se T è un aggregato, viene eseguita inizializzazione aggregata (8.5.1)
  • Altrimenti, se l'elenco di inizializzazione non ha elementi e T è un tipo di classe con un costruttore predefinito, l'oggetto è inizializzato in base al valore.
  • Altrimenti, se T è una specializzazione di std :: initializer_list, un oggetto initializer_list prvalue è costruito come descritto di seguito e utilizzato per inizializzare l'oggetto secondo le regole di inizializzazione di un oggetto da una classe dello stesso tipo (8.5).
  • Altrimenti, se T è un tipo di classe, vengono considerati i costruttori. I costruttori applicabili sono enumerate ed il migliore viene scelto attraverso la risoluzione di sovraccarico (13.3, 13.3.1.7) [...]
  • ...
  • In caso contrario, se la lista di inizializzazione non ha elementi, l'oggetto è valore -inizializzato.

§ 8.5 Initializers [dcl.init]

8 Per valore-inizializzare un oggetto di tipo T significa:

  • se T è un gruppo (possibilmente CV- qualificato) tipo di classe (clausola 9) con nessun costruttore predefinito (12.1) o un costruttore predefinito che è fornito dall'utente o eliminato, quindi l'oggetto è predefinito-inizializzato;
  • se T è un gruppo (possibilmente cv-qualificato) tipo di classe senza un costruttore predefinito fornito dall'utente o eliminato, l'oggetto è zero inizializzato ei vincoli semantiche per default-inizializzazione sono controllati, e se T ha un costruttore predefinito non banale, l'oggetto è inizializzato in modo predefinito;
  • se T è un tipo di matrice, quindi ogni elemento è inizializzato in base al valore;
  • altrimenti, l'oggetto è zero inizializzato

7 Per default-inizializzare un oggetto di tipo T significa:

  • se T è una classe (possibilmente cv-qualificato) type (Clausola 9), il costruttore predefinito (12.1) per T è chiamato (e l'inizializzazione è non formattato se T non ha un costruttore predefinito o una risoluzione di sovraccarico (13.3) restituisce un ambiguità o in una funzione che è cancellata o inaccessibile dal contesto dell'inizializzazione);
  • se T è un tipo di matrice, ogni elemento è inizializzato automaticamente;
  • in caso contrario, non viene eseguita alcuna inizializzazione.

6 Per zero inizializzare un oggetto o di riferimento di tipo T significa:

  • se T è un tipo scalare (3.9), l'oggetto viene inizializzato sul valore ottenuto convertendo il numero intero letterale 0 (zero) in T;
  • se T è un tipo di classe non unione (eventualmente qualificata per cv), ciascun membro di dati non statici e ciascun sottooggetto di classe base è inizializzato a zero e il riempimento è inizializzato su zero bit;
  • se T è un tipo di unione (eventualmente qualificato per il tipo cv), il primo membro dati non statico denominato nome è inizializzato a zero e il riempimento è inizializzato a zero bit;
  • se T è un tipo di matrice, ogni elemento è inizializzato a zero;
  • se T è un tipo di riferimento, non viene eseguita alcuna inizializzazione.

§13.3.1.7 inizializzazione di elenco-inizializzazione [over.match.list]

1 Quando gli oggetti di tipo non-aggregato classe T sono elenco inizializzata (8.5.4) , la risoluzione di sovraccarico seleziona il costruttore in due fasi:

  • Inizialmente, le funzioni candidate sono i inizializzatore-list costruttori (8.5.4) della classe T e arg L'elenco degli strumenti è costituito da l'elenco di inizializzazione come argomento singolo.
  • Se non viene trovato alcun costruttore di inizializzatore di inizializzazione valido, viene eseguita nuovamente la risoluzione di sovraccarico, in cui le funzioni candidate sono tutte i costruttori della classe T e l'elenco di argomenti è costituito dagli elementi dell'elenco di inizializzazione.

Se l'elenco di inizializzazione non ha elementi e T ha un costruttore predefinito , la prima fase viene omessa. [...]

+2

Non è proprio l'inizializzazione del valore. –

+0

@bolov Sei sicuro che non possa produrre un elenco di inizializzazione vuoto? E il tuo link contiene il seguente testo: "In tutti i casi, se viene utilizzata la coppia di parentesi {} vuota e T è un tipo aggregato, viene eseguita __aggregate-initialization__ anziché __value-initialization__." – ilotXXI

+1

Può anche chiamare un costruttore' initializer_list', se la classe ne ha uno e non ha un costruttore predefinito –

3

Un approccio pedonale è possibile, se si controlla la classe di arg. Utilizzare un costruttore di conversione di overload per enum:

// Define this enum, and then write constructors which take dfl 
enum dfl { dflval }; 

class a_really_long_type_name { 
public: 
    a_really_long_type_name(dfl arg = dflval); 
}; 

Ora foo può essere:

void foo(a_really_long_type_name arg = dflval); 

Se è possibile applicare questo, un vantaggio è la portabilità; questo dovrebbe funzionare bene in un compilatore C++ venticinquenne.

Più classi possono condividere questo numero dflenum e il suo zero dflval -flavored; è come avere una nuova parola chiave.

Poiché uno enum è un tipo distinto, questo non interferisce con sovraccarichi del costruttore per tipi di interi o caratteri e così via.

Lo svantaggio lo sta trasformando in alcune classi che hanno già una costruzione predefinita fornita tramite l'argomento default, che porta a duplicare il codice costruttore.

Problemi correlati