2011-07-25 11 views
16

Nel definire una funzione in un'interfaccia:Const vettore di non-const oggetti

virtual void ModifyPreComputedCoeffs (std::vector <IndexCoeffPair_t> & model_) = 0; 

vogliamo specificare che il model_ vettore non deve essere modificato nel senso push_back ecc operazioni non dovrebbero essere fatte sul vettore ma è possibile modificare gli oggetti struct IndexCoeffPair_t nel modello_. Come dovremmo specificarlo?

virtual void ModifyPreComputedCoeffs (const std::vector <IndexCoeffPair_t> & model_) = 0; 

non funziona, credo.

+0

Bene, che cosa hai provato? –

+1

Non funziona, pensi? Sembra che dovrebbe funzionare, hai provato a modificarlo? – yan

+1

@yan: No, non dovrebbe funzionare perché 'vector :: operator [] const' e tutti gli altri elementi di accesso' const' restituiscono 'vector :: const_reference'. – Josh

risposta

7

Il concetto di cost-correctness C++ è sovrastimato dalla modalità IMO. Quello che hai appena scoperto è uno dei grandi limiti che ha: non scala per composizione. Per poter creare un vettore const di oggetti non const è necessario implementare il proprio tipo di vettore. Si noti che, ad esempio, anche la libreria standard ha dovuto introdurre nuovi tipi per const_iterators.

Il mio suggerimento è di usare la cost-correttezza dove sei costretto, e non ovunque tu possa. In teoria la correttezza costante dovrebbe aiutare i programmatori, ma ha un costo molto alto a causa della sintassi ed è molto primitiva (solo un bit, non scala per composizione, richiede anche la duplicazione del codice).

Anche nella mia esperienza questo presunto grande aiuto non è poi così grande ... la maggior parte degli errori che si verificano sono legati al meccanismo di const-correctness stesso e non alla logica del programma.

Vi siete mai chiesti perché la maggior parte delle lingue (comprese quelle progettate dopo C++) non ha implementato questa idea?

+9

correttezza const, indipendentemente dall'opinione, esiste in C++ ed è una caratteristica importante che, se evitata, può causare grattacapi e perdite di tempo e denaro nel codice di produzione. Mentre mi piace il sentimento (e non necessariamente non sono d'accordo), è più un commento alla domanda originale che una risposta. 6502 - hai fatto un argomento simile contro la risposta const_iterator di Mark Ransom. – Kit10

+1

@Copperpot: Sì, la correttezza const esiste in C++ e sei costretto a gestirlo, a piacergli o no. È uno dei casi in cui la presunta filosofia del "paga per quello che vuoi" non si applica perché devi pagarla anche se non la vuoi. Nella mia esperienza con C++ non riesco a ricordare nemmeno un caso (anche solo UNO) in cui un errore di correttezza const mi ha impedito di fare un errore reale. Ogni volta che il problema era nelle dichiarazioni const errate (i casi più frequenti nella mia esperienza sono quelli che dovrebbero essere i metodi const non dichiarati const). – 6502

+0

Ma assolutamente non ha senso, avere un vettore const di non-const elemets e non essere in grado di modificarli (si comporta come un vettore const di elementi const). – Nuclear

12

Invece di trasferire il vettore nella funzione, eseguire invece ciò che fa la libreria standard e passare una coppia di iteratori.

virtual void ModifyPreComputedCoeffs (std::vector <IndexCoeffPair_t>::iterator & model_begin, std::vector <IndexCoeffPair_t>::iterator & model_end) 
+2

Stai eludendo la domanda. Cosa succede se lui/lui ha bisogno di passare un vettore di tali vettori? – 6502

+0

@ 6502, che sembra un po 'fuori dalla portata della domanda originale, non credi? –

+0

Non proprio.Ha chiesto come specificare un tale vettore e lei ha suggerito che non dovrebbe passare un vettore ma due iteratori. Mentre questo può funzionare in questo caso specifico con solo un fastidio minore (due parametri invece di uno) non scala e non risponde alla domanda originale (come specificare quel vettore). Sfortunatamente la risposta in C++ è "non puoi, devi definire la tua classe vettoriale per farlo". – 6502

0

Se è possibile modificare IndexCoeffPair_t, è possibile aggiungere alcune funzioni membro const e utilizzarle per modificare alcuni dei membri rendendo i membri mutabili utilizzando la parola chiave mutabile. Questa è una specie di trucco, dal momento che ora è possibile modificare il contenuto di qualsiasi const IndexCoeffPair_t.

Esempio:

class IndexCoeffPair_t { 
public: 
    void changeX(int newVal) const { 
     x = newVal; 
    } 

private: 
    mutable int x; 
}; 
+0

Qualcosa di simile sconfigge completamente lo scopo della parola chiave 'const'. Perché anche preoccuparsi se qualcosa di essere "const" non significa nulla ... :) – UncleBens

+0

Sì, in generale si dovrebbe evitare di usare 'mutable', motivo per cui ho detto che è un hack. Tuttavia, poiché l'OP vuole che il vettore sia const ma non gli oggetti contenuti, questo risolverebbe questo problema specifico. – MahlerFive

+0

IMO, questo è il male maggiore. Una cosa è preoccuparsi del potenziale abuso futuro (?) Di una singola funzione (con quale frequenza si chiama accidentalmente "push_back'?), Un'altra cosa è dire che è OK per tutti gli utenti modificare lo stato osservabile di un oggetto const. – UncleBens

1

Questa è probabile che sia in C++ 14 come std::dynarray.

In realtà se la dimensione è fissa al momento della compilazione è possibile utilizzare std::array. Ma probabilmente è più utile per cose come programmazione embedded, buffer, matrici e così via come spesso non si conosce la dimensione desiderata fino al runtime o si desidera che sia configurabile.

+1

std :: dynarray sembra interessante, ma secondo la corrente [pagina cppreference.com su dynarray] (http://en.cppreference.com/w/cpp/container/dynarray), non sarà in C++ 14: "Dopo aver esaminato i commenti del corpo nazionale al n3690, questo componente della biblioteca è stato votato dal documento di lavoro C++ 14 in una specifica tecnica separata. Questo contenitore non fa parte del progetto C++ 14 al n3797". – Alan

+0

Sembra sempre meno probabile ... – xaxxon

Problemi correlati