Ho esaminato le seguenti domande correlate e nessuno di esse sembra risolvere il mio problema esatto: one, two, three.Questo uso di reinterpret_cast su membri struct qualificati in modo diverso è sicuro?
Sto scrivendo una collezione di cui gli elementi (coppie chiave-valore) sono memorizzate insieme ad alcune informazioni di contabilità:
struct Element {
Key key;
Value value;
int flags;
};
std::vector<Element> elements;
(Per semplicità, supponiamo che sia Key
e Value
sono i tipi standard di layout . la raccolta non verrà utilizzato con qualsiasi altro tipo comunque.)
al fine di sostenere l'accesso iteratore-based, ho iteratori che sovrascrivono operator->
e operator*
per restituire all'utente un puntatore e un riferimento, rispettivamente, scritte , t o la coppia chiave-valore. Tuttavia, a causa della natura della raccolta, l'utente non è mai autorizzato a modificare la chiave restituita. Per questo motivo, ho dichiarato una struttura KeyValuePair
:
struct KeyValuePair {
const Key key;
Value value;
};
E ho implementato operator->
sull'iteratore come questo:
struct iterator {
size_t index;
KeyValuePair *operator->() {
return reinterpret_cast<KeyValuePair *>(&elements[index]);
}
};
La mia domanda è: è questo uso della reinterpret_cast
ben definito o invoca un comportamento indefinito? Ho cercato di interpretare parti rilevanti della norma ed esaminato le risposte alle domande relative a problemi simili, tuttavia, non sono riuscito a trarre una conclusione definitiva da loro, perché ...:
- i due tipi struct condividono alcuni membri di dati iniziali (vale a dire,
key
evalue
) che differiscono solo inconst
-qualificazione; - lo standard non dice esplicitamente che
T
ecv T
sono compatibili con il layout, ma non indica il contrario; inoltre, impone loro di avere gli stessi requisiti di rappresentazione e allineamento; - Due tipi di classi di layout standard condividono una sequenza iniziale comune se il primo, tuttavia, molti membri hanno tipi compatibili con il layout;
- per i tipi di unione contenenti membri di tipo di classe che condividono una sequenza iniziale comune, è consentito esaminare i membri di tale sequenza iniziale utilizzando uno dei membri del sindacato (9.2p18). - non esiste alcuna garanzia esplicita simile su
reinterpret_cast
ed i puntatori alle strutture condividono una sequenza iniziale comune. - è, tuttavia, garantito che un puntatore a struttura punti al suo membro iniziale (9.2p19).
Usando solo queste informazioni, ho trovato l'impossibilità di dedurre se le Element
e KeyValuePair
struct condividono una sequenza iniziale comune, o di avere qualcosa di diverso in comune che giustifichi la mia reinterpret_cast
.
Per inciso, se pensate che l'utilizzo di reinterpret_cast
per questo scopo sia inappropriato, e io sto davvero affrontando un problema XY e quindi dovrei semplicemente fare qualcos'altro per raggiungere il mio obiettivo, fatemelo sapere.
Stai chiedendo un giudizio [tag: language-lawyer]? Funziona davvero? 'reinterpret_cast' è quasi sempre l'approccio sbagliato, non dovrebbe un' const_cast' funzionare bene per quello che stai rivendicando? –
@ πάνταῥεῖ sì, sto chiedendo un giudizio di un avvocato linguistico. ** Non posso dire se effettivamente funziona ** o semplicemente "sembra funzionare" poiché non so se invoca un comportamento indefinito. Non so se 'const_cast' dovrebbe funzionare in questo caso, ma fammi provare - non è ancora chiaro, tuttavia, se la compilazione di' const_cast' significherebbe che questo è ben definito. –
_ "tuttavia, se la compilazione const_cast significherebbe che questo è ben definito." _ Naturalmente, penso che sia lo scopo. L'uso di un 'reinterpret_cast' non può garantire nulla. –