| 1 |
Ddoc |
|---|
| 2 |
|
|---|
| 3 |
$(SPEC_S Declarations, |
|---|
| 4 |
|
|---|
| 5 |
$(GRAMMAR |
|---|
| 6 |
$(GNAME Declaration): |
|---|
| 7 |
$(V1 $(B typedef) $(I Decl) |
|---|
| 8 |
) $(B alias) $(I Decl) |
|---|
| 9 |
$(I Decl) |
|---|
| 10 |
|
|---|
| 11 |
$(GNAME Decl): |
|---|
| 12 |
$(GLINK StorageClasses) $(I Decl) |
|---|
| 13 |
$(GLINK BasicType) $(GLINK Declarators) $(B ;) |
|---|
| 14 |
$(GLINK BasicType) $(GLINK Declarator) $(LINK2 function.html#FunctionBody, $(I FunctionBody)) |
|---|
| 15 |
$(GLINK AutoDeclaration) |
|---|
| 16 |
|
|---|
| 17 |
$(GNAME Declarators): |
|---|
| 18 |
$(I DeclaratorInitializer) |
|---|
| 19 |
$(I DeclaratorInitializer) $(B ,) $(GLINK DeclaratorIdentifierList) |
|---|
| 20 |
|
|---|
| 21 |
$(GNAME DeclaratorInitializer): |
|---|
| 22 |
$(GLINK Declarator) |
|---|
| 23 |
$(GLINK Declarator) $(B =) $(GLINK Initializer) |
|---|
| 24 |
|
|---|
| 25 |
$(GNAME DeclaratorIdentifierList): |
|---|
| 26 |
$(GLINK DeclaratorIdentifier) |
|---|
| 27 |
$(GLINK DeclaratorIdentifier) $(B ,) $(I DeclaratorIdentifierList) |
|---|
| 28 |
|
|---|
| 29 |
$(GNAME DeclaratorIdentifier): |
|---|
| 30 |
$(I Identifier) |
|---|
| 31 |
$(I Identifier) $(B =) $(GLINK Initializer) |
|---|
| 32 |
|
|---|
| 33 |
$(GNAME BasicType): |
|---|
| 34 |
$(GLINK BasicTypeX) |
|---|
| 35 |
$(B .)$(GLINK IdentifierList) |
|---|
| 36 |
$(GLINK IdentifierList) |
|---|
| 37 |
$(GLINK Typeof) |
|---|
| 38 |
$(GLINK Typeof) $(B .) $(GLINK IdentifierList) |
|---|
| 39 |
$(V2 $(B const$(LPAREN)) $(GLINK type) $(B $(RPAREN)) |
|---|
| 40 |
$(B immutable$(LPAREN)) $(GLINK type) $(B $(RPAREN)) |
|---|
| 41 |
$(B shared$(LPAREN)) $(GLINK type) $(B $(RPAREN)) |
|---|
| 42 |
$(B inout$(LPAREN)) $(GLINK type) $(B $(RPAREN)) |
|---|
| 43 |
) |
|---|
| 44 |
|
|---|
| 45 |
$(GNAME BasicTypeX): |
|---|
| 46 |
$(B bool) |
|---|
| 47 |
$(B byte) |
|---|
| 48 |
$(B ubyte) |
|---|
| 49 |
$(B short) |
|---|
| 50 |
$(B ushort) |
|---|
| 51 |
$(B int) |
|---|
| 52 |
$(B uint) |
|---|
| 53 |
$(B long) |
|---|
| 54 |
$(B ulong) |
|---|
| 55 |
$(B char) |
|---|
| 56 |
$(B wchar) |
|---|
| 57 |
$(B dchar) |
|---|
| 58 |
$(B float) |
|---|
| 59 |
$(B double) |
|---|
| 60 |
$(B real) |
|---|
| 61 |
$(B ifloat) |
|---|
| 62 |
$(B idouble) |
|---|
| 63 |
$(B ireal) |
|---|
| 64 |
$(B cfloat) |
|---|
| 65 |
$(B cdouble) |
|---|
| 66 |
$(B creal) |
|---|
| 67 |
$(B void) |
|---|
| 68 |
|
|---|
| 69 |
$(GNAME BasicType2): |
|---|
| 70 |
$(B *) |
|---|
| 71 |
$(B [ ]) |
|---|
| 72 |
$(B [) $(VEXPRESSION) $(B ]) |
|---|
| 73 |
$(B [) $(VEXPRESSION) .. $(VEXPRESSION) $(B ]) |
|---|
| 74 |
$(B [) $(GLINK Type) $(B ]) |
|---|
| 75 |
$(B delegate) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT)) |
|---|
| 76 |
$(B function) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT)) |
|---|
| 77 |
|
|---|
| 78 |
$(GNAME Declarator): |
|---|
| 79 |
$(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT) |
|---|
| 80 |
$(GLINK BasicType2)$(OPT) $(I Identifier) $(GLINK DeclaratorSuffixes)$(OPT) |
|---|
| 81 |
|
|---|
| 82 |
$(GNAME DeclaratorSuffixes): |
|---|
| 83 |
$(GLINK DeclaratorSuffix) |
|---|
| 84 |
$(GLINK DeclaratorSuffix) $(I DeclaratorSuffixes) |
|---|
| 85 |
|
|---|
| 86 |
$(GNAME DeclaratorSuffix): |
|---|
| 87 |
$(B [ ]) |
|---|
| 88 |
$(B [) $(VEXPRESSION) $(B ]) |
|---|
| 89 |
$(B [) $(GLINK Type) $(B ]) |
|---|
| 90 |
$(GLINK2 template, TemplateParameterList)$(OPT) $(GLINK Parameters) $(V2 $(GLINK MemberFunctionAttributes)$(OPT) $(GLINK2 template, Constraint)$(OPT)) |
|---|
| 91 |
|
|---|
| 92 |
$(GNAME IdentifierList): |
|---|
| 93 |
$(I Identifier) |
|---|
| 94 |
$(I Identifier) $(B .) $(I IdentifierList) |
|---|
| 95 |
$(GLINK2 template, TemplateInstance) |
|---|
| 96 |
$(GLINK2 template, TemplateInstance) $(B .) $(I IdentifierList) |
|---|
| 97 |
|
|---|
| 98 |
$(GNAME StorageClasses): |
|---|
| 99 |
$(GLINK StorageClass) |
|---|
| 100 |
$(GLINK StorageClass) $(I StorageClasses) |
|---|
| 101 |
|
|---|
| 102 |
$(GNAME StorageClass): |
|---|
| 103 |
$(B abstract) |
|---|
| 104 |
$(B auto) |
|---|
| 105 |
$(B const) |
|---|
| 106 |
$(B deprecated) |
|---|
| 107 |
$(B extern) |
|---|
| 108 |
$(B final) |
|---|
| 109 |
$(V2 $(B immutable) |
|---|
| 110 |
$(B inout) |
|---|
| 111 |
$(B shared) |
|---|
| 112 |
$(B nothrow) |
|---|
| 113 |
$(B override) |
|---|
| 114 |
$(B pure) |
|---|
| 115 |
$(B __gshared) |
|---|
| 116 |
$(GLINK Property) |
|---|
| 117 |
) $(B scope) |
|---|
| 118 |
$(B static) |
|---|
| 119 |
$(B synchronized) |
|---|
| 120 |
|
|---|
| 121 |
$(GNAME Property): |
|---|
| 122 |
$(B @) $(I Identifier) |
|---|
| 123 |
|
|---|
| 124 |
$(GNAME Type): |
|---|
| 125 |
$(GLINK BasicType) |
|---|
| 126 |
$(GLINK BasicType) $(GLINK Declarator2) |
|---|
| 127 |
|
|---|
| 128 |
$(GNAME Declarator2): |
|---|
| 129 |
$(GLINK BasicType2)$(OPT) $(GLINK DeclaratorSuffixes)$(OPT) |
|---|
| 130 |
$(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator2) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT) |
|---|
| 131 |
|
|---|
| 132 |
$(GNAME Parameters): |
|---|
| 133 |
$(B $(LPAREN)) $(GLINK ParameterList) $(B $(RPAREN)) |
|---|
| 134 |
$(B ( )) |
|---|
| 135 |
|
|---|
| 136 |
$(GNAME ParameterList): |
|---|
| 137 |
$(GLINK Parameter) |
|---|
| 138 |
$(GLINK Parameter) $(B ,) $(I ParameterList) |
|---|
| 139 |
$(B ...) |
|---|
| 140 |
|
|---|
| 141 |
$(GNAME Parameter): |
|---|
| 142 |
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) |
|---|
| 143 |
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) $(B ...) |
|---|
| 144 |
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) = $(GLINK DefaultInitializerExpression) |
|---|
| 145 |
$(I InOut)$(OPT) $(GLINK Type) |
|---|
| 146 |
$(I InOut)$(OPT) $(GLINK Type) $(B ...) |
|---|
| 147 |
|
|---|
| 148 |
$(GNAME InOut): |
|---|
| 149 |
$(I InOutX) |
|---|
| 150 |
$(I InOut InOutX) |
|---|
| 151 |
|
|---|
| 152 |
$(GNAME InOutX): |
|---|
| 153 |
$(B auto) |
|---|
| 154 |
$(B const) |
|---|
| 155 |
$(B final) |
|---|
| 156 |
$(V2 $(B immutable) |
|---|
| 157 |
) $(B in) |
|---|
| 158 |
$(B inout) |
|---|
| 159 |
$(B lazy) |
|---|
| 160 |
$(B out) |
|---|
| 161 |
$(B ref) |
|---|
| 162 |
$(B scope) |
|---|
| 163 |
$(B shared) |
|---|
| 164 |
|
|---|
| 165 |
$(V2 |
|---|
| 166 |
$(GNAME FunctionAttributes): |
|---|
| 167 |
$(GLINK FunctionAttribute) |
|---|
| 168 |
$(GLINK FunctionAttribute) $(I FunctionAttributes) |
|---|
| 169 |
|
|---|
| 170 |
$(GNAME FunctionAttribute): |
|---|
| 171 |
$(B nothrow) |
|---|
| 172 |
$(B pure) |
|---|
| 173 |
$(GLINK Property) |
|---|
| 174 |
) |
|---|
| 175 |
$(GNAME MemberFunctionAttributes): |
|---|
| 176 |
$(GLINK MemberFunctionAttribute) |
|---|
| 177 |
$(GLINK MemberFunctionAttribute) $(I MemberFunctionAttributes) |
|---|
| 178 |
|
|---|
| 179 |
$(GNAME MemberFunctionAttribute): |
|---|
| 180 |
$(B const) |
|---|
| 181 |
$(B immutable) |
|---|
| 182 |
$(B inout) |
|---|
| 183 |
$(B shared) |
|---|
| 184 |
$(GLINK FunctionAttribute) |
|---|
| 185 |
|
|---|
| 186 |
$(GNAME DefaultInitializerExpression): |
|---|
| 187 |
$(ASSIGNEXPRESSION) |
|---|
| 188 |
$(V2 $(B __FILE__) |
|---|
| 189 |
$(B __LINE__)) |
|---|
| 190 |
|
|---|
| 191 |
$(GNAME Initializer): |
|---|
| 192 |
$(GLINK VoidInitializer) |
|---|
| 193 |
$(GLINK NonVoidInitializer) |
|---|
| 194 |
|
|---|
| 195 |
$(GNAME NonVoidInitializer): |
|---|
| 196 |
$(ASSIGNEXPRESSION) |
|---|
| 197 |
$(GLINK ArrayInitializer) |
|---|
| 198 |
$(GLINK StructInitializer) |
|---|
| 199 |
|
|---|
| 200 |
$(GNAME ArrayInitializer): |
|---|
| 201 |
$(B [ ]) |
|---|
| 202 |
$(B [) $(GLINK ArrayMemberInitializations) $(B ]) |
|---|
| 203 |
|
|---|
| 204 |
$(GNAME ArrayMemberInitializations): |
|---|
| 205 |
$(GLINK ArrayMemberInitialization) |
|---|
| 206 |
$(GLINK ArrayMemberInitialization) $(B ,) |
|---|
| 207 |
$(GLINK ArrayMemberInitialization) $(B ,) $(I ArrayMemberInitializations) |
|---|
| 208 |
|
|---|
| 209 |
$(GNAME ArrayMemberInitialization): |
|---|
| 210 |
$(GLINK NonVoidInitializer) |
|---|
| 211 |
$(ASSIGNEXPRESSION) $(B :) $(GLINK NonVoidInitializer) |
|---|
| 212 |
|
|---|
| 213 |
$(GNAME StructInitializer): |
|---|
| 214 |
$(B { }) |
|---|
| 215 |
$(B {) $(GLINK StructMemberInitializers) $(B }) |
|---|
| 216 |
|
|---|
| 217 |
$(GNAME StructMemberInitializers): |
|---|
| 218 |
$(GLINK StructMemberInitializer) |
|---|
| 219 |
$(GLINK StructMemberInitializer) $(B ,) |
|---|
| 220 |
$(GLINK StructMemberInitializer) $(B ,) $(I StructMemberInitializers) |
|---|
| 221 |
|
|---|
| 222 |
$(GNAME StructMemberInitializer): |
|---|
| 223 |
$(GLINK NonVoidInitializer) |
|---|
| 224 |
$(I Identifier) $(B :) $(GLINK NonVoidInitializer) |
|---|
| 225 |
) |
|---|
| 226 |
|
|---|
| 227 |
<h3>Declaration Syntax</h3> |
|---|
| 228 |
|
|---|
| 229 |
$(P Declaration syntax generally reads right to left:) |
|---|
| 230 |
|
|---|
| 231 |
-------------------- |
|---|
| 232 |
int x; // x is an int |
|---|
| 233 |
int* x; // x is a pointer to int |
|---|
| 234 |
int** x; // x is a pointer to a pointer to int |
|---|
| 235 |
int[] x; // x is an array of ints |
|---|
| 236 |
int*[] x; // x is an array of pointers to ints |
|---|
| 237 |
int[]* x; // x is a pointer to an array of ints |
|---|
| 238 |
-------------------- |
|---|
| 239 |
|
|---|
| 240 |
$(P Arrays read right to left as well:) |
|---|
| 241 |
|
|---|
| 242 |
-------------------- |
|---|
| 243 |
int[3] x; // x is an array of 3 ints |
|---|
| 244 |
int[3][5] x; // x is an array of 5 arrays of 3 ints |
|---|
| 245 |
int[3]*[5] x; // x is an array of 5 pointers to arrays of 3 ints |
|---|
| 246 |
-------------------- |
|---|
| 247 |
|
|---|
| 248 |
$(P |
|---|
| 249 |
Pointers to functions are declared using the $(B function) keyword: |
|---|
| 250 |
) |
|---|
| 251 |
|
|---|
| 252 |
-------------------- |
|---|
| 253 |
int $(B function)(char) x; // x is a pointer to a function taking a char argument |
|---|
| 254 |
// and returning an int |
|---|
| 255 |
int $(B function)(char)[] x; // x is an array of pointers to functions |
|---|
| 256 |
// taking a char argument and returning an int |
|---|
| 257 |
-------------------- |
|---|
| 258 |
|
|---|
| 259 |
$(P |
|---|
| 260 |
$(V1 C-style array, function pointer and pointer to array declarations are possible as an alternative:) |
|---|
| 261 |
$(V2 C-style array, function pointer and pointer to array declarations are deprecated:) |
|---|
| 262 |
) |
|---|
| 263 |
|
|---|
| 264 |
-------------------- |
|---|
| 265 |
int x[3]; // x is an array of 3 ints |
|---|
| 266 |
int x[3][5]; // x is an array of 3 arrays of 5 ints |
|---|
| 267 |
int (*x[5])[3]; // x is an array of 5 pointers to arrays of 3 ints |
|---|
| 268 |
int (*x)(char); // x is a pointer to a function taking a char argument |
|---|
| 269 |
// and returning an int |
|---|
| 270 |
int (*[] x)(char); // x is an array of pointers to functions |
|---|
| 271 |
// taking a char argument and returning an int |
|---|
| 272 |
-------------------- |
|---|
| 273 |
|
|---|
| 274 |
$(P |
|---|
| 275 |
In a declaration declaring multiple symbols, all the declarations |
|---|
| 276 |
must be of the same type: |
|---|
| 277 |
) |
|---|
| 278 |
|
|---|
| 279 |
-------------------- |
|---|
| 280 |
int x,y; // x and y are ints |
|---|
| 281 |
int* x,y; // x and y are pointers to ints |
|---|
| 282 |
int x,*y; // error, multiple types |
|---|
| 283 |
int[] x,y; // x and y are arrays of ints |
|---|
| 284 |
int x[],y; // error, multiple types |
|---|
| 285 |
-------------------- |
|---|
| 286 |
|
|---|
| 287 |
<h3><a name="AutoDeclaration">Implicit Type Inference</a></h3> |
|---|
| 288 |
|
|---|
| 289 |
$(GRAMMAR |
|---|
| 290 |
$(GNAME AutoDeclaration): |
|---|
| 291 |
$(GLINK StorageClasses) $(I AutoDeclarationX) $(B ;) |
|---|
| 292 |
|
|---|
| 293 |
$(GNAME AutoDeclarationX): |
|---|
| 294 |
$(I Identifier) $(B =) $(GLINK Initializer) |
|---|
| 295 |
$(I AutoDeclarationX) $(B ,) $(I Identifier) $(B =) $(GLINK Initializer) |
|---|
| 296 |
) |
|---|
| 297 |
|
|---|
| 298 |
$(P If a declaration starts with a $(I StorageClass) and has |
|---|
| 299 |
a $(I NonVoidInitializer) from which the type can be inferred, |
|---|
| 300 |
the type on the declaration can be omitted. |
|---|
| 301 |
) |
|---|
| 302 |
|
|---|
| 303 |
---------- |
|---|
| 304 |
static x = 3; // x is type int |
|---|
| 305 |
auto y = 4u; // y is type uint |
|---|
| 306 |
$(V1 auto s = "string"; // s is type char[6]) |
|---|
| 307 |
$(V2 auto s = "string"; // s is type immutable(char)[]) |
|---|
| 308 |
|
|---|
| 309 |
class C { ... } |
|---|
| 310 |
|
|---|
| 311 |
auto c = new C(); // c is a handle to an instance of class C |
|---|
| 312 |
---------- |
|---|
| 313 |
|
|---|
| 314 |
$(P The $(I NonVoidInitializer) cannot contain forward references |
|---|
| 315 |
(this restriction may be removed in the future). |
|---|
| 316 |
The implicitly inferred type is statically bound |
|---|
| 317 |
to the declaration at compile time, not run time. |
|---|
| 318 |
) |
|---|
| 319 |
|
|---|
| 320 |
$(V2 |
|---|
| 321 |
$(P An $(LINK2 expression.html#ArrayLiteral, $(I ArrayLiteral)) |
|---|
| 322 |
is inferred to be a dynamic array |
|---|
| 323 |
type rather than a static array:) |
|---|
| 324 |
|
|---|
| 325 |
--- |
|---|
| 326 |
auto v = ["hello", "world"]; // type is string[], not string[2] |
|---|
| 327 |
--- |
|---|
| 328 |
) |
|---|
| 329 |
|
|---|
| 330 |
$(V1 |
|---|
| 331 |
<h3><a name="typedef">Type Defining</a></h3> |
|---|
| 332 |
|
|---|
| 333 |
$(P |
|---|
| 334 |
Strong types can be introduced with the typedef. Strong types are semantically a |
|---|
| 335 |
distinct type to the type checking system, for function overloading, and for the debugger. |
|---|
| 336 |
) |
|---|
| 337 |
|
|---|
| 338 |
-------------------- |
|---|
| 339 |
typedef int myint; |
|---|
| 340 |
|
|---|
| 341 |
void foo(int x) { . } |
|---|
| 342 |
void foo(myint m) { . } |
|---|
| 343 |
|
|---|
| 344 |
. |
|---|
| 345 |
myint b; |
|---|
| 346 |
foo(b); // calls foo(myint) |
|---|
| 347 |
-------------------- |
|---|
| 348 |
|
|---|
| 349 |
Typedefs can specify a default initializer different from the |
|---|
| 350 |
default initializer of the underlying type: |
|---|
| 351 |
|
|---|
| 352 |
-------------------- |
|---|
| 353 |
typedef int myint = 7; |
|---|
| 354 |
myint m; // initialized to 7 |
|---|
| 355 |
-------------------- |
|---|
| 356 |
) |
|---|
| 357 |
|
|---|
| 358 |
<h3><a name="alias">Type Aliasing</a></h3> |
|---|
| 359 |
|
|---|
| 360 |
$(P |
|---|
| 361 |
It's sometimes convenient to use an alias for a type, such as a shorthand for typing |
|---|
| 362 |
out a long, complex type like a pointer to a function. In D, this is done with the |
|---|
| 363 |
alias declaration: |
|---|
| 364 |
) |
|---|
| 365 |
|
|---|
| 366 |
-------------------- |
|---|
| 367 |
$(B alias) abc.Foo.bar myint; |
|---|
| 368 |
-------------------- |
|---|
| 369 |
|
|---|
| 370 |
$(P |
|---|
| 371 |
Aliased types are semantically identical to the types they are aliased to. The |
|---|
| 372 |
debugger cannot distinguish between them, and there is no difference as far as function |
|---|
| 373 |
overloading is concerned. For example: |
|---|
| 374 |
) |
|---|
| 375 |
|
|---|
| 376 |
-------------------- |
|---|
| 377 |
$(B alias) int myint; |
|---|
| 378 |
|
|---|
| 379 |
void foo(int x) { . } |
|---|
| 380 |
void foo(myint m) { . } // error, multiply defined function foo |
|---|
| 381 |
-------------------- |
|---|
| 382 |
|
|---|
| 383 |
$(V1 |
|---|
| 384 |
$(P |
|---|
| 385 |
Type aliases are equivalent to the C typedef. |
|---|
| 386 |
) |
|---|
| 387 |
) |
|---|
| 388 |
|
|---|
| 389 |
<h3>Alias Declarations</h3> |
|---|
| 390 |
|
|---|
| 391 |
$(P |
|---|
| 392 |
A symbol can be declared as an $(I alias) of another symbol. |
|---|
| 393 |
For example: |
|---|
| 394 |
) |
|---|
| 395 |
|
|---|
| 396 |
-------------------- |
|---|
| 397 |
import string; |
|---|
| 398 |
|
|---|
| 399 |
$(B alias) string.strlen mylen; |
|---|
| 400 |
... |
|---|
| 401 |
int len = mylen("hello"); // actually calls string.strlen() |
|---|
| 402 |
-------------------- |
|---|
| 403 |
|
|---|
| 404 |
$(P |
|---|
| 405 |
The following alias declarations are valid: |
|---|
| 406 |
) |
|---|
| 407 |
|
|---|
| 408 |
-------------------- |
|---|
| 409 |
template Foo2(T) { $(B alias) T t; } |
|---|
| 410 |
$(B alias) Foo2!(int) t1; |
|---|
| 411 |
$(B alias) Foo2!(int).t t2; |
|---|
| 412 |
$(B alias) t1.t t3; |
|---|
| 413 |
$(B alias) t2 t4; |
|---|
| 414 |
|
|---|
| 415 |
t1.t v1; // v1 is type int |
|---|
| 416 |
t2 v2; // v2 is type int |
|---|
| 417 |
t3 v3; // v3 is type int |
|---|
| 418 |
t4 v4; // v4 is type int |
|---|
| 419 |
-------------------- |
|---|
| 420 |
|
|---|
| 421 |
$(P |
|---|
| 422 |
Aliased symbols are useful as a shorthand for a long qualified |
|---|
| 423 |
symbol name, or as a way to redirect references from one symbol |
|---|
| 424 |
to another: |
|---|
| 425 |
) |
|---|
| 426 |
|
|---|
| 427 |
-------------------- |
|---|
| 428 |
version (Win32) |
|---|
| 429 |
{ |
|---|
| 430 |
$(B alias) win32.foo myfoo; |
|---|
| 431 |
} |
|---|
| 432 |
version (linux) |
|---|
| 433 |
{ |
|---|
| 434 |
$(B alias) linux.bar myfoo; |
|---|
| 435 |
} |
|---|
| 436 |
-------------------- |
|---|
| 437 |
|
|---|
| 438 |
$(P |
|---|
| 439 |
Aliasing can be used to $(SINGLEQUOTE import) a symbol from an import into the |
|---|
| 440 |
current scope: |
|---|
| 441 |
) |
|---|
| 442 |
|
|---|
| 443 |
-------------------- |
|---|
| 444 |
$(B alias) string.strlen strlen; |
|---|
| 445 |
-------------------- |
|---|
| 446 |
|
|---|
| 447 |
$(P |
|---|
| 448 |
Aliases can also $(SINGLEQUOTE import) a set of overloaded functions, that can |
|---|
| 449 |
be overloaded with functions in the current scope: |
|---|
| 450 |
) |
|---|
| 451 |
|
|---|
| 452 |
-------------------- |
|---|
| 453 |
class A { |
|---|
| 454 |
int foo(int a) { return 1; } |
|---|
| 455 |
} |
|---|
| 456 |
|
|---|
| 457 |
class B : A { |
|---|
| 458 |
int foo( int a, uint b ) { return 2; } |
|---|
| 459 |
} |
|---|
| 460 |
|
|---|
| 461 |
class C : B { |
|---|
| 462 |
int foo( int a ) { return 3; } |
|---|
| 463 |
$(B alias) B.foo foo; |
|---|
| 464 |
} |
|---|
| 465 |
|
|---|
| 466 |
class D : C { |
|---|
| 467 |
} |
|---|
| 468 |
|
|---|
| 469 |
|
|---|
| 470 |
void test() |
|---|
| 471 |
{ |
|---|
| 472 |
D b = new D(); |
|---|
| 473 |
int i; |
|---|
| 474 |
|
|---|
| 475 |
i = b.foo(1, 2u); // calls B.foo |
|---|
| 476 |
i = b.foo(1); // calls C.foo |
|---|
| 477 |
} |
|---|
| 478 |
-------------------- |
|---|
| 479 |
|
|---|
| 480 |
$(P |
|---|
| 481 |
$(B Note:) Type aliases can sometimes look indistinguishable from |
|---|
| 482 |
alias declarations: |
|---|
| 483 |
) |
|---|
| 484 |
|
|---|
| 485 |
-------------------- |
|---|
| 486 |
$(B alias) foo.bar abc; // is it a type or a symbol? |
|---|
| 487 |
-------------------- |
|---|
| 488 |
|
|---|
| 489 |
$(P |
|---|
| 490 |
The distinction is made in the semantic analysis pass. |
|---|
| 491 |
) |
|---|
| 492 |
|
|---|
| 493 |
$(P Aliases cannot be used for expressions:) |
|---|
| 494 |
|
|---|
| 495 |
----------- |
|---|
| 496 |
struct S { static int i; } |
|---|
| 497 |
S s; |
|---|
| 498 |
|
|---|
| 499 |
alias s.i a; // illegal, s.i is an expression |
|---|
| 500 |
alias S.i b; // ok |
|---|
| 501 |
b = 4; // sets S.i to 4 |
|---|
| 502 |
----------- |
|---|
| 503 |
|
|---|
| 504 |
<h3><a name="extern">Extern Declarations</a></h3> |
|---|
| 505 |
|
|---|
| 506 |
Variable declarations with the storage class $(B extern) are |
|---|
| 507 |
not allocated storage within the module. |
|---|
| 508 |
They must be defined in some other object file with a matching |
|---|
| 509 |
name which is then linked in. |
|---|
| 510 |
The primary usefulness of this is to connect with global |
|---|
| 511 |
variable declarations in C files. |
|---|
| 512 |
|
|---|
| 513 |
<h3><a name="typeof">typeof</a></h3> |
|---|
| 514 |
|
|---|
| 515 |
$(GRAMMAR |
|---|
| 516 |
$(GNAME Typeof): |
|---|
| 517 |
$(B typeof $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) |
|---|
| 518 |
$(B typeof $(LPAREN)) $(B return) $(B $(RPAREN)) |
|---|
| 519 |
) |
|---|
| 520 |
|
|---|
| 521 |
$(P |
|---|
| 522 |
$(I Typeof) is a way to specify a type based on the type |
|---|
| 523 |
of an expression. For example: |
|---|
| 524 |
) |
|---|
| 525 |
|
|---|
| 526 |
-------------------- |
|---|
| 527 |
void func(int i) |
|---|
| 528 |
{ |
|---|
| 529 |
$(B typeof)(i) j; // j is of type int |
|---|
| 530 |
$(B typeof)(3 + 6.0) x; // x is of type double |
|---|
| 531 |
$(B typeof)(1)* p; // p is of type pointer to int |
|---|
| 532 |
int[$(B typeof)(p)] a; // a is of type int[int*] |
|---|
| 533 |
|
|---|
| 534 |
writefln("%d", $(B typeof)('c').sizeof); // prints 1 |
|---|
| 535 |
double c = cast($(B typeof)(1.0))j; // cast j to double |
|---|
| 536 |
} |
|---|
| 537 |
-------------------- |
|---|
| 538 |
|
|---|
| 539 |
$(P |
|---|
| 540 |
$(I Expression) is not evaluated, just the type of it is |
|---|
| 541 |
generated: |
|---|
| 542 |
) |
|---|
| 543 |
|
|---|
| 544 |
-------------------- |
|---|
| 545 |
void func() |
|---|
| 546 |
{ int i = 1; |
|---|
| 547 |
$(B typeof)(++i) j; // j is declared to be an int, i is not incremented |
|---|
| 548 |
writefln("%d", i); // prints 1 |
|---|
| 549 |
} |
|---|
| 550 |
-------------------- |
|---|
| 551 |
|
|---|
| 552 |
$(P |
|---|
| 553 |
There are $(V1 two) $(V2 three) special cases: |
|---|
| 554 |
$(OL |
|---|
| 555 |
$(LI $(B typeof(this)) will generate the type of what $(B this) |
|---|
| 556 |
would be in a non-static member function, even if not in a member |
|---|
| 557 |
function. |
|---|
| 558 |
) |
|---|
| 559 |
$(LI Analogously, $(B typeof(super)) will generate the type of what |
|---|
| 560 |
$(B super) would be in a non-static member function. |
|---|
| 561 |
) |
|---|
| 562 |
$(V2 |
|---|
| 563 |
$(LI $(B typeof(return)) will, when inside a function scope, |
|---|
| 564 |
give the return type of that function. |
|---|
| 565 |
) |
|---|
| 566 |
) |
|---|
| 567 |
) |
|---|
| 568 |
) |
|---|
| 569 |
|
|---|
| 570 |
-------------------- |
|---|
| 571 |
class A { } |
|---|
| 572 |
|
|---|
| 573 |
class B : A |
|---|
| 574 |
{ |
|---|
| 575 |
$(B typeof(this)) x; // x is declared to be a B |
|---|
| 576 |
$(B typeof(super)) y; // y is declared to be an A |
|---|
| 577 |
} |
|---|
| 578 |
|
|---|
| 579 |
struct C |
|---|
| 580 |
{ |
|---|
| 581 |
$(B typeof(this)) z; // z is declared to be a C* |
|---|
| 582 |
$(B typeof(super)) q; // error, no super struct for C |
|---|
| 583 |
} |
|---|
| 584 |
|
|---|
| 585 |
$(B typeof(this)) r; // error, no enclosing struct or class |
|---|
| 586 |
-------------------- |
|---|
| 587 |
|
|---|
| 588 |
$(P |
|---|
| 589 |
Where $(I Typeof) is most useful is in writing generic |
|---|
| 590 |
template code. |
|---|
| 591 |
) |
|---|
| 592 |
|
|---|
| 593 |
<h3>Void Initializations</h3> |
|---|
| 594 |
|
|---|
| 595 |
$(GRAMMAR |
|---|
| 596 |
$(GNAME VoidInitializer): |
|---|
| 597 |
$(B void) |
|---|
| 598 |
) |
|---|
| 599 |
|
|---|
| 600 |
Normally, variables are initialized either with an explicit |
|---|
| 601 |
$(I Initializer) or are set to the default value for the |
|---|
| 602 |
type of the variable. If the $(I Initializer) is $(B void), |
|---|
| 603 |
however, the variable is not initialized. If its value is |
|---|
| 604 |
used before it is set, undefined program behavior will result. |
|---|
| 605 |
|
|---|
| 606 |
------------------------- |
|---|
| 607 |
void foo() |
|---|
| 608 |
{ |
|---|
| 609 |
int x = void; |
|---|
| 610 |
writefln(x); // will print garbage |
|---|
| 611 |
} |
|---|
| 612 |
------------------------- |
|---|
| 613 |
|
|---|
| 614 |
Therefore, one should only use $(B void) initializers as a |
|---|
| 615 |
last resort when optimizing critical code. |
|---|
| 616 |
|
|---|
| 617 |
) |
|---|
| 618 |
|
|---|
| 619 |
Macros: |
|---|
| 620 |
TITLE=Declarations |
|---|
| 621 |
WIKI=Declaration |
|---|
| 622 |
OPT=<sub>opt</sub> |
|---|
| 623 |
ASSIGNEXPRESSION=$(LINK2 expression.html#AssignExpression, $(I AssignExpression)) |
|---|
| 624 |
EXPRESSION=$(LINK2 expression.html#Expression, $(I Expression)) |
|---|
| 625 |
VEXPRESSION=$(V1 $(EXPRESSION))$(V2 $(ASSIGNEXPRESSION)) |
|---|
| 626 |
FOO= |
|---|