d直阵数量由枚举索引



在我的D程序中,我有一个只读的固定长度,我希望通过枚举类型为数组索引。

如果我做

之类的事情
static const my_struct_t aray[ my_enum_t ] = ... whatever ...;
my_enum_t index;
result = aray[ index ];

然后,GDC产生的代码是巨大的,当索引阵列时,通话时间为运行时。因此看起来好像阵列被视为可变长度,也可以将其视为关联阵列(哈希表)之类的东西,无论如何,远离固定长度的轻巧的C风格阵列都远不及直接索引。由于枚举具有固定的基数且无法增长,而且我的值范围很小(我不是滥用关键字枚举只是为了定义了随机常数的负载),所以我不知道为什么会发生这种情况。/p>

我通过将行更改为

来解决问题
static const my_struct_t aray[ my_enum_t.max + 1 ]

据我了解,这意味着方括号中的值只是已知的积分类型的常数。由于该索引现在根本不是枚举,因此我现在有一个由整数索引的数组,因此我丢失了类型检查,我可以用任何随机整数键入变量索引,而不是确保只有正确的(强)类型是

我应该做什么?

在更一般的情况下(愚蠢的示例)

static const value_t aray[ bool ] = blah

例如,我的索引类型在语义上是完全明智的,但不仅仅是一个少于size_t/int/uint,我认为我会遇到同样的问题。

我不想说这是一个编译器设计问题。这无疑是次优行为的情况。但是,要公平地对编译器公平,该数组是固定长度还是可变,稀疏或密集的确切地说是什么?我想要两件事;类型检查索引和不可变化的长度。实际上,在这种特殊情况下,数组是const(我也可以放置不变的),因此显然不能以任何方式变化。但是,对于一个具有可修改内容但长度固定的数组,您需要能够声明其固定长度。

V[K] name是关联数组的语法,即使类型仅限于少数值(例如 bool或enum),它确实确实会进行运行时调用。编译器可能可以优化它,使其像AA一样以AA的形式作用,同时将其作为简单的固定长度阵列实现,但事实并非如此;它将所有关键类型都相同。

我建议您开始使用您的开始:T[enum.max + 1],但是如果您想强制键入安全性,然后执行包装器。如果您只想要一个实例,则可以使索引过载静态载荷:

enum Foo {
        one,
        two
}
struct struct_t {}
struct array {
        static private struct_t[Foo.max + 1] content;
        static struct_t opIndex(Foo idx) { return content[cast(int) idx]; }     
}
void main() {
        struct_t a = array[Foo.one];
}

那么,如果您想要更简单的重复使用,就可以通用。

struct enum_array(Key, Value) {
        static private struct_t[Key.max + 1] content;
        static Value opIndex(Key idx) { return content[cast(int) idx]; }
}
alias array = enum_array!(Foo, struct_t);

当然,您不需要使其静态,您也可以执行常规实例,并初始化内部内容。

在d中,静态和动态数组均由 size_t索引,就像它们在C和C 中一样。而且,您不能比在C或C 中更改D中的索引类型。因此,在D中,如果您在数组声明中的括号之间放置类型,则您将定义关联数组而不是静态数组。如果您想要一个静态数组,则必须提供整数字面或编译时常数,并且没有办法要求由具有size_t的基本类型或隐式类型的枚举类型索引一个裸露的静态数组转换为size_t

如果要要求除了size_t以外的其他类型索引静态数组,则需要将其包装在结构或类中,并通过成员函数控制对静态数组的访问。您可以超载 opIndex来采用枚举类型并将结构类型对待,就像它是静态数组一样。因此,效果应该有效地是您尝试将枚举类型放入静态数组声明中的作用,但是将成员函数占据了枚举值并将其称为静态数组,而不是对此做任何事情静态数组本身。

最新更新