Spesso è abbastanza confuso per i nuovi arrivati C++ che le funzioni membro const sono autorizzati a chiamare metodi non-const sugli oggetti a cui fa riferimento la classe (tramite puntatore o riferimento). Ad esempio, il seguente è perfettamente corretto:Propagare la costanza ai dati puntati dalle variabili membro
class SomeClass
{
class SomeClassImpl;
SomeClassImpl * impl_; // PImpl idiom
public:
void const_method() const;
};
struct SomeClass::SomeClassImpl
{
void non_const_method() { /*modify data*/ }
};
void SomeClass::const_method() const
{
impl_->non_const_method(); //ok because impl_ is const, not *impl_
};
Tuttavia, sarebbe a volte essere piuttosto utile se la costanza si propaga agli oggetti appuntiti (io ho usato volontariamente l'idioma Pimpl perché è uno dei casi in cui credo " la propagazione della costanza "sarebbe molto utile).
Quando si utilizza puntatori, questo può essere facilmente raggiunto utilizzando una sorta di puntatore intelligente con gli operatori di overload on constness:
template < typename T >
class const_propagating_ptr
{
public:
const_propagating_ptr(T * ptr) : ptr_(ptr) {}
T & operator*() { return *ptr_; }
T const & operator*() const { return *ptr_; }
T * operator->() { return ptr_; }
T const * operator->() const { return ptr_; }
// assignment operator (?), get() method (?), reset() method (?)
// ...
private:
T * ptr_;
};
Ora, ho solo bisogno di modificare SomeClass::impl_
essere un const_propagating_ptr<SomeClassImpl>
per ottenere il comportamento desiderato .
Così ho alcune domande su questo:
- ci sono alcuni problemi con costanza propagazione che ho trascurato?
- In caso contrario, esistono librerie che forniscono classi per ottenere la propagazione della costanza?
- Non sarebbe utile che i puntatori intelligenti comuni (unique_ptr, shared_ptr, ecc.) Forniscano un mezzo per ottenere questo comportamento (ad esempio attraverso un parametro template)?
Cosa succede se copio lo smart-pointer? Voilà, ne ho uno non-const. –
'T const * const operator ->() const {return ptr_; } '- Probabilmente non c'è bisogno del secondo' const' qui –
@Alf e @robin: lo schizzo che ho dato di una possibile implementazione è probabilmente pieno di bug (nonostante le sue ridotte dimensioni :)), non è il punto centrale del domanda. Tuttavia, il tuo feedback è molto apprezzato! Per quanto riguarda il problema della copia, al momento non vedo come impedire che ciò sia possibile, ma spesso non riesci a impedirti completamente di spararti nel piede (ad esempio, puoi sempre const_cast'stare via, non significa che const è inutile). Per quanto riguarda il secondo commento, hai ragione @robin, l'ho fatto erroneamente per impedire che 'ptr_' venga ... –