| 1 |
Ddoc |
|---|
| 2 |
|
|---|
| 3 |
$(SPEC_S Structs & Unions, |
|---|
| 4 |
|
|---|
| 5 |
$(P Whereas classes are reference types, structs are value types. |
|---|
| 6 |
Any C struct can be exactly represented as a D struct. |
|---|
| 7 |
In C++ parlance, a D struct is a |
|---|
| 8 |
$(LINK2 glossary.html#pod, POD (Plain Old Data)) type, |
|---|
| 9 |
with a trivial constructors and destructors. |
|---|
| 10 |
Structs and unions are meant as simple aggregations of data, or as a way |
|---|
| 11 |
to paint a data structure over hardware or an external type. External |
|---|
| 12 |
types can be defined by the operating system API, or by a file format. |
|---|
| 13 |
Object oriented features are provided with the class data type. |
|---|
| 14 |
) |
|---|
| 15 |
|
|---|
| 16 |
$(P A struct is defined to not have an identity; that is, |
|---|
| 17 |
the implementation is free to make bit copies of the struct |
|---|
| 18 |
as convenient.) |
|---|
| 19 |
|
|---|
| 20 |
$(TABLE2 Struct$(COMMA) Class Comparison Table, |
|---|
| 21 |
|
|---|
| 22 |
$(TR |
|---|
| 23 |
$(TH Feature) |
|---|
| 24 |
$(TH struct) |
|---|
| 25 |
$(TH class) |
|---|
| 26 |
$(TH C struct) |
|---|
| 27 |
$(TH C++ struct) |
|---|
| 28 |
$(TH C++ class) |
|---|
| 29 |
) |
|---|
| 30 |
|
|---|
| 31 |
$(TR |
|---|
| 32 |
$(TD value type) |
|---|
| 33 |
$(YES) |
|---|
| 34 |
$(NO) |
|---|
| 35 |
$(YES) |
|---|
| 36 |
$(YES) |
|---|
| 37 |
$(YES) |
|---|
| 38 |
) |
|---|
| 39 |
|
|---|
| 40 |
$(TR |
|---|
| 41 |
$(TD reference type) |
|---|
| 42 |
$(NO) |
|---|
| 43 |
$(YES) |
|---|
| 44 |
$(NO) |
|---|
| 45 |
$(NO) |
|---|
| 46 |
$(NO) |
|---|
| 47 |
) |
|---|
| 48 |
|
|---|
| 49 |
$(TR |
|---|
| 50 |
$(TD data members) |
|---|
| 51 |
$(YES) |
|---|
| 52 |
$(YES) |
|---|
| 53 |
$(YES) |
|---|
| 54 |
$(YES) |
|---|
| 55 |
$(YES) |
|---|
| 56 |
) |
|---|
| 57 |
|
|---|
| 58 |
$(TR |
|---|
| 59 |
$(TD hidden members) |
|---|
| 60 |
$(V1 $(NO)) |
|---|
| 61 |
$(V2 $(YES)) |
|---|
| 62 |
$(YES) |
|---|
| 63 |
$(NO) |
|---|
| 64 |
$(YES) |
|---|
| 65 |
$(YES) |
|---|
| 66 |
) |
|---|
| 67 |
|
|---|
| 68 |
$(TR |
|---|
| 69 |
$(TD static members) |
|---|
| 70 |
$(YES) |
|---|
| 71 |
$(YES) |
|---|
| 72 |
$(NO) |
|---|
| 73 |
$(YES) |
|---|
| 74 |
$(YES) |
|---|
| 75 |
) |
|---|
| 76 |
|
|---|
| 77 |
$(TR |
|---|
| 78 |
$(TD default member initializers) |
|---|
| 79 |
$(YES) |
|---|
| 80 |
$(YES) |
|---|
| 81 |
$(NO) |
|---|
| 82 |
$(NO) |
|---|
| 83 |
$(NO) |
|---|
| 84 |
) |
|---|
| 85 |
|
|---|
| 86 |
$(TR |
|---|
| 87 |
$(TD bit fields) |
|---|
| 88 |
$(NO) |
|---|
| 89 |
$(NO) |
|---|
| 90 |
$(YES) |
|---|
| 91 |
$(YES) |
|---|
| 92 |
$(YES) |
|---|
| 93 |
) |
|---|
| 94 |
|
|---|
| 95 |
$(TR |
|---|
| 96 |
$(TD non-virtual member functions) |
|---|
| 97 |
$(YES) |
|---|
| 98 |
$(YES) |
|---|
| 99 |
$(NO) |
|---|
| 100 |
$(YES) |
|---|
| 101 |
$(YES) |
|---|
| 102 |
) |
|---|
| 103 |
|
|---|
| 104 |
$(TR |
|---|
| 105 |
$(TD virtual member functions) |
|---|
| 106 |
$(NO) |
|---|
| 107 |
$(YES) |
|---|
| 108 |
$(NO) |
|---|
| 109 |
$(YES) |
|---|
| 110 |
$(YES) |
|---|
| 111 |
) |
|---|
| 112 |
|
|---|
| 113 |
$(V1 |
|---|
| 114 |
$(TR |
|---|
| 115 |
$(TD constructors) |
|---|
| 116 |
$(NO) |
|---|
| 117 |
$(YES) |
|---|
| 118 |
$(NO) |
|---|
| 119 |
$(YES) |
|---|
| 120 |
$(YES) |
|---|
| 121 |
) |
|---|
| 122 |
$(TR |
|---|
| 123 |
$(TD destructors) |
|---|
| 124 |
$(NO) |
|---|
| 125 |
$(YES) |
|---|
| 126 |
$(NO) |
|---|
| 127 |
$(YES) |
|---|
| 128 |
$(YES) |
|---|
| 129 |
) |
|---|
| 130 |
$(TR |
|---|
| 131 |
$(TD RAII) |
|---|
| 132 |
$(NO) |
|---|
| 133 |
$(YES) |
|---|
| 134 |
$(NO) |
|---|
| 135 |
$(YES) |
|---|
| 136 |
$(YES) |
|---|
| 137 |
) |
|---|
| 138 |
$(TR |
|---|
| 139 |
$(TD assign overload) |
|---|
| 140 |
$(NO) |
|---|
| 141 |
$(NO) |
|---|
| 142 |
$(NO) |
|---|
| 143 |
$(YES) |
|---|
| 144 |
$(YES) |
|---|
| 145 |
) |
|---|
| 146 |
) |
|---|
| 147 |
$(V2 |
|---|
| 148 |
$(TR |
|---|
| 149 |
$(TD $(LINK2 #Struct-Constructor, constructors)) |
|---|
| 150 |
$(YES) |
|---|
| 151 |
$(YES) |
|---|
| 152 |
$(NO) |
|---|
| 153 |
$(YES) |
|---|
| 154 |
$(YES) |
|---|
| 155 |
) |
|---|
| 156 |
$(TR |
|---|
| 157 |
$(TD $(LINK2 #StructPostblit, postblit)/copy constructors) |
|---|
| 158 |
$(YES) |
|---|
| 159 |
$(NO) |
|---|
| 160 |
$(NO) |
|---|
| 161 |
$(YES) |
|---|
| 162 |
$(YES) |
|---|
| 163 |
) |
|---|
| 164 |
$(TR |
|---|
| 165 |
$(TD $(LINK2 #StructDestructor, destructors)) |
|---|
| 166 |
$(YES) |
|---|
| 167 |
$(YES) |
|---|
| 168 |
$(NO) |
|---|
| 169 |
$(YES) |
|---|
| 170 |
$(YES) |
|---|
| 171 |
) |
|---|
| 172 |
$(TR |
|---|
| 173 |
$(TD $(LINK2 class.html#SharedStaticConstructor, shared static constructors)) |
|---|
| 174 |
$(YES) |
|---|
| 175 |
$(YES) |
|---|
| 176 |
$(NO) |
|---|
| 177 |
$(NO) |
|---|
| 178 |
$(NO) |
|---|
| 179 |
) |
|---|
| 180 |
$(TR |
|---|
| 181 |
$(TD $(LINK2 class.html#SharedStaticDestructor, shared static destructors)) |
|---|
| 182 |
$(YES) |
|---|
| 183 |
$(YES) |
|---|
| 184 |
$(NO) |
|---|
| 185 |
$(NO) |
|---|
| 186 |
$(NO) |
|---|
| 187 |
) |
|---|
| 188 |
$(TR |
|---|
| 189 |
$(TD RAII) |
|---|
| 190 |
$(YES) |
|---|
| 191 |
$(YES) |
|---|
| 192 |
$(NO) |
|---|
| 193 |
$(YES) |
|---|
| 194 |
$(YES) |
|---|
| 195 |
) |
|---|
| 196 |
$(TR |
|---|
| 197 |
$(TD $(LINK2 #AssignOverload, assign overload)) |
|---|
| 198 |
$(YES) |
|---|
| 199 |
$(NO) |
|---|
| 200 |
$(NO) |
|---|
| 201 |
$(YES) |
|---|
| 202 |
$(YES) |
|---|
| 203 |
) |
|---|
| 204 |
) |
|---|
| 205 |
|
|---|
| 206 |
$(TR |
|---|
| 207 |
$(TD $(LINK2 #StructLiteral, literals)) |
|---|
| 208 |
$(YES) |
|---|
| 209 |
$(NO) |
|---|
| 210 |
$(NO) |
|---|
| 211 |
$(NO) |
|---|
| 212 |
$(NO) |
|---|
| 213 |
) |
|---|
| 214 |
|
|---|
| 215 |
$(TR |
|---|
| 216 |
$(TD operator overloading) |
|---|
| 217 |
$(YES) |
|---|
| 218 |
$(YES) |
|---|
| 219 |
$(NO) |
|---|
| 220 |
$(YES) |
|---|
| 221 |
$(YES) |
|---|
| 222 |
) |
|---|
| 223 |
|
|---|
| 224 |
$(TR |
|---|
| 225 |
$(TD inheritance) |
|---|
| 226 |
$(NO) |
|---|
| 227 |
$(YES) |
|---|
| 228 |
$(NO) |
|---|
| 229 |
$(YES) |
|---|
| 230 |
$(YES) |
|---|
| 231 |
) |
|---|
| 232 |
|
|---|
| 233 |
$(TR |
|---|
| 234 |
$(TD invariants) |
|---|
| 235 |
$(YES) |
|---|
| 236 |
$(YES) |
|---|
| 237 |
$(NO) |
|---|
| 238 |
$(NO) |
|---|
| 239 |
$(NO) |
|---|
| 240 |
) |
|---|
| 241 |
|
|---|
| 242 |
$(TR |
|---|
| 243 |
$(TD unit tests) |
|---|
| 244 |
$(YES) |
|---|
| 245 |
$(YES) |
|---|
| 246 |
$(NO) |
|---|
| 247 |
$(NO) |
|---|
| 248 |
$(NO) |
|---|
| 249 |
) |
|---|
| 250 |
|
|---|
| 251 |
$(TR |
|---|
| 252 |
$(TD synchronizable) |
|---|
| 253 |
$(NO) |
|---|
| 254 |
$(YES) |
|---|
| 255 |
$(NO) |
|---|
| 256 |
$(NO) |
|---|
| 257 |
$(NO) |
|---|
| 258 |
) |
|---|
| 259 |
|
|---|
| 260 |
$(TR |
|---|
| 261 |
$(TD parameterizable) |
|---|
| 262 |
$(YES) |
|---|
| 263 |
$(YES) |
|---|
| 264 |
$(NO) |
|---|
| 265 |
$(YES) |
|---|
| 266 |
$(YES) |
|---|
| 267 |
) |
|---|
| 268 |
|
|---|
| 269 |
$(TR |
|---|
| 270 |
$(TD alignment control) |
|---|
| 271 |
$(YES) |
|---|
| 272 |
$(YES) |
|---|
| 273 |
$(NO) |
|---|
| 274 |
$(NO) |
|---|
| 275 |
$(NO) |
|---|
| 276 |
) |
|---|
| 277 |
|
|---|
| 278 |
$(TR |
|---|
| 279 |
$(TD member protection) |
|---|
| 280 |
$(YES) |
|---|
| 281 |
$(YES) |
|---|
| 282 |
$(NO) |
|---|
| 283 |
$(YES) |
|---|
| 284 |
$(YES) |
|---|
| 285 |
) |
|---|
| 286 |
|
|---|
| 287 |
$(TR |
|---|
| 288 |
$(TD default public) |
|---|
| 289 |
$(YES) |
|---|
| 290 |
$(YES) |
|---|
| 291 |
$(YES) |
|---|
| 292 |
$(YES) |
|---|
| 293 |
$(NO) |
|---|
| 294 |
) |
|---|
| 295 |
|
|---|
| 296 |
$(TR |
|---|
| 297 |
$(TD tag name space) |
|---|
| 298 |
$(NO) |
|---|
| 299 |
$(NO) |
|---|
| 300 |
$(YES) |
|---|
| 301 |
$(YES) |
|---|
| 302 |
$(YES) |
|---|
| 303 |
) |
|---|
| 304 |
|
|---|
| 305 |
$(TR |
|---|
| 306 |
$(TD anonymous) |
|---|
| 307 |
$(YES) |
|---|
| 308 |
$(NO) |
|---|
| 309 |
$(YES) |
|---|
| 310 |
$(YES) |
|---|
| 311 |
$(YES) |
|---|
| 312 |
) |
|---|
| 313 |
|
|---|
| 314 |
$(TR |
|---|
| 315 |
$(TD static constructor) |
|---|
| 316 |
$(YES) |
|---|
| 317 |
$(YES) |
|---|
| 318 |
$(NO) |
|---|
| 319 |
$(NO) |
|---|
| 320 |
$(NO) |
|---|
| 321 |
) |
|---|
| 322 |
|
|---|
| 323 |
$(TR |
|---|
| 324 |
$(TD static destructor) |
|---|
| 325 |
$(YES) |
|---|
| 326 |
$(YES) |
|---|
| 327 |
$(NO) |
|---|
| 328 |
$(NO) |
|---|
| 329 |
$(NO) |
|---|
| 330 |
) |
|---|
| 331 |
|
|---|
| 332 |
$(V2 |
|---|
| 333 |
$(TR |
|---|
| 334 |
$(TD const/immutable/shared) |
|---|
| 335 |
$(YES) |
|---|
| 336 |
$(YES) |
|---|
| 337 |
$(NO) |
|---|
| 338 |
$(NO) |
|---|
| 339 |
$(NO) |
|---|
| 340 |
) |
|---|
| 341 |
|
|---|
| 342 |
$(TR |
|---|
| 343 |
$(TD inner nesting) |
|---|
| 344 |
$(TD $(LINK2 #nested, YES)) |
|---|
| 345 |
$(TD $(LINK2 class.html#nested, YES)) |
|---|
| 346 |
$(NO) |
|---|
| 347 |
$(NO) |
|---|
| 348 |
$(NO) |
|---|
| 349 |
) |
|---|
| 350 |
) |
|---|
| 351 |
) |
|---|
| 352 |
|
|---|
| 353 |
$(GRAMMAR |
|---|
| 354 |
$(GNAME AggregateDeclaration): |
|---|
| 355 |
$(B struct) $(I Identifier) $(GLINK StructBody) |
|---|
| 356 |
$(B union) $(I Identifier) $(GLINK StructBody) |
|---|
| 357 |
$(B struct) $(I Identifier) $(B ;) |
|---|
| 358 |
$(B union) $(I Identifier) $(B ;) |
|---|
| 359 |
$(LINK2 template.html#StructTemplateDeclaration, $(I StructTemplateDeclaration)) |
|---|
| 360 |
$(LINK2 template.html#UnionTemplateDeclaration, $(I UnionTemplateDeclaration)) |
|---|
| 361 |
|
|---|
| 362 |
$(GNAME StructBody): |
|---|
| 363 |
$(B {) $(B }) |
|---|
| 364 |
$(B {) $(GLINK StructBodyDeclarations) $(B }) |
|---|
| 365 |
|
|---|
| 366 |
$(GNAME StructBodyDeclarations): |
|---|
| 367 |
$(GLINK StructBodyDeclaration) |
|---|
| 368 |
$(GLINK StructBodyDeclaration) $(I StructBodyDeclarations) |
|---|
| 369 |
|
|---|
| 370 |
$(GNAME StructBodyDeclaration): |
|---|
| 371 |
$(LINK2 module.html#DeclDef, $(I DeclDef)) |
|---|
| 372 |
$(GLINK StructAllocator) |
|---|
| 373 |
$(GLINK StructDeallocator) |
|---|
| 374 |
$(V2 $(GLINK StructPostblit) |
|---|
| 375 |
$(LINK2 class.html#AliasThis, $(I AliasThis))) |
|---|
| 376 |
|
|---|
| 377 |
$(GNAME StructAllocator): |
|---|
| 378 |
$(LINK2 class.html#ClassAllocator, $(I ClassAllocator)) |
|---|
| 379 |
|
|---|
| 380 |
$(GNAME StructDeallocator): |
|---|
| 381 |
$(LINK2 class.html#ClassDeallocator, $(I ClassDeallocator)) |
|---|
| 382 |
) |
|---|
| 383 |
|
|---|
| 384 |
$(P They work like they do in C, with the following exceptions:) |
|---|
| 385 |
|
|---|
| 386 |
$(UL |
|---|
| 387 |
$(LI no bit fields) |
|---|
| 388 |
$(LI alignment can be explicitly specified) |
|---|
| 389 |
$(LI no separate tag name space - tag names go into the current scope) |
|---|
| 390 |
$(LI declarations like: |
|---|
| 391 |
|
|---|
| 392 |
------ |
|---|
| 393 |
struct ABC x; |
|---|
| 394 |
------ |
|---|
| 395 |
are not allowed, replace with: |
|---|
| 396 |
|
|---|
| 397 |
------ |
|---|
| 398 |
ABC x; |
|---|
| 399 |
------ |
|---|
| 400 |
) |
|---|
| 401 |
$(LI anonymous structs/unions are allowed as members of other structs/unions) |
|---|
| 402 |
$(LI Default initializers for members can be supplied.) |
|---|
| 403 |
$(LI Member functions and static members are allowed.) |
|---|
| 404 |
) |
|---|
| 405 |
|
|---|
| 406 |
|
|---|
| 407 |
|
|---|
| 408 |
<h3>Static Initialization of Structs</h3> |
|---|
| 409 |
|
|---|
| 410 |
Static struct members are by default initialized to whatever the |
|---|
| 411 |
default initializer for the member is, and if none supplied, to |
|---|
| 412 |
the default initializer for the member's type. |
|---|
| 413 |
If a static initializer is supplied, the |
|---|
| 414 |
members are initialized by the member name, |
|---|
| 415 |
colon, expression syntax. The members may be initialized in any order. |
|---|
| 416 |
Initializers for statics must be evaluatable at compile time. |
|---|
| 417 |
Members not specified in the initializer list are default initialized. |
|---|
| 418 |
|
|---|
| 419 |
------ |
|---|
| 420 |
struct X { int a; int b; int c; int d = 7;} |
|---|
| 421 |
static X x = { a:1, b:2}; // c is set to 0, d to 7 |
|---|
| 422 |
static X z = { c:4, b:5, a:2 , d:5}; // z.a = 2, z.b = 5, z.c = 4, z.d = 5 |
|---|
| 423 |
------ |
|---|
| 424 |
|
|---|
| 425 |
C-style initialization, based on the order of the members in the |
|---|
| 426 |
struct declaration, is also supported: |
|---|
| 427 |
|
|---|
| 428 |
------ |
|---|
| 429 |
static X q = { 1, 2 }; // q.a = 1, q.b = 2, q.c = 0, q.d = 7 |
|---|
| 430 |
------ |
|---|
| 431 |
|
|---|
| 432 |
$(P Struct literals can also be used to initialize statics, but |
|---|
| 433 |
they must be evaluable at compile time.) |
|---|
| 434 |
|
|---|
| 435 |
----- |
|---|
| 436 |
static X q = S( 1, 2+3 ); // q.a = 1, q.b = 5, q.c = 0, q.d = 7 |
|---|
| 437 |
----- |
|---|
| 438 |
|
|---|
| 439 |
$(P The static initializer syntax can also be used to initialize |
|---|
| 440 |
non-static variables, provided that the member names are not given. |
|---|
| 441 |
The initializer need not be evaluatable at compile time.) |
|---|
| 442 |
|
|---|
| 443 |
---- |
|---|
| 444 |
void test(int i) |
|---|
| 445 |
{ |
|---|
| 446 |
S s = { 1, i }; // q.a = 1, q.b = i, q.c = 0, q.d = 7 |
|---|
| 447 |
} |
|---|
| 448 |
---- |
|---|
| 449 |
|
|---|
| 450 |
|
|---|
| 451 |
<h3>Static Initialization of Unions</h3> |
|---|
| 452 |
|
|---|
| 453 |
Unions are initialized explicitly. |
|---|
| 454 |
|
|---|
| 455 |
------ |
|---|
| 456 |
union U { int a; double b; } |
|---|
| 457 |
static U u = { b : 5.0 }; // u.b = 5.0 |
|---|
| 458 |
------ |
|---|
| 459 |
|
|---|
| 460 |
Other members of the union that overlay the initializer, |
|---|
| 461 |
but occupy more storage, have |
|---|
| 462 |
the extra storage initialized to zero. |
|---|
| 463 |
|
|---|
| 464 |
<h3>Dynamic Initialization of Structs</h3> |
|---|
| 465 |
|
|---|
| 466 |
$(P Structs can be dynamically initialized from another |
|---|
| 467 |
value of the same type:) |
|---|
| 468 |
|
|---|
| 469 |
---- |
|---|
| 470 |
struct S { int a; } |
|---|
| 471 |
S t; // default initialized |
|---|
| 472 |
t.a = 3; |
|---|
| 473 |
S s = t; // s.a is set to 3 |
|---|
| 474 |
---- |
|---|
| 475 |
|
|---|
| 476 |
$(P If $(TT opCall) is overridden for the struct, and the struct |
|---|
| 477 |
is initialized with a value that is of a different type, |
|---|
| 478 |
then the $(TT opCall) operator is called:) |
|---|
| 479 |
|
|---|
| 480 |
---- |
|---|
| 481 |
struct S |
|---|
| 482 |
{ int a; |
|---|
| 483 |
|
|---|
| 484 |
static S $(B opCall)(int v) |
|---|
| 485 |
{ S s; |
|---|
| 486 |
s.a = v; |
|---|
| 487 |
return s; |
|---|
| 488 |
} |
|---|
| 489 |
|
|---|
| 490 |
static S $(B opCall)(S v) |
|---|
| 491 |
{ S s; |
|---|
| 492 |
s.a = v.a + 1; |
|---|
| 493 |
return s; |
|---|
| 494 |
} |
|---|
| 495 |
} |
|---|
| 496 |
|
|---|
| 497 |
S s = 3; // sets s.a to 3 |
|---|
| 498 |
S t = s; // sets t.a to 3, S.$(B opCall)(s) is not called |
|---|
| 499 |
---- |
|---|
| 500 |
|
|---|
| 501 |
<h3>$(LNAME2 StructLiteral, Struct Literals)</h3> |
|---|
| 502 |
|
|---|
| 503 |
$(P Struct literals consist of the name of the struct followed |
|---|
| 504 |
by a parenthesized argument list:) |
|---|
| 505 |
|
|---|
| 506 |
--- |
|---|
| 507 |
struct S { int x; float y; } |
|---|
| 508 |
|
|---|
| 509 |
int foo(S s) { return s.x; } |
|---|
| 510 |
|
|---|
| 511 |
foo( S(1, 2) ); // set field x to 1, field y to 2 |
|---|
| 512 |
--- |
|---|
| 513 |
|
|---|
| 514 |
$(P Struct literals are syntactically like function calls. |
|---|
| 515 |
If a struct has a member function named $(CODE opCall), then |
|---|
| 516 |
struct literals for that struct are not possible. |
|---|
| 517 |
It is an error if there are more arguments than fields of |
|---|
| 518 |
the struct. |
|---|
| 519 |
If there are fewer arguments than fields, the remaining |
|---|
| 520 |
fields are initialized with their respective default |
|---|
| 521 |
initializers. |
|---|
| 522 |
If there are anonymous unions in the struct, only the first |
|---|
| 523 |
member of the anonymous union can be initialized with a |
|---|
| 524 |
struct literal, and all subsequent non-overlapping fields are default |
|---|
| 525 |
initialized. |
|---|
| 526 |
) |
|---|
| 527 |
|
|---|
| 528 |
<h3>Struct Properties</h3> |
|---|
| 529 |
|
|---|
| 530 |
$(TABLE2 Struct Properties, |
|---|
| 531 |
$(TR $(TD .sizeof) $(TD Size in bytes of struct)) |
|---|
| 532 |
$(TR $(TD .alignof) $(TD Size boundary struct needs to be aligned on)) |
|---|
| 533 |
$(TR $(TD .tupleof) $(TD Gets type tuple of fields)) |
|---|
| 534 |
) |
|---|
| 535 |
|
|---|
| 536 |
<h3>Struct Field Properties</h3> |
|---|
| 537 |
|
|---|
| 538 |
$(TABLE2 Struct Field Properties, |
|---|
| 539 |
$(TR $(TD .offsetof) $(TD Offset in bytes of field from beginning of struct)) |
|---|
| 540 |
) |
|---|
| 541 |
|
|---|
| 542 |
$(V2 |
|---|
| 543 |
$(SECTION3 <a name="ConstStruct">Const and Invariant Structs</a>, |
|---|
| 544 |
|
|---|
| 545 |
$(P A struct declaration can have a storage class of |
|---|
| 546 |
$(CODE const), $(CODE immutable) or $(CODE shared). It has an equivalent |
|---|
| 547 |
effect as declaring each member of the struct as |
|---|
| 548 |
$(CODE const), $(CODE immutable) or $(CODE shared). |
|---|
| 549 |
) |
|---|
| 550 |
|
|---|
| 551 |
---- |
|---|
| 552 |
const struct S { int a; int b = 2; } |
|---|
| 553 |
|
|---|
| 554 |
void main() |
|---|
| 555 |
{ |
|---|
| 556 |
S s = S(3); // initializes s.a to 3 |
|---|
| 557 |
S t; // initializes t.a to 0 |
|---|
| 558 |
t = s; // ok, t.a is now 3 |
|---|
| 559 |
t.a = 4; // error, t.a is const |
|---|
| 560 |
} |
|---|
| 561 |
---- |
|---|
| 562 |
) |
|---|
| 563 |
) |
|---|
| 564 |
|
|---|
| 565 |
$(V2 |
|---|
| 566 |
$(SECTION3 <a name="Struct-Constructor">Struct Constructors</a>, |
|---|
| 567 |
|
|---|
| 568 |
$(P Struct constructors are used to initialize an instance |
|---|
| 569 |
of a struct. |
|---|
| 570 |
The $(I ParameterList) may not be empty. |
|---|
| 571 |
Struct instances that are not instantiated with a constructor |
|---|
| 572 |
are default initialized to their $(CODE .init) value. |
|---|
| 573 |
) |
|---|
| 574 |
) |
|---|
| 575 |
) |
|---|
| 576 |
|
|---|
| 577 |
$(V2 |
|---|
| 578 |
$(SECTION3 <a name="StructPostblit">Struct Postblits</a>, |
|---|
| 579 |
|
|---|
| 580 |
$(GRAMMAR |
|---|
| 581 |
$(GNAME StructPostblit): |
|---|
| 582 |
$(B this(this)) $(LINK2 function.html#FunctionBody, $(I FunctionBody)) |
|---|
| 583 |
) |
|---|
| 584 |
|
|---|
| 585 |
$(P $(I Copy construction) is defined as initializing |
|---|
| 586 |
a struct instance from another struct of the same type. |
|---|
| 587 |
Copy construction is divided into two parts:) |
|---|
| 588 |
|
|---|
| 589 |
$(OL |
|---|
| 590 |
$(LI blitting the fields, i.e. copying the bits) |
|---|
| 591 |
$(LI running $(I postblit) on the result) |
|---|
| 592 |
) |
|---|
| 593 |
|
|---|
| 594 |
$(P The first part is done automatically by the language, |
|---|
| 595 |
the second part is done if a postblit function is defined |
|---|
| 596 |
for the struct. |
|---|
| 597 |
The postblit has access only to the destination struct object, |
|---|
| 598 |
not the source. |
|---|
| 599 |
Its job is to $(SINGLEQUOTE fix up) the destination as necessary, such as |
|---|
| 600 |
making copies of referenced data, incrementing reference counts, |
|---|
| 601 |
etc. For example: |
|---|
| 602 |
) |
|---|
| 603 |
|
|---|
| 604 |
--- |
|---|
| 605 |
struct S |
|---|
| 606 |
{ |
|---|
| 607 |
int[] a; // array is privately owned by this instance |
|---|
| 608 |
this(this) |
|---|
| 609 |
{ |
|---|
| 610 |
a = a.dup; |
|---|
| 611 |
} |
|---|
| 612 |
~this() |
|---|
| 613 |
{ |
|---|
| 614 |
delete a; |
|---|
| 615 |
} |
|---|
| 616 |
} |
|---|
| 617 |
--- |
|---|
| 618 |
|
|---|
| 619 |
) |
|---|
| 620 |
) |
|---|
| 621 |
|
|---|
| 622 |
$(V2 |
|---|
| 623 |
$(SECTION3 <a name="StructDestructor">Struct Destructors</a>, |
|---|
| 624 |
|
|---|
| 625 |
$(P Destructors are called when an object goes out of scope. |
|---|
| 626 |
Their purpose is to free up resources owned by the struct |
|---|
| 627 |
object. |
|---|
| 628 |
) |
|---|
| 629 |
) |
|---|
| 630 |
) |
|---|
| 631 |
|
|---|
| 632 |
$(V2 |
|---|
| 633 |
$(SECTION3 <a name="AssignOverload">Assignment Overload</a>, |
|---|
| 634 |
|
|---|
| 635 |
$(P While copy construction takes care of initializing |
|---|
| 636 |
an object from another object of the same type, |
|---|
| 637 |
assignment is defined as copying the contents of one |
|---|
| 638 |
object over another, already initialized, type: |
|---|
| 639 |
) |
|---|
| 640 |
|
|---|
| 641 |
--- |
|---|
| 642 |
struct S { ... } |
|---|
| 643 |
S s; // default construction of s |
|---|
| 644 |
S t = s; // t is copy-constructed from s |
|---|
| 645 |
t = s; // t is assigned from s |
|---|
| 646 |
--- |
|---|
| 647 |
|
|---|
| 648 |
$(P Struct assignment $(CODE t=s) is defined to be semantically |
|---|
| 649 |
equivalent to: |
|---|
| 650 |
) |
|---|
| 651 |
|
|---|
| 652 |
--- |
|---|
| 653 |
t = S.opAssign(s); |
|---|
| 654 |
--- |
|---|
| 655 |
|
|---|
| 656 |
$(P where $(CODE opAssign) is a member function of S:) |
|---|
| 657 |
|
|---|
| 658 |
--- |
|---|
| 659 |
S* opAssign(S s) |
|---|
| 660 |
{ ... bitcopy *this into tmp ... |
|---|
| 661 |
... bitcopy s into *this ... |
|---|
| 662 |
... call destructor on tmp ... |
|---|
| 663 |
return this; |
|---|
| 664 |
} |
|---|
| 665 |
--- |
|---|
| 666 |
|
|---|
| 667 |
$(P While the compiler will generate a default $(CODE opAssign) |
|---|
| 668 |
as needed, a user-defined one can be supplied. The user-defined |
|---|
| 669 |
one must still implement the equivalent semantics, but can |
|---|
| 670 |
be more efficient. |
|---|
| 671 |
) |
|---|
| 672 |
|
|---|
| 673 |
$(P One reason a custom $(CODE opAssign) might be more efficient |
|---|
| 674 |
is if the struct has a reference to a local buffer: |
|---|
| 675 |
) |
|---|
| 676 |
|
|---|
| 677 |
--- |
|---|
| 678 |
struct S |
|---|
| 679 |
{ |
|---|
| 680 |
int[] buf; |
|---|
| 681 |
int a; |
|---|
| 682 |
|
|---|
| 683 |
S* opAssign(ref const S s) |
|---|
| 684 |
{ |
|---|
| 685 |
a = s.a; |
|---|
| 686 |
return this; |
|---|
| 687 |
} |
|---|
| 688 |
|
|---|
| 689 |
this(this) |
|---|
| 690 |
{ |
|---|
| 691 |
buf = buf.dup; |
|---|
| 692 |
} |
|---|
| 693 |
|
|---|
| 694 |
~this() |
|---|
| 695 |
{ |
|---|
| 696 |
delete buf; |
|---|
| 697 |
} |
|---|
| 698 |
} |
|---|
| 699 |
--- |
|---|
| 700 |
|
|---|
| 701 |
$(P Here, $(CODE S) has a temporary workspace $(CODE buf[]). |
|---|
| 702 |
The normal postblit |
|---|
| 703 |
will pointlessly free and reallocate it. The custom $(CODE opAssign) |
|---|
| 704 |
will reuse the existing storage. |
|---|
| 705 |
) |
|---|
| 706 |
|
|---|
| 707 |
) |
|---|
| 708 |
) |
|---|
| 709 |
|
|---|
| 710 |
$(V2 |
|---|
| 711 |
<h2>$(LNAME2 nested, Nested Structs)</h2> |
|---|
| 712 |
|
|---|
| 713 |
$(P A $(I nested struct) is a struct that is declared inside the scope |
|---|
| 714 |
of a function or a templated struct that has aliases to local |
|---|
| 715 |
functions as a template argument. |
|---|
| 716 |
Nested structs have member functions. |
|---|
| 717 |
It has access to the context of its enclosing scope |
|---|
| 718 |
(via an added hidden field). |
|---|
| 719 |
) |
|---|
| 720 |
|
|---|
| 721 |
--- |
|---|
| 722 |
void foo() |
|---|
| 723 |
{ int i = 7; |
|---|
| 724 |
struct SS |
|---|
| 725 |
{ |
|---|
| 726 |
int x,y; |
|---|
| 727 |
int bar() { return x + i + 1; } |
|---|
| 728 |
} |
|---|
| 729 |
SS s; |
|---|
| 730 |
s.x = 3; |
|---|
| 731 |
s.bar(); // returns 11 |
|---|
| 732 |
} |
|---|
| 733 |
--- |
|---|
| 734 |
|
|---|
| 735 |
$(P Nested structs cannot be used as fields or as the |
|---|
| 736 |
element type of an array: |
|---|
| 737 |
) |
|---|
| 738 |
|
|---|
| 739 |
--- |
|---|
| 740 |
void foo() |
|---|
| 741 |
{ int i = 7; |
|---|
| 742 |
struct SS |
|---|
| 743 |
{ |
|---|
| 744 |
int x,y; |
|---|
| 745 |
int bar() { return x + i + 1; } |
|---|
| 746 |
} |
|---|
| 747 |
struct DD |
|---|
| 748 |
{ |
|---|
| 749 |
SS s; // error, cannot be field |
|---|
| 750 |
} |
|---|
| 751 |
SS[3] a; // error, cannot be array element |
|---|
| 752 |
SS[] a; // error, cannot be array element |
|---|
| 753 |
} |
|---|
| 754 |
--- |
|---|
| 755 |
|
|---|
| 756 |
$(P A struct can be prevented from being nested by |
|---|
| 757 |
using the static attribute, but then of course it |
|---|
| 758 |
will not be able to access variables from its enclosing |
|---|
| 759 |
scope.) |
|---|
| 760 |
|
|---|
| 761 |
--- |
|---|
| 762 |
void foo() |
|---|
| 763 |
{ int i = 7; |
|---|
| 764 |
$(B static) struct SS |
|---|
| 765 |
{ |
|---|
| 766 |
int x,y; |
|---|
| 767 |
int bar() |
|---|
| 768 |
{ |
|---|
| 769 |
return i; // error, SS is not a nested struct |
|---|
| 770 |
} |
|---|
| 771 |
} |
|---|
| 772 |
} |
|---|
| 773 |
--- |
|---|
| 774 |
|
|---|
| 775 |
$(P A templated struct can become a nested struct if it |
|---|
| 776 |
has a local function passed as an aliased argument: |
|---|
| 777 |
) |
|---|
| 778 |
|
|---|
| 779 |
--- |
|---|
| 780 |
struct A(alias F) |
|---|
| 781 |
{ |
|---|
| 782 |
int fun(int i) { return F(i); } |
|---|
| 783 |
} |
|---|
| 784 |
|
|---|
| 785 |
A!(F) makeA(alias F)() {return A!(F)(); } |
|---|
| 786 |
|
|---|
| 787 |
void main() |
|---|
| 788 |
{ |
|---|
| 789 |
int x = 40; |
|---|
| 790 |
int fun(int i) { return x + i; } |
|---|
| 791 |
A!(fun) a = makeA!(fun)(); |
|---|
| 792 |
a.fun(2); |
|---|
| 793 |
} |
|---|
| 794 |
--- |
|---|
| 795 |
) |
|---|
| 796 |
|
|---|
| 797 |
) |
|---|
| 798 |
|
|---|
| 799 |
Macros: |
|---|
| 800 |
TITLE=Structs, Unions |
|---|
| 801 |
WIKI=Struct |
|---|
| 802 |
NO=$(TD ) |
|---|
| 803 |
YES=$(TD X) |
|---|
| 804 |
GLINK=$(LINK2 #$0, $(I $0)) |
|---|
| 805 |
GNAME=<a name=$0>$(I $0)</a> |
|---|
| 806 |
FOO= |
|---|