forked from dlang/dlang.org
-
Notifications
You must be signed in to change notification settings - Fork 4
/
declaration.dd
666 lines (537 loc) · 17.4 KB
/
declaration.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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
Ddoc
$(SPEC_S 宣言,
$(GRAMMAR
$(V1 $(GNAME Declaration):
$(GLINK TypedefDeclaration)
$(GLINK AliasDeclaration)
$(GLINK Decl)
$(GNAME TypedefDeclaration):
$(B typedef) $(GLINK Decl)
$(GNAME AliasDeclaration):
$(B alias) $(GLINK Decl)
)$(V2 $(GNAME Declaration):
$(GLINK AliasDeclaration)
$(GLINK AliasThisDeclaration)
$(GLINK Decl)
$(GNAME AliasDeclaration):
$(B alias) $(GLINK BasicType) $(GLINK Declarator)
$(GNAME AliasThisDeclaration):
$(B alias) $(I Identifier) $(B this)
)
$(GNAME Decl):
$(GLINK StorageClasses) $(I Decl)
$(GLINK BasicType) $(GLINK Declarators) $(B ;)
$(GLINK BasicType) $(GLINK Declarator) $(GLINK2 function, FunctionBody)
$(GLINK AutoDeclaration)
$(GNAME Declarators):
$(I DeclaratorInitializer)
$(I DeclaratorInitializer) $(B ,) $(GLINK DeclaratorIdentifierList)
$(GNAME DeclaratorInitializer):
$(GLINK Declarator)
$(GLINK Declarator) $(B =) $(GLINK Initializer)
$(GNAME DeclaratorIdentifierList):
$(GLINK DeclaratorIdentifier)
$(GLINK DeclaratorIdentifier) $(B ,) $(I DeclaratorIdentifierList)
$(GNAME DeclaratorIdentifier):
$(I Identifier)
$(I Identifier) $(B =) $(GLINK Initializer)
$(GNAME BasicType):
$(GLINK BasicTypeX)
$(B .)$(GLINK IdentifierList)
$(GLINK IdentifierList)
$(GLINK Typeof)
$(GLINK Typeof) $(B .) $(GLINK IdentifierList)
$(V2 $(B const$(LPAREN)) $(GLINK Type) $(B $(RPAREN))
$(B immutable$(LPAREN)) $(GLINK Type) $(B $(RPAREN))
$(B shared$(LPAREN)) $(GLINK Type) $(B $(RPAREN))
$(B inout$(LPAREN)) $(GLINK Type) $(B $(RPAREN))
)
$(GNAME BasicTypeX):
$(B bool)
$(B byte)
$(B ubyte)
$(B short)
$(B ushort)
$(B int)
$(B uint)
$(B long)
$(B ulong)
$(B char)
$(B wchar)
$(B dchar)
$(B float)
$(B double)
$(B real)
$(B ifloat)
$(B idouble)
$(B ireal)
$(B cfloat)
$(B cdouble)
$(B creal)
$(B void)
$(GNAME BasicType2):
$(B *)
$(B [ ])
$(B [) $(VEXPRESSION) $(B ])
$(B [) $(VEXPRESSION) .. $(VEXPRESSION) $(B ])
$(B [) $(GLINK Type) $(B ])
$(B delegate) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT))
$(B function) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT))
$(GNAME Declarator):
$(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT)
$(GLINK BasicType2)$(OPT) $(I Identifier) $(GLINK DeclaratorSuffixes)$(OPT)
$(GNAME DeclaratorSuffixes):
$(GLINK DeclaratorSuffix)
$(GLINK DeclaratorSuffix) $(I DeclaratorSuffixes)
$(GNAME DeclaratorSuffix):
$(B [ ])
$(B [) $(VEXPRESSION) $(B ])
$(B [) $(GLINK Type) $(B ])
$(GLINK2 template, TemplateParameterList)$(OPT) $(GLINK Parameters) $(V2 $(GLINK MemberFunctionAttributes)$(OPT) $(GLINK2 template, Constraint)$(OPT))
$(GNAME IdentifierList):
$(I Identifier)
$(I Identifier) $(B .) $(I IdentifierList)
$(GLINK2 template, TemplateInstance)
$(GLINK2 template, TemplateInstance) $(B .) $(I IdentifierList)
$(GNAME StorageClasses):
$(GLINK StorageClass)
$(GLINK StorageClass) $(I StorageClasses)
$(GNAME StorageClass):
$(B abstract)
$(B auto)
$(B const)
$(B deprecated)
$(V2 $(B enum)
) $(B extern)
$(B final)
$(V2 $(B immutable)
$(B inout)
$(B shared)
$(B nothrow)
$(B override)
$(B pure)
$(B __gshared)
$(GLINK Property)
) $(B scope)
$(B static)
$(B synchronized)
$(V2
$(GNAME Property):
$(B @) $(GLINK PropertyIdentifier)
$(GNAME PropertyIdentifier):
$(B property)
$(B safe)
$(B trusted)
$(B system)
$(B disable)
)
$(GNAME Type):
$(GLINK BasicType)
$(GLINK BasicType) $(GLINK Declarator2)
$(GNAME Declarator2):
$(GLINK BasicType2)$(OPT) $(GLINK DeclaratorSuffixes)$(OPT)
$(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator2) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT)
$(GNAME Parameters):
$(B $(LPAREN)) $(GLINK ParameterList) $(B $(RPAREN))
$(B ( ))
$(GNAME ParameterList):
$(GLINK Parameter)
$(GLINK Parameter) $(B ,) $(I ParameterList)
$(B ...)
$(GNAME Parameter):
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator)
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) $(B ...)
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) = $(GLINK DefaultInitializerExpression)
$(I InOut)$(OPT) $(GLINK Type)
$(I InOut)$(OPT) $(GLINK Type) $(B ...)
$(GNAME InOut):
$(I InOutX)
$(I InOut InOutX)
$(GNAME InOutX):
$(B auto)
$(B const)
$(B final)
$(V2 $(B immutable)
) $(B in)
$(B inout)
$(B lazy)
$(B out)
$(B ref)
$(B scope)
$(V2
$(B shared)
)
$(V2
$(GNAME FunctionAttributes):
$(GLINK FunctionAttribute)
$(GLINK FunctionAttribute) $(I FunctionAttributes)
$(GNAME FunctionAttribute):
$(B nothrow)
$(B pure)
$(GLINK Property)
$(GNAME MemberFunctionAttributes):
$(GLINK MemberFunctionAttribute)
$(GLINK MemberFunctionAttribute) $(I MemberFunctionAttributes)
$(GNAME MemberFunctionAttribute):
$(B const)
$(B immutable)
$(B inout)
$(B shared)
$(GLINK FunctionAttribute)
)
$(GNAME DefaultInitializerExpression):
$(ASSIGNEXPRESSION)
$(V2 $(B __FILE__)
$(B __LINE__))
$(GNAME Initializer):
$(GLINK VoidInitializer)
$(GLINK NonVoidInitializer)
$(GNAME NonVoidInitializer):
$(ASSIGNEXPRESSION)
$(GLINK ArrayInitializer)
$(GLINK StructInitializer)
$(GNAME ArrayInitializer):
$(B [ ])
$(B [) $(GLINK ArrayMemberInitializations) $(B ])
$(GNAME ArrayMemberInitializations):
$(GLINK ArrayMemberInitialization)
$(GLINK ArrayMemberInitialization) $(B ,)
$(GLINK ArrayMemberInitialization) $(B ,) $(I ArrayMemberInitializations)
$(GNAME ArrayMemberInitialization):
$(GLINK NonVoidInitializer)
$(ASSIGNEXPRESSION) $(B :) $(GLINK NonVoidInitializer)
$(GNAME StructInitializer):
$(B { })
$(B {) $(GLINK StructMemberInitializers) $(B })
$(GNAME StructMemberInitializers):
$(GLINK StructMemberInitializer)
$(GLINK StructMemberInitializer) $(B ,)
$(GLINK StructMemberInitializer) $(B ,) $(I StructMemberInitializers)
$(GNAME StructMemberInitializer):
$(GLINK NonVoidInitializer)
$(I Identifier) $(B :) $(GLINK NonVoidInitializer)
)
<h3>宣言の構文</h3>
$(P 宣言の構文は、基本的に左から右へと読むことができます:)
--------------------
int x; // x は int
int* x; // x は int へのポインタ
int** x; // x は int へのポインタ へのポインタ
int[] x; // x は int の配列
int*[] x; // x は int へのポインタ の配列
int[]* x; // x は int の配列 へのポインタ
--------------------
$(P 配列も、左から右へ読みます:)
--------------------
int[3] x; // xは int の3要素配列
int[3][5] x; // xは int の3要素配列 の5要素配列
int[3]*[5] x; // xは int の3要素配列 へのポインタ の5要素配列
--------------------
$(P
関数へのポインタは $(B function) キーワードを使って宣言します:
)
--------------------
int $(B function)(char) x; // x はcharを引数としてintを返す関数
// へのポインタ
int $(B function)(char)[] x; // x はcharを引数としてintを返す関数
// へのポインタ の配列
--------------------
$(P
$(V1 C風の宣言構文も使用可能です:)
$(V2 C風の宣言構文は非推奨となっています:)
)
--------------------
int x[3]; // x は int の3要素配列
int x[3][5]; // x は int の5要素配列 の3要素配列
int (*x[5])[3]; // x は int の3要素配列 へのポインタ の5要素配列
int (*x)(char); // x はcharを引数としてintを返す関数
// へのポインタ
int (*[] x)(char); // x はcharを引数としてintを返す関数
// へのポインタ の配列
--------------------
$(P
一行で複数のシンボルを宣言をする時は、
全ての変数が同じ型でなくてはなりません:
)
--------------------
int x,y; // x と y は int
int* x,y; // x と y は intへのポインタ
int x,*y; // エラー, 2種類の型
int[] x,y; // x と y は intの配列
int x[],y; // エラー, 2種類の型
--------------------
<h3><a name="AutoDeclaration">暗黙の型推論</a></h3>
$(GRAMMAR
$(GNAME AutoDeclaration):
$(GLINK StorageClasses) $(I AutoDeclarationX) $(B ;)
$(GNAME AutoDeclarationX):
$(I Identifier) $(B =) $(GLINK Initializer)
$(I AutoDeclarationX) $(B ,) $(I Identifier) $(B =) $(GLINK Initializer)
)
$(P 宣言が $(I StorageClass) で始まって、
型のわかる $(I NonVoidInitializer) が指定されているとき、
宣言の型は省略することが可能です。
)
----------
static x = 3; // x はint型
auto y = 4u; // y はuint型
$(V1 auto s = "string"; // s はchar[6]型)
$(V2 auto s = "string"; // s はimmutable(char)[]型)
class C { ... }
auto c = new C(); // c はクラスCのインスタンスへのハンドル
----------
$(P $(I NonVoidInitializer) に前方参照を含むことはできません
(この制限は将来的に取り除かれる予定です)。
暗黙に推論される型は、
実行時ではなくコンパイル時に静的に決まります。
)
$(V2
$(P $(GLINK2 expression, ArrayLiteral)
の型は、
静的配列ではなく動的配列と推論されます:)
---
auto v = ["hello", "world"]; // 型は string[]。 string[2] ではない
---
)
$(V1
<h3><a name="typedef">型の定義</a></h3>
$(P
typedef によって、「強い型」を導入できます。強い型とは、型システムによって、
関数オーバーロードやデバッガに対して、オリジナルの型と厳密に区別される型です。
)
--------------------
typedef int myint;
void foo(int x) { . }
void foo(myint m) { . }
.
myint b;
foo(b); // foo(myint) が呼ばれる
--------------------
元の型とは違う初期値を
typedef で指定することができます:
--------------------
typedef int myint = 7;
myint m; // 7 に初期化される
--------------------
)
<h3><a name="alias">型の別名</a></h3>
$(P
$(GLINK AliasDeclaration) は他の型の別名となるシンボルを作り、
その型の代わりとしてどんな場所でも使えるようにします。
)
--------------------
$(B alias) abc.Foo.bar myint;
--------------------
$(P
別名となっている型は、意味論的には元の型と全く同一に扱われます。
デバッガは二つの型を区別しませんし、関数オーバーロードの際も、
違いは生じません。例として:
)
--------------------
$(B alias) int myint;
void foo(int x) { . }
void foo(myint m) { . } // ラー。同じ関数fooが二回以上定義されている
--------------------
$(V1
$(P
型の別名は C の typedef と同等の機能です。
)
)
<h3>別名宣言</h3>
$(P
型だけでなく、任意のシンボルに対する $(I alias) を宣言できます。
例:
)
--------------------
import string;
$(B alias) string.strlen mylen;
...
int len = mylen("hello"); // 実際には string.strlen() が呼ばれる
--------------------
$(P
次のような別名宣言が全て有効です:
)
--------------------
template Foo2(T) { $(B alias) T t; }
$(B alias) Foo2!(int) t1;
$(B alias) Foo2!(int).t t2;
$(B alias) t1.t t3;
$(B alias) t2 t4;
t1.t v1; // v1 はint型
t2 v2; // v2 はint型
t3 v3; // v3 はint型
t4 v4; // v4 はint型
--------------------
$(P
シンボルの別名は、
長く修飾された名前を省略したり、
シンボルから別のシンボルへ転送する方法として役に立ちます:
)
--------------------
version (Win32)
{
$(B alias) win32.foo myfoo;
}
version (linux)
{
$(B alias) linux.bar myfoo;
}
--------------------
$(P
シンボルを現在のスコープへ $(SINGLEQUOTE import) するのに alias
を利用できます:
)
--------------------
$(B alias) string.strlen strlen;
--------------------
$(P
alias によってオーバーロードされた関数達をまとめて $(SINGLEQUOTE import) することも可能で、
その際には、新しく導入される関数は、現在のスコープに存在した関数とさらにオーバーロードされます:
)
--------------------
class A {
int foo(int a) { return 1; }
}
class B : A {
int foo( int a, uint b ) { return 2; }
}
class C : B {
int foo( int a ) { return 3; }
$(B alias) B.foo foo;
}
class D : C {
}
void test()
{
D b = new D();
int i;
i = b.foo(1, 2u); // B.foo が呼ばれる
i = b.foo(1); // C.foo が呼ばれる
}
--------------------
$(P
$(B 注:) 型のaliasは、見かけだけではシンボルの alias
宣言と区別できないことがあります:
)
--------------------
$(B alias) foo.bar abc; // 型? シンボル?
--------------------
$(P
この区別は意味解析のフェーズで行われます。
)
$(P aliasを式に対して使うことはできません:)
-----------
struct S { static int i; }
S s;
alias s.i a; // 不正。s.i は式
alias S.i b; // ok
b = 4; // S.i を 4 にする
-----------
<h3><a name="extern">extern 宣言</a></h3>
記憶域クラス $(B extern) つきで宣言された変数の領域は、
モジュール内には確保されません。
同じ名前で変数を定義した別のオブジェクトファイルを
リンクする必要があります。
この機能の使いどころは、
C言語のグローバル変数宣言の利用です。
<h3><a name="typeof">typeof</a></h3>
$(GRAMMAR
$(GNAME Typeof):
$(B typeof $(LPAREN)) $(EXPRESSION) $(B $(RPAREN))
$(V2
$(B typeof $(LPAREN)) $(B return) $(B $(RPAREN))
)
)
$(P
$(I Typeof) は、式の型に基づいて型を指定する方法です。
例えば:
)
--------------------
void func(int i) {
$(B typeof)(i) j; // j の型はint
$(B typeof)(3 + 6.0) x; // x の型はdouble
$(B typeof)(1)* p; // p の型はintへのポインタ
int[$(B typeof)(p)] a; // a の型はint[int*]
writefln("%d", $(B typeof)('c').sizeof); // 1を表示
double c = cast($(B typeof)(1.0))j; // jをdoubleへキャスト
}
--------------------
$(P
$(I Expression) は評価されず、
その型情報のみが生成されます:
)
--------------------
void func() {
int i = 1;
$(B typeof)(++i) j; // j はintと宣言される。iは増加しない。
writefln("%d", i); // 1と表示
}
--------------------
$(P $(V1 二つ)$(V2 三つ)ほど、特別な場合があります: )
$(OL
$(LI $(B typeof(this)) は、例えメンバ関数の外であっても、
非静的メンバ関数の中で $(B this)
が指すはずの型になることがあります。
)
$(LI 同様に、$(B typeof(super)) は非静的メンバ関数の中で
$(B super) が指すであろう型になることがあります。
)
$(V2
$(LI $(B typeof(return)) は、関数の中では、
その関数の返値の型になります。
)
)
)
--------------------
class A { }
class B : A {
$(B typeof(this)) x; // x は B と宣言される
$(B typeof(super)) y; // y は A と宣言される
}
struct C {
$(B typeof(this)) z; // z は C* と宣言される
$(B typeof(super)) q; // エラー。構造体 C には super がない
}
$(B typeof(this)) r; // エラー。構造体やクラス宣言の内部でない
--------------------
$(P
$(I Typeof) がもっとも有効なのは、
templateを使ったジェネリックなコードを書く時です。
)
<h3>void 初期化子</h3>
$(GRAMMAR
$(GNAME VoidInitializer):
$(B void)
)
$(P 通常、変数は明示的な
$(I Initializer) で初期化されるか、
その型のデフォルトの値がセットされます。しかし $(I Initializer) が $(B void) であった場合に限り、
変数は初期化されません。そのような変数が
値をセットされる前に使用されると、未定義動作を引き起こすことがあります。
)
-------------------------
void foo() {
int x = void;
writefln(x); // 意味のない値を表示
}
-------------------------
$(P ですから、$(B void)
初期化子は速度が最優先のコードを最適化する最後の手段としておくべきです。
)
<h3>グローバル初期化子と静的初期化子</h3>
$(P グローバル変数と静的変数の $(GLINK Initializer) は、
コンパイル時評価が可能でなければなりません。
ポインタが他の関数やデータのアドレスで初期化できるかどうかは、
実装定義です。
実行時初期化は静的コンストラクタを使って行ってください。
)
)
Macros:
TITLE=宣言
WIKI=Declaration
CATEGORY_SPEC=$0
OPT=<sub>opt</sub>
ASSIGNEXPRESSION=$(GLINK2 expression, AssignExpression)
EXPRESSION=$(GLINK2 expression, Expression)
VEXPRESSION=$(V1 $(EXPRESSION))$(V2 $(ASSIGNEXPRESSION))
FOO=