thisconst qualifier

Сергей Тиунов
Сергей Тиунов

Мотивация

Рассмотрим простую структуру данных, например, массив:

template<typename E>
class array_t
{
public:
    E& operator[](size_t i) { return _elements[i]; }
    const E& operator[](size_t i) const { return _elements[i]; }
    ...
private:
    E *_elements;
    ...
};

Здесь есть пара недостатков:

Недостаток 1. Абсолютно идентичные реализации методов для const и не const, что приводит к дублированию кода со всеми вытекающими последствиями.

 

Недостаток 2. Семантика _elements предполагает, что const-методы класса не могут менять элементы, а остальные - могут. Однако C++ не содержит средств, чтобы это выразить, поэтому компилятор не имеет возможности это проверить. В частности, ничто не помешает сделать так:

    E& operator[](size_t i) const { return _elements[i]; }

В результате клиент получит не-const ссылку на элемент и будет иметь возможность его изменить, что нарушит обычный инвариант контейнера (константность контейнера гарантирует константность его элементов).

 

Предложение

Предлагается ввести новое ключевое слово (thisconst), которое позволит сделать так:

    thisconst E& operator[](size_t i) thisconst { return _elements[i]; }
    ...
    thisconst E *_elements;

Здесь thisconst использован в трех контекстах:

  1. Квалификатор member-функции (operator[]) - обозначает две идентичных функции для const и не const (что-то вроде шаблона функции).
  2. Квалификатор возвращаемого значения функции - означает, что возвращаемое значение const E&, если *this - const, и просто E& в противном случае.
  3. Квалификатор data member (_elements) - означает, что это указатель на const (const E *), если *this - const, и просто указатель (E *) в противном случае.

Вообще, thisconst может быть использован во всех контекстах, где можно использовать const И доступен this. В частности, помимо указанных применений, можно обозначить как thisconst аргументы member-функции, а также локальные переменные в ее теле.

Квалификатор thisconst позволяет решить два вышеприведенных недостатка, а именно:

  • скомбинировать const и non-const варианты member-функции в одном определении
  • связать константность this-объекта и других доступных объектов
-2
рейтинг
11 комментариев
yndx-antoshkka
Нечто подобное предложили добавить в стандартную библиотеку и к С++20 оно скорее всего уже окажется в стандарте: en.cppreference.com/w/cpp/experimental/propagate_const

Вместо `E *_elements;` надо будет написать `std::propogate_const<E*>_elements;` и готово :)
Но оба метода всё равно придётся написать (однако, получить неконстантную ссылку из константного метода уже не получится):
E& operator[](size_t i) const { return _elements[i]; } // compile time error
yndx-antoshkka
Сергей Тиунов
yndx-antoshkka, Хорошее предложение :) не хватает только operator[] (по крайней мере на cppreference)
Сергей Тиунов
ru.night.beast
на rsdn было более общее предложение:
rsdn.org/forum/cpp/4541793.1
ru.night.beast
Сергей Тиунов
ru.night.beast, правильно я понял, что преимущество в том, что можно сделать возвращаемый тип зависимым от константности?
Сергей Тиунов
ru.night.beast
Сергей Тиунов, не только возвращаемый, но и параметры.
все обсуждение (rsdn.org/forum/cpp/4541793) глянь, там и другие примеры были.
но насколько я понял, Николай это предложение в комитете не предлагал.
можно уточнить, если интересно.
ru.night.beast
smertigdon
Было похожее: stdcpp.ru/proposals/b41bac7b-f618-4ae0-b0fa-c3744ba26b9b
В комментарии был предложен вариант, который мне лично очень нравится, но нужно мнение опытных людей - ввести операторы const(bool) и volatile(bool), позволив писать:

template <bool constness>
const(constness) E& operator[](size_t i) const(constness) { return _elements[i]; }
smertigdon
Antervis
E& operator[](size_t i) const { return _elements; } - нелегальная конструкция, мутабельную ссылку можно получить только через const_cast
Antervis
Сергей Тиунов
Antervis, Вы не правы, это совершенно легальная конструкция в С++.
Посмотрите, например, сюда: cpp.sh/2j2o
Код компилируется и выполняется.
Сергей Тиунов
zamazan4ik@tut.by
Сергей Тиунов, А я на godbolt и ideone проверил - и ничего не собирается (и не должно как бы). ideone.com/CfXuhn
zamazan4ik@tut.by
Сергей Тиунов
zamazan4ik@tut.by, Antervis,

Господа, перечитайте, пожалуйста, еще раз внимательнее основной текст предложения.
В нем речь о распространении const на элементы, на которые указывает указатель. В Ваших примерах нет членов-указателей, поэтому они (примеры) не имеют отношения к поставленной проблеме.
Сергей Тиунов
Andrey Davydov
Andrey Davydov
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).