forked from dlang/dlang.org
-
Notifications
You must be signed in to change notification settings - Fork 0
/
enum.dd
270 lines (208 loc) · 6.55 KB
/
enum.dd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
Ddoc
$(SPEC_S Enums,
$(GRAMMAR
$(GNAME EnumDeclaration):
$(D enum) $(I Identifier) $(GLINK EnumBody)
$(D enum) $(I Identifier) $(D :) $(GLINK EnumBaseType) $(GLINK EnumBody)
$(GLINK AnonymousEnumDeclaration)
$(GNAME EnumBaseType):
$(GLINK2 declaration, Type)
$(GNAME EnumBody):
$(D {) $(GLINK EnumMembers) $(D })
$(D ;)
$(GNAME EnumMembers):
$(GLINK EnumMember)
$(GLINK EnumMember) $(D ,)
$(GLINK EnumMember) $(D ,) $(GLINK EnumMembers)
$(GNAME EnumMember):
$(I Identifier)
$(I Identifier) $(D =) $(ASSIGNEXPRESSION)
$(GNAME AnonymousEnumDeclaration):
$(D enum) $(D :) $(GLINK EnumBaseType) $(D {) $(GLINK EnumMembers) $(D })
$(D enum) $(D {) $(GLINK EnumMembers) $(D })
$(D enum) $(D {) $(GLINK AnonymousEnumMembers) $(D })
$(GNAME AnonymousEnumMembers):
$(GLINK AnonymousEnumMember)
$(GLINK AnonymousEnumMember) $(D ,)
$(GLINK AnonymousEnumMember) $(D ,) $(GLINK AnonymousEnumMembers)
$(GNAME AnonymousEnumMember):
$(GLINK EnumMember)
$(GLINK2 declaration, Type) $(I Identifier) $(D =) $(ASSIGNEXPRESSION)
)
$(P Enum declarations are used to define a group of constants.
They come in these forms:
)
$(OL
$(LI Named enums, which have a name.)
$(LI Anonymous enums, which do not have a name.)
$(LI Manifest constants.)
)
$(H2 Named Enums)
$(P
Named enums are used to declare related
constants and group them by giving them a unique type.
The $(I EnumMembers) are declared in the scope of the named enum. The named
enum declares a new type, and all the $(I EnumMembers) have that type.
)
$(P This defines a new type $(CODE X) which has values
$(CODE X.A=0), $(CODE X.B=1), $(CODE X.C=2):)
------
enum X { A, B, C } // named enum
------
$(P If the $(I EnumBaseType) is not explicitly set, and the first
$(I EnumMember) has an $(ASSIGNEXPRESSION), it is set to the type of that
$(ASSIGNEXPRESSION). Otherwise, it defaults to
type $(CODE int).)
$(P Named enum members may not have individual $(I Type)s.
)
$(P A named enum member can be implicitly cast to its $(I EnumBaseType),
but $(I EnumBaseType) types
cannot be implicitly cast to an enum type.
)
$(P The value of an $(I EnumMember) is given by its $(ASSIGNEXPRESSION).
If there is no $(ASSIGNEXPRESSION) and it is the first $(I EnumMember),
its value is $(CODE $(GLINK EnumBaseType).init).
)
$(P If there is no $(ASSIGNEXPRESSION) and it is not the first $(I EnumMember),
it is given the value of the previous $(CODE $(I EnumMember)+1).
If the value of the previous $(I EnumMember) is $(CODE $(GLINK EnumBaseType).max),
it is an error.
If the value of the previous $(CODE $(I EnumMember)+1) is the same as the
value of the previous $(I EnumMember), it is an error. (This can happen
with floating point types.)
)
$(P All $(I EnumMember)s are in scope for the $(ASSIGNEXPRESSION)s.
)
---
enum A = 3;
enum B
{
A = A // error, circular reference
}
enum C
{
A = B, // A = 4
B = D, // B = 4
C = 3, // C = 3
D // D = 4
}
enum E : C
{
E1 = C.D,
E2 // error, C.D is C.max
}
---
$(P An empty enum body (For example $(CODE enum E;)) signifies an opaque
enum - the enum members are unknown.)
$(H3 Enum Default Initializer)
$(P The $(CODE .init) property of an enum type is the value
of the first member of that enum.
This is also the default initializer for the enum type.
)
------
enum X { A=3, B, C }
X x; // x is initialized to 3
------
$(H3 Enum Properties)
$(P Enum properties only exist for named enums.
)
$(TABLE
$(CAPTION Named Enum Properties)
$(TROW $(D .init), First enum member value)
$(TROW $(D .min), Smallest value of enum)
$(TROW $(D .max), Largest value of enum)
$(TROW $(D .sizeof), Size of storage for an enumerated value)
)
$(P For example:)
---
enum X { A=3, B, C }
X.min // is X.A
X.max // is X.C
X.sizeof // is same as int.sizeof
---
$(P The $(I EnumBaseType) of named enums must support comparison
in order to compute the $(CODE .max) and $(CODE .min) properties.
)
$(H2 Anonymous Enums)
$(P If the enum $(I Identifier) is not present, then the enum
is an $(I anonymous enum), and the $(I EnumMembers) are declared
in the scope the $(I EnumDeclaration) appears in.
No new type is created.
)
$(P The $(I EnumMembers) can have different types.
Those types are given by the first of:
)
$(OL
$(LI The $(I Type), if present. Types are not permitted when an
$(I EnumBaseType) is present.)
$(LI The $(I EnumBaseType), if present.)
$(LI The type of the $(I AssignExpression), if present.)
$(LI The type of the previous $(I EnumMember), if present.)
$(LI $(CODE int))
)
------
enum { A, B, C } // anonymous enum
------
$(P Defines the constants A=0, B=1, C=2, all of type int.)
$(P Enums must have at least one member.
)
$(P The value of an $(I EnumMember) is given by its $(ASSIGNEXPRESSION).
If there is no $(ASSIGNEXPRESSION) and it is the first $(I EnumMember),
its value is the $(CODE .init) property of the $(I EnumMember)'s type.
)
$(P If there is no $(ASSIGNEXPRESSION) and it is not the first $(I EnumMember),
it is given the value of the previous $(CODE $(I EnumMember)+1).
If the value of the previous $(I EnumMember) is the $(CODE .max) property
if the previous $(I EnumMember)'s type,
it is an error.
If the value of the previous $(CODE $(I EnumMember)+1) is the same as the
value of the previous $(I EnumMember), it is an error. (This can happen
with floating point types.)
)
$(P All $(I EnumMember)s are in scope for the $(ASSIGNEXPRESSION)s.
)
------
enum { A, B = 5+7, C, D = 8+C, E }
------
$(P Sets A=0, B=12, C=13, D=21, and E=22, all of type int.)
---
enum : long { A = 3, B }
---
$(P Sets A=3, B=4 all of type long.)
---
enum : string
{
A = "hello",
B = "betty",
C // error, cannot add 1 to "betty"
}
---
---
enum
{
A = 1.2f, // A is 1.2f of type float
B, // B is 2.2f of type float
int C = 3, // C is 3 of type int
D // D is 4 of type int
}
---
$(H2 Manifest Constants)
$(P If there is only one member of an anonymous enum, the { } can
be omitted. Gramatically speaking, this is an $(GLINK2 declaration, AutoDeclaration).
)
---
enum i = 4; // i is 4 of type int
enum long l = 3; // l is 3 of type long
---
$(P Such declarations are not lvalues, meaning their address
cannot be taken. They exist only in the memory of the compiler.)
---
enum size = __traits(classInstanceSize, Foo); // evaluated at compile-time
---
$(P Using manifest constants is an idiomatic D method
to force compile-time evaluation of an expression.)
)
Macros:
TITLE=Enums
WIKI=Enum
CATEGORY_SPEC=$0