Skip to content

Commit 2fa467e

Browse files
authored
Merge pull request #3158 from ntrel/cast-expr
[expression.dd] Improve *CastExpression* docs Signed-off-by: Dennis <dkorpel@users.noreply.github.com> Merged-on-behalf-of: Dennis <dkorpel@users.noreply.github.com>
2 parents c015dd8 + b442408 commit 2fa467e

File tree

1 file changed

+65
-36
lines changed

1 file changed

+65
-36
lines changed

spec/expression.dd

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,34 +1073,42 @@ $(H3 $(LNAME2 cast_expressions, Cast Expressions))
10731073
$(GRAMMAR
10741074
$(GNAME CastExpression):
10751075
$(D cast $(LPAREN)) $(GLINK2 type, Type) $(D $(RPAREN)) $(GLINK UnaryExpression)
1076-
$(D cast $(LPAREN)) $(GLINK2 type, TypeCtors)$(OPT) $(D $(RPAREN)) $(GLINK UnaryExpression)
1076+
$(GLINK CastQual)
10771077
)
10781078

10791079
$(P A $(I CastExpression) converts the $(I UnaryExpression)
1080-
to $(GLINK2 type, Type).)
1080+
to $(I Type).)
10811081

10821082
-------------
10831083
cast(foo) -p; // cast (-p) to type foo
10841084
(foo) - p; // subtract p from foo
10851085
-------------
10861086

1087+
$(H4 $(LNAME2 cast_class, Class References))
1088+
10871089
$(P Any casting of a class reference to a
10881090
derived class reference is done with a runtime check to make sure it
10891091
really is a downcast. $(D null) is the result if it isn't.
10901092
)
10911093

1094+
$(SPEC_RUNNABLE_EXAMPLE_RUN
10921095
-------------
1093-
class A { ... }
1094-
class B : A { ... }
1096+
class A {}
1097+
class B : A {}
10951098

1096-
void test(A a, B b)
1099+
void main()
10971100
{
1098-
B bx = a; // error, need cast
1099-
B bx = cast(B) a; // bx is null if a is not a B
1100-
A ax = b; // no cast needed
1101-
A ax = cast(A) b; // no runtime check needed for upcast
1101+
A a = new A;
1102+
//B b = a; // error, need cast
1103+
B b = cast(B) a; // b is null if a is not a B
1104+
assert(b is null);
1105+
1106+
a = b; // no cast needed
1107+
a = cast(A) b; // no runtime check needed for upcast
1108+
assert(a is b);
11021109
}
11031110
-------------
1111+
)
11041112

11051113
$(P In order to determine if an object $(D o) is an instance of
11061114
a class $(D B) use a cast:)
@@ -1120,52 +1128,54 @@ $(GNAME CastExpression):
11201128
(i.e. a reinterpret cast).
11211129
)
11221130

1131+
$(H4 $(LNAME2 cast_array, Arrays))
1132+
11231133
$(P Casting a dynamic array to another dynamic array is done only if the
11241134
array lengths multiplied by the element sizes match. The cast is done
11251135
as a type paint, with the array length adjusted to match any change in
11261136
element size. If there's not a match, a runtime error is generated.)
11271137

1128-
---
1129-
import std.stdio;
1130-
1131-
int main()
1132-
{
1138+
$(SPEC_RUNNABLE_EXAMPLE_RUN
1139+
---
11331140
byte[] a = [1,2,3];
1134-
auto b = cast(int[])a; // runtime array cast misalignment
1141+
//auto b = cast(int[])a; // runtime error: array cast misalignment
11351142

11361143
int[] c = [1, 2, 3];
11371144
auto d = cast(byte[])c; // ok
11381145
// prints:
11391146
// [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0]
11401147
writeln(d);
1141-
return 0;
1142-
}
1143-
---
1148+
---
1149+
)
1150+
1151+
$(DDOC_SEE_ALSO $(RELATIVE_LINK2 cast_array_literal, Casting array literals).)
11441152

1153+
$(H4 $(LNAME2 cast_static_array, Static Arrays))
11451154

11461155
$(P Casting a static array to another static array is done only if the
11471156
array lengths multiplied by the element sizes match; a mismatch
11481157
is illegal.
11491158
The cast is done as a type paint (aka a reinterpret cast).
11501159
The contents of the array are not changed.)
11511160

1152-
---
1153-
import core.stdc.stdio;
1154-
1155-
void main()
1156-
{
1157-
byte[16] b = 3;
1161+
$(SPEC_RUNNABLE_EXAMPLE_RUN
1162+
---
1163+
byte[16] b = 3; // set each element to 3
1164+
assert(b[0] == 0x03);
11581165
int[4] ia = cast(int[4]) b;
1166+
// print elements as hex
11591167
foreach (i; ia)
1160-
printf("%x\n", i);
1168+
writefln("%x", i);
11611169
/* prints:
11621170
3030303
11631171
3030303
11641172
3030303
11651173
3030303
11661174
*/
1167-
}
1168-
---
1175+
---
1176+
)
1177+
1178+
$(H4 $(LNAME2 cast_floating, Floating Point))
11691179

11701180
$(P Casting a floating point literal from one type to another
11711181
changes its type, but internally it is retained at full
@@ -1217,40 +1227,55 @@ $(GNAME CastExpression):
12171227
}
12181228
---
12191229

1230+
$(H4 $(LNAME2 cast_struct, Structs))
1231+
12201232
$(P Casting a value $(I v) to a struct $(I S), when value is not a struct
12211233
of the same type, is equivalent to:)
12221234

12231235
---
12241236
S(v)
12251237
---
12261238

1227-
$(P Casting to a $(GLINK CastQual) replaces the qualifiers to the type of
1228-
the $(GLINK UnaryExpression).)
1239+
$(H4 $(LNAME2 cast_qualifier, Qualifier Cast))
1240+
1241+
$(GRAMMAR
1242+
$(GNAME CastQual):
1243+
$(D cast $(LPAREN)) $(GLINK2 type, TypeCtors)$(OPT) $(D $(RPAREN)) $(GLINK UnaryExpression)
1244+
)
12291245

1246+
$(P A $(I CastQual) replaces the qualifiers in the type of
1247+
the $(I UnaryExpression):)
1248+
1249+
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
12301250
---
12311251
shared int x;
1232-
assert(is(typeof(cast(const)x) == const int));
1252+
static assert(is(typeof(cast(const)x) == const int));
12331253
---
1254+
)
12341255

1235-
$(P Casting with no $(GLINK2 type, Type) or $(GLINK CastQual) removes
1256+
$(P Casting with no type or qualifiers removes
12361257
any top level $(D const), $(D immutable), $(D shared) or $(D inout)
12371258
type modifiers from the type
1238-
of the $(GLINK UnaryExpression).)
1259+
of the $(I UnaryExpression).)
12391260

1261+
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
12401262
---
12411263
shared int x;
1242-
assert(is(typeof(cast()x) == int));
1264+
static assert(is(typeof(cast()x) == int));
12431265
---
1266+
)
1267+
1268+
$(H4 $(LNAME2 cast_void, Casting to `void`))
12441269

12451270
$(P Casting an expression to $(D void) type is allowed to mark that
12461271
the result is unused. On $(GLINK2 statement, ExpressionStatement),
1247-
it could be used properly to avoid "has no effect" error.)
1272+
it could be used properly to avoid a "has no effect" error.)
12481273

12491274
----
12501275
void foo(lazy void exp) {}
12511276
void main()
12521277
{
1253-
foo(10); // NG - has no effect in expression '10'
1278+
foo(10); // NG - expression '10' has no effect
12541279
foo(cast(void)10); // OK
12551280
}
12561281
----
@@ -1644,11 +1669,14 @@ $(GNAME ArrayLiteral):
16441669
}
16451670
---
16461671

1672+
$(H3 $(LNAME2 cast_array_literal, Casting))
1673+
16471674
$(P When array literals are cast to another array type, each
16481675
element of the array is cast to the new element type.
1649-
When arrays that are not literals are cast, the array is
1676+
When arrays that are not literals $(RELATIVE_LINK2 cast_array, are cast), the array is
16501677
reinterpreted as the new type, and the length is recomputed:)
16511678

1679+
$(SPEC_RUNNABLE_EXAMPLE_RUN
16521680
---
16531681
import std.stdio;
16541682

@@ -1667,6 +1695,7 @@ $(GNAME ArrayLiteral):
16671695
writeln(rt); // writes [257]
16681696
}
16691697
---
1698+
)
16701699

16711700
In other words, casting an array literal will change the type of each initializer element.
16721701

0 commit comments

Comments
 (0)