在 D 中,如何声明本身可变的不可变类型的散列?

In D, how can I declare a hash of immutable types that is itself mutable?

我相信我能够在该语言的早期版本中做到这一点,事实上,我几个月前编写的代码当时编译得很好,现在却无法编译。示例:

immutable(X)[int] myhash;
myhash[5] = some_immutable_X; //previously fine.
myhash[5] = some_other_immutable_X; //previously fine also.

然而现在,dmd 抱怨

Error: cannot modify immutable expression myhash[5]

我尝试了一些其他可能的语法但没有成功(例如 (immutable X)[int])。似乎不再有办法声明哈希本身是可变的,但内容不是?这似乎是一个相当常见的用例:一种用于存储对不应更改的事物的引用的数据结构。有人对此有所了解吗?

此行为在 2.061 之前不起作用,从 2.061 到 2.066.1 一直有效。并且是2.067中的"fix".

更多信息:github pull and bug issue

如果它曾经工作过,那是一个错误(可能是由于使用 void* 和 AA 实现中某处的不正确转换,因为它尚未正确切换到模板 AFAIK)。你不能改变 immutable 值,当你这样做时

myHash[5] = value;

并且 myHash 中的元素是 immutable,那么您正在尝试改变 immutable 值,即使它是该类型的 init 值(因为一个 AA 元素在被赋值之前用 init 值初始化,类型系统无法知道该元素之前是否在 AA 中,所以它不能通过 [=18= 处理第一个赋值] 作为初始化,其他作为赋值)。如果你想拥有 immutable 元素的 AA,那么你将需要另一个间接级别,以便元素本身不是 immutable 而是引用 immutable 的东西- 例如,通过使用指向 immutable 类型的可变指针,或者如果你正在处理 classes,那么使用 std.typecons.Rebindable (因为你不能有可变的 class对 constimmutable 个对象的引用)。

我发现最简单的方法是在插入期间将关联数组和元素都转换为可变的,如下所示:

cast()myhash[5] = cast()some_immutable_X;

我在我的应用程序中做了类似的事情,我初始化了在运行时从外部源加载的不可变定义,然后在可变实体中引用它们,所以我在这里放了一个小的通用示例:http://dpaste.dzfl.pl/3a4233e5ec82