2010-05-19 9 views
27

ho una variabile membro di tipo vector<T> (dove è T è una classe personalizzata, ma potrebbe essere int pure.) Ho una funzione da cui voglio restituire un puntatore a questa vettore, ma non voglio che il chiamante sia in grado di cambiare il vettore o gli elementi. Quindi voglio che il tipo restituito sia const vector<const T>*Fusioni vettore <T> al vettore <const T>

Nessuno dei metodi di fusione che ho provato ha funzionato. Il compilatore continua a lamentarsi del fatto che T non è compatibile con const T.

Ecco un codice che dimostra il succo di ciò che sto cercando di fare;

vector<int> a; 
const vector<const int>* b = (const vector<const int>*) (&a); 

Questo codice non viene compilato per me.

Grazie in anticipo!

+1

perché non restituire invece riferimento const? – Anycorn

+0

[vector-and-const] (http: // stackoverflow.it/questions/2102244/vector-and-const) –

risposta

27

Se si dispone di un const vector<int> non è possibile modificare il contenitore, né è possibile modificare alcun elemento nel contenitore. Non è necessario un const vector<const int> per raggiungere quella semantica.

+0

Avrei dovuto testarlo prima di chiederlo. L'ho provato ora e funziona come hai descritto tu. Grazie. – user345386

+2

ma cosa succede se ho vettore ? Ha senso la maggior parte del tempo per creare tali vettori. – user3111311

2

è possibile forzare la conversione in questo modo:

b = reinterpret_cast<const std::vector<const int>*>(&a); 

ma non credo che si dovrebbe fare, dal momento che non è garantito il funzionamento, solo per compilare

+2

Dato che l'OP ha usato un cast in stile c, questo è in effetti effettivamente ciò che hanno cercato di fare. Un cast in stile c farà una reinterpretazione del cast quando i tipi non sono correlati e il vettore non è correlato al vettore o qualsiasi altra cosa. –

14

Oltre alla risposta di James su come per farlo dovresti notare che const int non è un tipo valido da inserire in un contenitore standard poiché non è assegnabile.

12

Sul perché un vector<T> non possono essere convertiti correttamente un vector<const T> anche se T possono essere convertiti const T

Questo è un problema ricorrente comune nella programmazione se è con costanza o eredità (un contenitore di oggetto derivato non può essere convertito in un contenitore di oggetti di base, anche se gli stessi elementi contenuti possono). Il problema è che elemento per elemento ognuno di essi può essere convertito, ma il contenitore stesso non può senza rompere il sistema di tipi.

Se fosse consentito fare vector< const T > &vr = my_vector_of_T, sarà consentito aggiungere elementi tramite vr e tali elementi sarebbero costanti per definizione. Ma allo stesso tempo quegli stessi elementi sarebbero aliasati in my_vector_of_T come elementi non-const e potrebbero essere modificati attraverso quell'interfaccia, interrompendo la costanza nel sistema dei tipi.

Nel caso particolare di un vector<int> essere convertito in un vector<const int>, è probabile che non si nota effetti davvero strano --besides aggiunta di un elemento a un vector<const int> e vedere come le costanti elemento viene modificato nel tempo, ma ancora ricorda che dati due tipi correlati T1 e T2 per i quali esiste una relazione, nella maggior parte dei casi si tenta di applicare la stessa relazione ai contenitori di T1 e T2 interromperà il sistema di tipi.

+0

+1 per spiegare perché alterare il contenitore può causare problemi anche se i riferimenti nel contenitore sono const. –

0

Il compilatore decide di bloccarlo. Tuttavia, sappiamo che questo è sicuro, quindi forse possiamo ingannarlo:

const vector<const int>* b = (const vector<const int>*)(void *)(&a); 
+3

Beh, non è sicuro. Il tipo 'std :: vector ' non è valido perché 'std :: vector ' richiede che T sia assegnabile e 'const int' non lo sia. – MSalters

+0

La cosa divertente è che ho usato un compilatore che lo compilava fino a quando non hai provato a scrivere sul vettore, quindi ottieni un errore del compilatore davvero oscuro. – Joshua

+0

"sappiamo che questo è sicuro" - haha, wow! "safe" non è mai, non una volta, una cosa appropriata da dire su "reinterpret_cast' a qualcosa tranne" [un/signed] char const * '. Tutto il resto è definito dall'implementazione se sei fortunato e sei disposto a scrivere un codice fragile non portatile. Inoltre, (A) 'T const' non è un tipo di elemento valido, e (B) anche se lo fosse, lo Standard non ha bisogno di mettere le variabili membro di 2 istanze nello stesso ordine, quindi anche se' reinterpret_cast' ha reinterpretato l'oggetto rappresentazione sul tuo compilatore, è follia presumere che i membri compatibili vivano a compensazioni equivalenti all'interno di entrambi –

Problemi correlati