@@ -566,6 +566,100 @@ $(GNAME Postblit):
566
566
}
567
567
---
568
568
569
+ $(P Depending on the struct layout, the compiler may generate the following
570
+ internal postblits:)
571
+
572
+ $(OL
573
+ $(LI `__postblit`. The compiler assigns this name to the explicitly
574
+ defined postblit `this(this)` so that it can be treated exactly as
575
+ a normal function. Note that if a struct defines a postblit, it cannot
576
+ define a function named `__postblit` - no matter the signature -
577
+ as this will result in a compilation error due to the name conflict.)
578
+ $(LI `__fieldPostblit`. If a struct `X` has at least 1 member which is a
579
+ struct that defines a postblit, then a field postblit is generated
580
+ for `X` that calls all the underlying postblits of the struct fields
581
+ in topological order.)
582
+ $(LI `__aggrPostblit`. If a struct has an explicitly defined postblit
583
+ and at least 1 struct member that has a postblit (any type of postblit)
584
+ an aggregated postblit is generated which calls `__fieldPostblit` first
585
+ and then `__postblit`.)
586
+ $(LI `__xpostblit`. The field and aggregated postblits, although generated
587
+ for a struct, are not actual struct members. In order to be able to call
588
+ them, the compiler internally creates an alias, called `__xpostblit` which
589
+ is a member of the struct and which points to the generated postblit that
590
+ is the most inclusive.)
591
+ )
592
+
593
+ ($SPEC_RUNNABLE_EXAMPLE_COMPILE
594
+ ---
595
+ // struct with alias __xpostblit = __postblit
596
+ struct X
597
+ {
598
+ this(this) {}
599
+ }
600
+
601
+ // struct with alias __xpostblit = __fieldPostblit
602
+ // which contains a call to X.__xpostblit
603
+ struct Y
604
+ {
605
+ X a;
606
+ }
607
+
608
+ // struct with alias __xpostblit = __aggrPostblit which contains
609
+ // a call to Y.__xpostblit and a call to Z.__postblit
610
+ struct Z
611
+ {
612
+ Y a;
613
+ this(this) {}
614
+ }
615
+
616
+ void main()
617
+ {
618
+ // X has __postblit and __xpostblit (pointing to __postblit)
619
+ static assert(__traits(hasMember, X, "__postblit"));
620
+ static assert(__traits(hasMember, X, "__xpostblit"));
621
+
622
+ // Y does not have __postblit, but has __xpostblit (pointing to __fieldPostblit)
623
+ static assert(!__traits(hasMember, Y, "__postblit"));
624
+ static assert(__traits(hasMember, Y, "__xpostblit"));
625
+ // __fieldPostblit is not a member of the struct
626
+ static assert(!__traits(hasMember, Y, "__fieldPostblit"));
627
+
628
+ // Z has __postblit and __xpostblit (pointing to __aggrPostblit)
629
+ static assert(__traits(hasMember, Z, "__postblit"));
630
+ static assert(__traits(hasMember, Z, "__xpostblit"));
631
+ // __aggrPostblit is not a member of the struct
632
+ static assert(!__traits(hasMember, Z, "__aggrPostblit"));
633
+ }
634
+ ---
635
+ )
636
+
637
+ $(P Neither of the above postblits is defined for structs that don't
638
+ define `this(this)` and don't have fields that transitively define it.
639
+ Example:)
640
+
641
+ ($SPEC_RUNNABLE_EXAMPLE_COMPILE
642
+ ---
643
+ struct X
644
+ {}
645
+
646
+ struct Y
647
+ {
648
+ int a;
649
+ X b;
650
+ }
651
+
652
+ void main()
653
+ {
654
+ static assert(!__traits(hasMember, X, "__postblit"));
655
+ static assert(!__traits(hasMember, X, "__xpostblit"));
656
+
657
+ static assert(!__traits(hasMember, Y, "__postblit"));
658
+ static assert(!__traits(hasMember, Y, "__xpostblit"));
659
+ }
660
+ ---
661
+ )
662
+
569
663
$(P Unions may not have fields that have postblits.)
570
664
571
665
$(H2 $(LEGACY_LNAME2 StructDestructor, struct-destructor, Struct Destructors))
0 commit comments