在 D 中使用简单枚举器
Using simple enumerators in D
假设我有以下枚举:
struct Test {
string value;
}
Test new_test(string value) {
Test t;
t.value = value;
return t;
}
enum Foo : Test {
A = new_test("a"),
B = new_test("b"),
c = new_test("c"),
}
我对一些事情感到困惑。我如何将其传递给函数?
void do_something(Foo f) {
}
do_something(Foo.A);
// or
void do_something(Test t) {
}
do_something(Foo.A);
最后,有什么方法可以获取枚举的数值
例如
A -> 0
B -> 1
C -> 2
像这样简单的东西:
Foo.A.id ???
写的时候
enum Foo {
A = new_test("a"),
B = new_test("b"),
C = new_test("c"),
}
您基本上是在创建一组命名的值。它们没有数值,就像你想的那样 - 它们只是常规结构。如果您需要知道集合中某个值的索引(例如 getIndex(Foo.C)
将 return 2),您可以使用此代码:
// Gets the index of an enum value in the enum it's part of.
int getIndex(T)(T value) if (is(T == enum)) {
// Iterate over all the members of the enum, and return the index if it's a match.
static foreach (i, member; __traits(allMembers, T)) {
if (value == __traits(getMember, T, member))
return i;
}
return -1;
}
至于传递它,任何一种方式都可以,正如您可能已经注意到的那样。同样,枚举没有什么神奇之处。它们不是伪装成 Test
的数字,可以像 Test
一样以各种方式使用。
我不知道你为什么在这里将 Foo
定义为 Test
,你可以只使用一个匿名枚举,例如:
enum Foo {
a,
b,
c,
}
或将其定义为字符串:
enum Foo {
A="a",
B="b",
C="c",
}
无论如何,这取决于你的功能设计,如果功能应该只接收 Foo
那么你应该传递一个 Foo
并且与 Test
相同,如果您正在编写的函数应该适用于所有 Test
对象,而不仅仅是这 3 个预定义的 Test
,然后传递 Test
将是您的选择,但是,如果您希望该函数仅适用于您定义的枚举然后使用 Foo
,您明白了。
关于 id,假设您可以让 Test
包含另一个名为 id
的字段,并使用数字对其进行初始化,现在您可以将该字段用作标识符:
struct Test {
string value;
int id;
}
Test new_test(string value, int id) {
Test t;
t.value = value;
t.id = id;
return t;
}
enum Foo : Test {
A = new_test("a", 1),
B = new_test("b", 2),
c = new_test("c", 3),
}
现在如果你想获得一个 Foo
的索引,你可以使用 traits:
auto i = [__traits(allMembers, Foo)].countUntil(Foo.B.to!string);
假设我有以下枚举:
struct Test {
string value;
}
Test new_test(string value) {
Test t;
t.value = value;
return t;
}
enum Foo : Test {
A = new_test("a"),
B = new_test("b"),
c = new_test("c"),
}
我对一些事情感到困惑。我如何将其传递给函数?
void do_something(Foo f) {
}
do_something(Foo.A);
// or
void do_something(Test t) {
}
do_something(Foo.A);
最后,有什么方法可以获取枚举的数值 例如
A -> 0
B -> 1
C -> 2
像这样简单的东西:
Foo.A.id ???
写的时候
enum Foo {
A = new_test("a"),
B = new_test("b"),
C = new_test("c"),
}
您基本上是在创建一组命名的值。它们没有数值,就像你想的那样 - 它们只是常规结构。如果您需要知道集合中某个值的索引(例如 getIndex(Foo.C)
将 return 2),您可以使用此代码:
// Gets the index of an enum value in the enum it's part of.
int getIndex(T)(T value) if (is(T == enum)) {
// Iterate over all the members of the enum, and return the index if it's a match.
static foreach (i, member; __traits(allMembers, T)) {
if (value == __traits(getMember, T, member))
return i;
}
return -1;
}
至于传递它,任何一种方式都可以,正如您可能已经注意到的那样。同样,枚举没有什么神奇之处。它们不是伪装成 Test
的数字,可以像 Test
一样以各种方式使用。
我不知道你为什么在这里将 Foo
定义为 Test
,你可以只使用一个匿名枚举,例如:
enum Foo {
a,
b,
c,
}
或将其定义为字符串:
enum Foo {
A="a",
B="b",
C="c",
}
无论如何,这取决于你的功能设计,如果功能应该只接收 Foo
那么你应该传递一个 Foo
并且与 Test
相同,如果您正在编写的函数应该适用于所有 Test
对象,而不仅仅是这 3 个预定义的 Test
,然后传递 Test
将是您的选择,但是,如果您希望该函数仅适用于您定义的枚举然后使用 Foo
,您明白了。
关于 id,假设您可以让 Test
包含另一个名为 id
的字段,并使用数字对其进行初始化,现在您可以将该字段用作标识符:
struct Test {
string value;
int id;
}
Test new_test(string value, int id) {
Test t;
t.value = value;
t.id = id;
return t;
}
enum Foo : Test {
A = new_test("a", 1),
B = new_test("b", 2),
c = new_test("c", 3),
}
现在如果你想获得一个 Foo
的索引,你可以使用 traits:
auto i = [__traits(allMembers, Foo)].countUntil(Foo.B.to!string);