在我的D程序中,我有一个固定长度的只读数组,我希望通过枚举类型对数组进行索引。
如果我做了这样的事
static const my_struct_t aray[ my_enum_t ] = ... whatever ...;
my_enum_t index;
result = aray[ index ];然后,GDC生成的代码是巨大的,当数组被索引时,会充满对运行时的调用。因此,看起来要么将数组视为可变长度,要么将其视为关联数组(哈希表)或其他什么,而不是一个简单索引的固定长度的轻量级C型数组。因为枚举有固定的基数,不能增长,而且我有一个有限的稀疏值范围(我没有滥用关键字enum来定义大量随机常量),所以我不知道为什么会出现这种情况。
我通过将行改为
static const my_struct_t aray[ my_enum_t.max + 1 ]据我理解,这意味着方括号中的值只是一个已知的积分型常数。由于索引现在根本不是枚举,所以现在有一个由整数索引的数组,因此我已经丢失了类型检查,所以可以使用任意随机整数类型变量对其进行索引,而不是确保只使用正确的(强)类型。
我该怎么做?
在更一般的情况下,(愚蠢的例子)
static const value_t aray[ bool ] = blah例如,我的索引类型在语义上是完全合理的,但不只是一个无类型的size_t/int/uint --我假设我会遇到同样的问题。
我不想说这是一个编译器设计问题。这肯定是次优行为的一个例子。但是公平地说,对于编译器来说,究竟是要告诉它数组是固定长度还是变量,还是稀疏还是密集?我想要两件事:索引类型检查和非变量长度。实际上,在这个特定的情况下,数组是const (我也可以将它放在不可变的位置),所以它显然不可能是可变长度。但是,对于具有可修改内容但长度固定的数组,您需要能够声明它是固定长度的。
发布于 2017-02-27 00:54:32
V[K] name是关联数组的语法,它确实执行运行时调用等操作,即使类型仅限于少量的值(如bool或枚举)。编译器可能会对其进行优化,使其作为一个简单的固定长度数组来实现,从而使它对程序的作用就像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);或者,当然,您不需要使它是静态的,您也可以执行一个常规的实例,并初始化内部的内容等等。
发布于 2017-02-27 00:55:50
在D中,静态数组和动态数组都由size_t索引,就像在C和C++中一样。你不能像在C或C++中那样改变D中索引的类型。因此,在D中,如果在数组声明的括号之间放置类型,则定义关联数组,而不是静态数组。如果您想要一个静态数组,您必须提供一个整数文本或编译时常量,并且没有办法要求一个裸露的静态数组被具有基本类型size_t或隐式转换为size_t的枚举类型索引。
如果要要求静态数组由size_t以外的类型索引,则需要将其包装在结构或类中,并通过成员函数控制对静态数组的访问。您可以重载opIndex以获取枚举类型,并将您的结构类型视为静态数组。因此,效果应该是您试图将枚举类型放入静态数组声明中的效果,但是它将是接受枚举值并使用它调用静态数组的成员函数,而不是对静态数组本身做任何事情。
https://stackoverflow.com/questions/42476071
复制相似问题