D имеет два типа констант: неизменяемые переменные - это те, которые были объявлены неизменяемыми, и всегда будет неизменным, тогда как переменные const - это просто версии объекта только для чтения.
Логическая константа - это когда функция помечена как const , но разрешает запись доступ к одной или нескольким переменным-членам. Обычно это используется для ленивых вычислений, например (в C ++)
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;
};
Здесь определитель ()
равен const
, но все еще может изменять m_dirty
и m_determinant
из-за того, что они помечены как изменяемые
.
D const (FAQ) говорит, что D2 не поддерживает логические константы из-за слабой гарантии что он обеспечивает, что является препятствием для написания параллельных программ и затрудняет определенную оптимизацию.
Я полностью понимаю проблему, но что, если нам нужна логическая константа ?
Рассмотрим приведенный выше случай с классом Matrix
, но без кэширования (и без необходимости в логической константе). Также представьте, что этот класс используется во всей моей кодовой базе и в основном доступен через константные ссылки.
Теперь учтите, что профилирование показало, что функция определитель ()
является узким местом в коде, и, более того, к нему обычно обращаются многократно, а его значение редко меняется, т.е. кэширование, как указано выше, было бы идеальной оптимизацией.
Как я могу сделать это без логической константы? Перебирать всю мою кодовую базу с заменой константных ссылок на неконстантные ссылки не вариант (по очевидным причинам).
Какие у меня есть варианты (если есть)?