D имеет два типа константы: неизменяемые переменные - это те, которые были объявлены неизменяемыми и всегда будут неизменными, а константные переменные - это просто версии объекта только для чтения.
Логическая константа - это когда функция помечена как const, но допускает доступ на запись к одной или нескольким переменным-членам. Типичное использование этого метода - для ленивой оценки, например. (в С++)
struct Matrix
{
double determinant() const
{
if ( m_dirty )
{
m_determinant = /* expensive calculation */;
m_dirty = false;
}
return m_determinant;
}
void set(int i, int j, double x) { m_dirty = true; ...; }
mutable bool m_dirty;
mutable double m_determinant;
};
Здесь determinant()
есть const
, но все еще может изменить m_dirty
и m_determinant
, потому что они помечены как mutable
.
D const (FAQ) говорит, что D2 не поддерживает логическую константу из-за слабой гарантии, которую она предоставляет, что является препятствием к написанию параллельных программ и затрудняет определенные оптимизации.
Я полностью понимаю беспокойство, но что, если нам нужна логическая константа?
Рассмотрим вышеприведенный случай с классом Matrix
, но без кеширования (и любой необходимости для логической константы). Также представьте, что этот класс используется по всей моей кодовой базе и в основном доступен через ссылки const.
Теперь рассмотрим, что профилирование показало, что функция determinant()
является узким местом в коде, и, кроме того, к ней обычно обращаются неоднократно, причем ее значение редко изменяется, т.е. кэширование, как указано выше, будет идеальной оптимизацией.
Как я могу сделать это без логического const? По всем моим кодовым базам изменение константных ссылок на неконстантные ссылки не является вариантом (по понятным причинам).
Какие параметры у меня есть (если есть)?