Aggiornamento: La risoluzione proposta di CWG 1734, attualmente in stato di "pronto", modificherebbe [class]/p6 per leggere:
Una classe banalmente copiabile è una classe:
- dove ogni costruttore di copia, costruttore di movimento, operatore di assegnazione copia e operatore di spostamento (12.8 [class.copy], 13.5.3 [over.ass]) è cancellato o banale,
- che ha almeno un costruttore di copia non cancellato, costruttore di movimento, operatore di assegnazione copia o operatore di spostamento, e
- con un distruttore banale, non cancellato (12.4 [class.dtor]).
Questo rende le classi come
struct B {
B() = default;
B(const B&) = delete;
B& operator=(const B&) = delete;
};
non è più banalmente
copiabile. (Classi di questo tipo includono primitive di sincronizzazione come std::atomic<T>
e std::mutex
.)
Tuttavia, il A
nel PO ha una implicitamente dichiarata, non cancellato copia operatore di assegnamento che è banale, così rimane banalmente copiabile.
La risposta originale per la situazione pre-CWG1734 è conservata sotto per riferimento.
Sì, un po 'controintuitivamente, è banalmente copiabile. [Class]/p6:
Un banalmente classe copiabile è una classe che:
- non ci sono costruttori non banali copia (12,8),
- non ha costruttori mossa non banali (12.8),
- non ha operatori non banali assegnazione copia (13.5.3, 12.8),
- ha nessun operatori di assegnazione mossa non banali (13.5.3, 12.8), e
- ha un distruttore banale (12.4).
[class.copy]/p12:
Una copia/spostamento costruttore per la classe X è banale, se non è fornito dall'utente, la sua parametro di tipo-list è equivalente al parametro di tipo-list di una dichiarazione implicita, e se
- classe X non ha alcuna fu virtuale nctions (10.3) e nessuna classe base virtuale (10.1), e
- la classe X non ha membri di dati non statici di tipo volatile e
- il costruttore selezionato per copiare/spostare ogni sottobase di classe di base diretta è banale e
- per ogni membro di dati non statici di X che è di tipo classe (o matrice di esso), il costruttore selezionato per copiare/spostare quel membro è banale;
Analogamente ([class.copy]/p25):
Una copia/spostamento operatore di assegnazione per la classe X è banale se non è , la sua parametro di tipo fornito dall'utente -list è equivalente al parametro di tipo-list di una dichiarazione implicita, e se
- classe X non ha funzioni virtuali (10.3) e senza classi base virtuali (10.1), e
- classe X non ha membri dati non statici della volatili qualificato tipo, e
- l'operatore di assegnazione selezionato da copiare/spostare ogni diretto subobject di classe base è banale e
- per ogni membro di dati non statici di X che è di tipo classe (o matrice di esso), l'operatore di assegnazione selezionato per copiare/spostare quel membro è banale;
[class.dtor]/p5:
Un distruttore è banale se non è fornita dall'utente e se:
- il distruttore non è
virtual
,
- tutte le classi di base dirette della sua classe hanno distruttori banali e
- per tutte le unità non statiche i membri di dati della sua classe che sono di tipo classe (o array di essi), ciascuna di queste classi ha un distruttore banale .
[dcl.fct.def.predefinita]/p5:
Una funzione viene fornito dall'utente se è user-dichiarata e non esplicitamente in default o cancellato la sua prima dichiarazione.
Infatti, questo è stato a source of problems for the committee itself, perché sotto l'attuale definizione atomic<T>
(insieme con mutex e variabili di condizione) sarebbe banalmente copiabile. (E ovviamente, consentire a qualcuno di fare lo atomic
o uno atomic
o un mutex
senza invocare UB sarebbe ... diciamo solo seriamente problematico.) Vedi anche N4460.
Perché pensi che la memcpy si comporti diversamente se il costruttore di copie non è stato cancellato? – iheanyi
@iheanyi: Perché ci sono delle regole su ciò che puoi e non puoi fare con lo storage che supporta un oggetto. –
@LightningRacisinObrit No, non c'è. Posso fare tutto ciò che voglio con esso. – iheanyi