@@ -183,14 +183,19 @@ $(H3 C++ $(LNAME2 namespace, Namespaces))
183
183
184
184
$(P Namespaces create a new named scope that is imported into its enclosing scope.)
185
185
186
+ $(SPEC_RUNNABLE_EXAMPLE_COMPILE
186
187
---
187
188
extern (C++, N) { void foo(); void bar(); }
188
189
extern (C++, M) { void foo(); }
189
190
190
- bar(); // ok
191
- foo(); // error - N.foo() or M.foo() ?
192
- M.foo(); // ok
191
+ void main()
192
+ {
193
+ bar(); // ok
194
+ //foo(); // error - N.foo() or M.foo() ?
195
+ M.foo(); // ok
196
+ }
193
197
---
198
+ )
194
199
195
200
$(P Multiple identifiers in the $(I QualifiedIdentifier) create nested namespaces:)
196
201
@@ -373,16 +378,23 @@ $(GNAME DeprecatedAttribute):
373
378
$(P Calling CTFE-able functions or using manifest constants is also possible.
374
379
)
375
380
381
+ $(SPEC_RUNNABLE_EXAMPLE_COMPILE
376
382
---------------
377
383
import std.format;
378
- enum Message = format("%s and all its members are obsolete", Foobar.stringof);
379
- deprecated(Message) class Foobar {}
380
- auto f = new Foobar(); // Deprecated: class test.Foobar is deprecated - Foobar
381
- // and all its members are obsolete
384
+
385
+ enum message = format("%s and all its members are obsolete", Foobar.stringof);
386
+ deprecated(message) class Foobar {}
382
387
deprecated(format("%s is also obsolete", "This class")) class BarFoo {}
383
- auto bf = new BarFoo(); // Deprecated: class test.BarFoo is deprecated - This
384
- // class is also obsolete
388
+
389
+ void main()
390
+ {
391
+ auto fb = new Foobar(); // Deprecated: class test.Foobar is deprecated - Foobar
392
+ // and all its members are obsolete
393
+ auto bf = new BarFoo(); // Deprecated: class test.BarFoo is deprecated - This
394
+ // class is also obsolete
395
+ }
385
396
---------------
397
+ )
386
398
387
399
$(P $(D Implementation Note:) The compiler should have a switch
388
400
specifying if $(D deprecated) should be ignored, cause a warning, or cause an error during compilation.
733
745
$(LI Putting a `scope` variable in an array literal)
734
746
)
735
747
$(P
736
- The `scope` attribute is part of the variable declaration, not of the type, and it only applies to the first level of indirection.
748
+ The `scope` attribute is part of the variable declaration, not the type, and it only applies to the first level of indirection.
737
749
For example, it is impossible to declare a variable as a dynamic array of scope pointers, because `scope` only applies to the `.ptr`
738
750
of the array itself, not its elements. `scope` affects various types as follows:
739
751
)
@@ -772,6 +784,8 @@ string escape(scope S s, scope S* sPtr, scope string[2] sarray, scope string[] d
772
784
}
773
785
---
774
786
787
+ $(H3 $(LNAME2 scope-values, Scope Values))
788
+
775
789
$(P
776
790
A "`scope` value" is the value of a `scope` variable, or a generated value pointing to stack allocated memory.
777
791
Such values are generated by $(DDSUBLINK spec/arrays, slicing, slicing) a static array
@@ -814,6 +828,14 @@ void variadic(int[] a...)
814
828
int[] x = a; // inferred `scope int[]`
815
829
}
816
830
831
+ void main()
832
+ {
833
+ variadic(1, 2, 3);
834
+ }
835
+ ---
836
+
837
+ $(SPEC_RUNNABLE_EXAMPLE_COMPILE
838
+ ---
817
839
struct S
818
840
{
819
841
int x;
@@ -826,6 +848,7 @@ struct S
826
848
}
827
849
}
828
850
---
851
+ )
829
852
830
853
$(P
831
854
$(DDSUBLINK spec/function, scope-parameters, Scope Parameters) are treated the same as scope local variables,
@@ -857,21 +880,29 @@ $(P
857
880
proper destruction of the variable.
858
881
)
859
882
883
+ $(SPEC_RUNNABLE_EXAMPLE_COMPILE
860
884
---
861
- class C {}
885
+ import core.stdc.stdio : puts;
886
+
887
+ class C
888
+ {
889
+ ~this() @nogc { puts(__FUNCTION__); }
890
+ }
862
891
863
892
void main() @nogc
864
893
{
865
894
{
866
895
scope c0 = new C(); // allocated on the stack
867
896
scope c1 = new C();
868
897
869
- c1 = c0; // not allowed
898
+ // c1 = c0; // Error: cannot rebind scope variables
870
899
871
900
// destructor of `c1` and `c0` are called here in that order
872
901
}
902
+ puts("bye");
873
903
}
874
904
---
905
+ )
875
906
876
907
877
908
$(H2 $(LNAME2 class-attributes, Class Attributes))
@@ -1025,6 +1056,7 @@ pragma(msg, __traits(getAttributes, s)); // prints tuple('c')
1025
1056
The expression tuple can be turned into a manipulatable tuple:
1026
1057
)
1027
1058
1059
+ $(SPEC_RUNNABLE_EXAMPLE_COMPILE
1028
1060
---
1029
1061
enum EEE = 7;
1030
1062
@("hello") struct SSS { }
@@ -1034,7 +1066,10 @@ alias TP = __traits(getAttributes, foo);
1034
1066
1035
1067
pragma(msg, TP); // prints tuple(3, 4, 7, (SSS))
1036
1068
pragma(msg, TP[2]); // prints 7
1069
+
1070
+ void main() {}
1037
1071
---
1072
+ )
1038
1073
1039
1074
$(P
1040
1075
Of course the tuple types can be used to declare things:
@@ -1065,12 +1100,15 @@ pragma(msg, __traits(getAttributes, typeof(a))); // prints tuple("hello")
1065
1100
interprets them.
1066
1101
)
1067
1102
1103
+ $(H3 $(LNAME2 uda-templates, Templates))
1104
+
1068
1105
$(P
1069
1106
If a UDA is attached to a template declaration, then it will be automatically
1070
1107
attached to all direct members of instances of that template. If any of those
1071
1108
members are templates themselves, this rule applies recursively:
1072
1109
)
1073
1110
1111
+ $(SPEC_RUNNABLE_EXAMPLE_COMPILE
1074
1112
---
1075
1113
@("foo") template Outer(T)
1076
1114
{
@@ -1098,7 +1136,10 @@ pragma(msg, __traits(getAttributes, Outer!int.Inner));
1098
1136
// prints tuple("foo", "bar")
1099
1137
pragma(msg, __traits(getAttributes, Outer!int.Inner!int.z));
1100
1138
// prints tuple("foo", "bar")
1139
+
1140
+ void main() {}
1101
1141
---
1142
+ )
1102
1143
1103
1144
$(P
1104
1145
UDAs cannot be attached to template parameters.
0 commit comments