Думаю, что было бы уместно опубликовать основные выводы недавняя ветка по этой теме в группе новостей D здесь, чтобы те, кто не отслеживает этот список, могли получить соответствующий ответ.
Константа D не является логической константой. Оно транзитивно и полностью константно. Язык технически не поддерживает логическую константу. Язык не определяет способа изменения константного объекта.
И на самом деле в С++ тоже нет логической константы. Использование mutable
и отбрасывание const-ness позволяет вам полностью обойти const, так что, с технической точки зрения, const на самом деле ничего не гарантирует, кроме того, что вы не вызываете никаких неконстантных функций для константной переменной. Тот факт, что константные функции на самом деле являются константными и не связаны с вашими переменными, полностью поддерживается соглашением. Теперь большинство программистов не отбрасывают константность влево и вправо и делают все изменяемым, поэтому на практике это весьма полезно, но его можно не только полностью обойти, но и язык специально дает вам определенные средства для этого. . В C++ mutable
и отбрасывание const четко определены и поддерживаются языком.
Д так не делает. Константа D на самом деле константа. Отбрасывание const для переменной и последующее ее изменение не определено. Изменяемого нет. У const D есть реальные гарантии (пока вы не делаете ничего неопределенного, например, отбрасываете const на что-то, а затем мутируете). Это важно не только потому, что гарантии компилятора для D намного сильнее, чем для C++, но и потому, что неизменяемые переменные нельзя изменить каким-либо образом форму или форму. Они могут находиться в памяти только для чтения, и кто знает, какие ужасные вещи произойдут, если вы попытаетесь отказаться от неизменяемости и изменить такую переменную (segfault, вероятно, будет самым приятным, что может случиться). А поскольку константная переменная на самом деле может ссылаться на неизменяемые данные, отбрасывание const для изменения переменной или разрешение каким-либо образом изменять константные переменные было бы, по меньшей мере, плохо. Так язык не позволяет.
Теперь, как указывает BCS, D является прагматичным языком. Вы можете отказаться от const, после чего вы можете изменить переменную. Так, например, у вас может быть переменная, которая использовалась для кэширования возвращаемого значения функции const (предположительно, с тем, что этот кеш становится недействительным, если состояние объекта изменилось) и отбросить const, чтобы изменить его. Пока рассматриваемая переменная на самом деле не является неизменной, она будет работать. Однако это неопределенное поведение. Как только вы это сделаете, вы сами по себе. Вы обходите систему типов и гарантии компилятора. Вы несете ответственность за то, чтобы не сделать это с неизменяемым объектом или иным образом не испортить то, что компилятор обычно гарантирует. Итак, если вам нужно это сделать, вы можете, но вы выходите на Дикий Запад, и вы должны убедиться, что вы не мутируете то, что не должны.
Учитывая, что отбрасывание const будет работать до тех пор, пока переменная на самом деле не ссылается на неизменяемые данные, можно создать шаблон Mutable
, чтобы по существу получить то, что mutable
дает вам в C++ (таким образом, он будет выполнять отбрасывание const -ness для вас). he_the_great приводит пример такого шаблона в своем ответе. Но использование такого шаблона по-прежнему является неопределенным поведением. Использование его на объекте, который на самом деле неизменяем, вызовет проблемы. Вы, программист, должны убедиться, что он используется правильно.
Таким образом, D технически позволяет иметь логическую константу, отбрасывая константу, но для этого вам нужно выйти за пределы того, что гарантирует компилятор, обходя систему типов, и вы должны убедиться, что не используете неправильно это и изменить переменные, которые не должны/не могут быть изменены, или ваш код будет иметь проблемы - вполне возможно, что segfaults будут наименьшими среди них.
EDIT: я забыл упомянуть об одном предложенном решении, которое не нарушает систему типов. Пока вы готовы отказаться от чистоты, вы можете использовать какую-либо глобальную переменную (будь то в области модуля, переменной класса или переменной структуры) для хранения кэшированных значений. Функция const может свободно использовать и изменять глобальные переменные, поэтому ее можно использовать вместо отсутствующей mutable
. Однако это означает, что функция не может быть чистой, что также может быть большой проблемой. Однако это способ, позволяющий константной функции изменять данные, которые ей нужны, без нарушения системы типов.
person
Jonathan M Davis
schedule
01.12.2010
determinant()
для одного и того жеMatrix
без изменений в матрице, как они могут независимо знать, что могут использовать одно и то же кэшированное значение? - person Peter Alexander   schedule 19.11.2010determinant()
было константой? - person Alexander Malakhov   schedule 02.12.2010