const ctor (и возможно dtor)

post-increment
post-increment

Пример того, как это может работать.

class Index
{
public:
    Index(int* rhs, int len)
    : data_{rhs}
    , length_{len}
    {}

    Index(int const* rhs, int len) const
    : data_{const_cast<int*>(rhs)} // Note: only for this example
    , length_{len}
    {}
    
    Index(Index& rhs)
    : data_{rhs.data_}
    , length_{rhs.length_}
    {}

    Index(Index const& rhs) const
    : data_{rhs.data_}
    , length_{rhs.length_}
    {}


    //some other ctors and methods
    
    int  operator[](int i) const { return data_[i]; }
    int& operator[](int i) &     { return data_[i]; }
    
private:
    int* data_;
    int  length_;
};

void do_smth(Index const& ind)
{
Index ref_ind(ind);// error: non-const c-tor can't take const Index&
// do smth
}

int main
{
   int* data[10];
   for(int k = 0; k < 10; ++k)
     data[k] = k+3;
   int const* cdata = data;
   Index mut_ind(data+3, 7);          // ok
   Index const const_ind(cdata+2, 8); // ok

   mut_ind[0] = 0;   // ok
   const_ind[0] = 3; // error: can't access non-const operator[]

   do_smth(mut_ind);
   Index ind1(cdata + 1, 9); // error: non-const c-tor can't take const int* 

   Index const const_ind1(const_ind); // ok
   Index mut_ind1(mut_ind);           //ok
   Index ind2(const_ind);   // error: non-const c-tor can't take const Index&
}

В данном примере const-объект может быть создан только по const int*.
Для простоты примера я сделал const_cast.
Опасаюсь, что пример может показаться притянутым за уши, поэтому также добавил конструкторы копии.
Итак, non-const-объект в этом случае может быть создан только из non-const-объекта.

Как это можно сделать сейчас? Как мне видится...
Создать класс ConstIndex и прописать для него все const-методы.
Отнаследовать от него класс Index и про писать для него все non-const методы.
Почему так? Чтобы защитить constness объекта-ссылки от создания non-const ссылки через копию.
Если не создавать ConstIndex, то получается такой пример некорректного использования квалификатора const. 

// Bad example
class Index1
{
public:
    Index1(Index1 const& i);// copy
private:
};

void do_smth1(Index1 const& ind)
{
   Index1 ref_ind(ind);
   // got access to all non-const methods
}

Если же ввести в язык указанную конструкцию, то

  • не потребуется создавать ConstIndex.
  • получаем const-safe. функция do_smth не сможет создать non-const-объект-ссылку-на-данные и их менять.

Жду обратной связи.
Хотелось бы увидеть помимо плюсов и минусов ваше мнение, понимание и объяснение.

4
рейтинг
2 комментария
dix75
Судя по идее здесь также откроется широкое поле для оптимизации, но стоит подумать о всех нюансах, возможно такое предложение уже было.
Но приведенный пример с const_cast не считаю показательным, а вот с шаблонным классом был бы весьма уместен
dix75
post-increment
dix75, не понял про шаблонный класс. Можете привести пример?
post-increment
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).