在运行时填充 array/assoc 不可变对象数组

Filling an array/assoc array of immutable objects at runtime

是否可以在运行时在 D 中填充不可变对象的数组或关联数组?我有一组不可变的定义,其数据在运行时从外部源读取。每个定义还包含几个其他不可变对象的数组。但是,编译器似乎禁止使用循环实例化不可变数组。在这个例子中(字段数据简化):

immutable class Definition {
    string name;
    int size;
    immutable(Field)[string] fields;

    immutable class Field {
        int num;
        this (int num) {
            this.num = num;
        }
    }
    this(string name, int size) {
        this.name = name;
        this.size = size;
        foreach (i; 0..size) {
            string key = [cast(char)('a' + i)]; // a, b, c...
            auto field = new immutable(Field)(i);
            fields[key] = field; // ERROR
        }
    }
}
class Instance {
    Definition def;
    void speak() {
        writefln("I am currently referencing definition '%s' (%d)", def.name, def.size);
    }
}

auto defA = new immutable(Definition)("AAA", 4);
auto defB = new immutable(Definition)("BBB", 6);
auto instance = new Instance();
instance.def = cast(Definition) defA;
instance.speak();
instance.def = cast(Definition) defB;
instance.speak();

我收到 错误:不可变字段 'fields' 在循环中或在标签 之后不允许初始化。有没有办法解决这个问题,或者有更好的方法来实现它?还是我做错了?

您需要使用辅助函数和临时函数。

--- test.d  2015-04-11 12:03:54.257670300 +0000
+++ test2.d 2015-04-11 12:03:59.433170300 +0000
@@ -1,3 +1,4 @@
+import std.exception;
 import std.stdio;

 immutable class Definition {
@@ -14,11 +15,13 @@
     this(string name, int size) {
         this.name = name;
         this.size = size;
+        immutable(Field)[string] fields;
         foreach (i; 0..size) {
             string key = [cast(char)('a' + i)]; // a, b, c...
             auto field = new immutable(Field)(i);
-            fields[key] = field; // ERROR
+            add(fields, key, field);
         }
+        this.fields = fields.assumeUnique();
     }
 }
 class Instance {
@@ -38,3 +41,9 @@
    instance.def = cast(Definition) defB;
    instance.speak();
 }
+
+void add(K, V)(V[K] aa, K k, V v)
+{
+   assert(k !in aa);
+   cast()aa[k] = cast()v;
+}