D言語のcast
D言語で型変換したかったら基本は std.conv.to
使うのが安全である。
import std.conv; void main() { int a = 1; long b = a.to!long; assert(b == 1); }
std.conv.toは安全であるが、安全であるということは制約が強いということでもある。例えば以下のコードはOverflowを検知し例外を投げる。
import std.conv : to; void main() { auto a = -11; // int ulong b = a.to!ulong; }
$ rdmd -fPIC to.d std.conv.ConvOverflowException@/home/kubo39/dlang/dmd-2.072.1/linux/bin64/../../src/phobos/std/conv.d(445): Conversion negative overflow ---------------- ??:? pure @safe bool std.exception.enforce!(bool).enforce(bool, lazy object.Throwable) [0xde158fb2] ??:? pure @safe ulong std.conv.toImpl!(ulong, int).toImpl(int) [0xde158f34] ??:? pure @safe ulong std.conv.to!(ulong).to!(int).to(int) [0xde158f00] ??:? _Dmain [0xde158ef0] ??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [0x6dda5387] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x6dda52b3] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x6dda532c] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x6dda52b3] ??:? _d_run_main [0x6dda5217] ??:? main [0xde159047] ??:? __libc_start_main [0x6d5413f0]
こういうことがやりたいときもたまにあって、そういうときは cast
を使う。
import std.stdio; void main() { auto a = -1; uint b = cast(uint) a; b.writeln; }
castは危険な操作を許容する。例えば以下のようなコードはコンパイルが通り、未定義動作となる。
void main() { ubyte[4] arr = [0, 1, 0, 0]; auto ptr = cast(uint*) arr.ptr; assert(*ptr == 256); auto ptr2 = cast(ulong*) ptr; import std.stdio; (*ptr2).writeln; // 未定義 }
(dmd-2.072.1)( ՞ਊ ՞) :~/dev/misc $ rdmd -fPIC cast.d 139972984176896 (dmd-2.072.1)( ՞ਊ ՞) :~/dev/misc $ rdmd -fPIC cast.d 140411070841088 (dmd-2.072.1)( ՞ਊ ՞) :~/dev/misc $ rdmd -fPIC cast.d 140045998620928 (dmd-2.072.1)( ՞ਊ ՞) :~/dev/misc $ rdmd -fPIC cast.d 256