Распространение постоянства на данные, указанные переменными-членами

Новичков в C ++ часто сбивает с толку, что константным функциям-членам разрешено вызывать неконстантные методы для объектов, на которые ссылается класс (либо по указателю, либо по ссылке). Например, совершенно верно следующее:

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_
};

Однако иногда было бы довольно удобно, если бы константность распространялась на заостренные объекты (я добровольно использовал идиому PImpl, потому что это один из тех случаев, когда я думаю, что «распространение константности» будет быть очень полезным).

При использовании указателей этого легко добиться, используя какой-то интеллектуальный указатель с операторами, перегруженными на постоянство:

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_;
};

Теперь мне просто нужно изменить SomeClass :: impl_ быть const_propagating_ptr для получения желаемого поведения.

Итак, у меня есть несколько вопросов по этому поводу:

  1. Есть ли какие-то проблемы с распространением констант, которые я упустил?
  2. Если нет, существуют ли библиотеки, которые предоставляют классы для получения распространения констант?
  3. Разве не было бы полезно, чтобы общие умные указатели (unique_ptr, shared_ptr и т. д.) предоставляют средство для достижения такого поведения (например, с помощью параметра шаблона)?
24
задан Luc Touraille 27 November 2014 в 22:27
поделиться