2016-02-11 3 views
2

Я занимаюсь D, и был удивлен поведением названных vs анонимных перечислений с заданным базовым типом. Учитывая следующий код D:D lang enum с basetype удивительное поведение

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.

ответ

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 «s, anon1 и anon2 это просто строки, и он будет печатать их, как и любую строку, в то время как Foo и Bar являются перечисления, и поэтому он будет печатать их имена.Внутренне, writefln использует is(T == enum), чтобы проверить, является ли что-то enum, и точно так же, как и с этими утверждениями, только те, которые являются фактическими перечислениями, а не манифестными константами, приведут к тому, что это выражение будет истинным, так что это те, которые получают их имена распечатаны.

3

Безымянные перечисления - это просто блок констант манифеста и не имеют собственного типа. Значение:

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

... так же, как ...

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

Однако ваше strs перечисления является типом его собственного, так writefln выводит имена перечислений поля (однако странно, что может быть).

Смежные вопросы