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;
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