D lang enum具有基本类型令人惊讶的行为

时间:2016-02-11 09:01:27

标签: enums d

我正在涉及D,并且对具有指定基类型的命名vs匿名枚举的行为感到惊讶。给出以下D代码:

import std.stdio;

enum strs : string 
{
    Foo = "Hello", 
    Bar = "World",
}

enum : string 
{
    anon1 = "pen", 
    anon2 = "sword",
}

int main(string[] args)
{
    writefln("%s %s", strs.Foo, strs.Bar);
    writefln("%s %s", anon1, anon2);

    return 0;
}

输出:

Foo Bar
pen sword

换句话说,对于命名的枚举,将值传递给writefln作为字符串会打印值的名称,而不是值本身。但对于匿名枚举,做同样的事情会打印出值本身。

这似乎是一种奇怪的不一致。那么为什么呢?

我使用的是Visual D 0.3.42。

2 个答案:

答案 0 :(得分:3)

无名枚举只是一个清单常量块,并没有自己的类型。含义:

enum : string 
{
    anon1 = "pen", 
    anon2 = "sword",
}

...与...相同

enum string anon1 = "pen";
enum string anon2 = "sword";

但是,您的strs枚举是一种类型,因此writefln会打印出枚举字段名称(无论多么奇怪)。

答案 1 :(得分:3)

好吧,问题的一部分是关键字enum在D中被过度使用。匿名枚举有时被称为清单常量。声明

enum : string 
{
    anon1 = "pen", 
    anon2 = "sword",
}

基本相同
enum string anon1 = "pen";
enum string anon2 = "sword";

enum anon1 = "pen";
enum anon2 = "sword";

因为他们无论如何都会被推断为string。这些真的不是枚举。只是你在块中而不是单独声明它们。他们更像是在C中定义一个常量,因为你声明了一个没有地址的符号,并且只会被替换为在使用该符号的地方分配的值。它不是enum通常应该是的关联值列表。事实上,这些断言将会失败:

assert(is(typeof(anon1) == enum));
assert(is(typeof(anon2) == enum));

那是因为它们表现出传统意义上的常数而不是真正的枚举。与

对比
assert(is(typeof(strs.Foo) == enum));
assert(is(typeof(strs.Bar) == enum));

会传递 - 因为strs是一个实际的enum而不是一个清单常量(虽然枚举类似于显式常量,因为它们没有地址,当你使用它们时,它们只会得到它们替换为它们的值 - 这可能是清单常量也使用enum关键字的原因的一部分。)

因此,从writefln的角度来看,anon1anon2只是字符串,它会像任何字符串一样打印它们,而{{1 }和Foo是枚举,因此它会打印出他们的名字。在内部,Bar正在使用writefln检查某些内容是否为is(T == enum),就像这些断言一样,只有实际枚举而不是显式常量才会导致该表达式为是的,所以他们是那些打印出他们名字的人。