文字列化できた
文字列化できる型の文字列化テンプレートがようやくできた。
template ToString(T) { char ToString(T value) in { static assert (!(is (T == union))); static assert (!(is (T == function))); static assert (!(is (T == delegate))); } body { static if (is (T : char)) return value; else static if ( is (typeof(T.toString) == typeof(Object.toString)) ) return value.toString(); else static if (is (typeof(T.init.keys))) return MapToString!( typeof(T.init.keys[0]), typeof(T.init.values[0]) )(value); else static if (is (typeof(T.init)[(T).length])) return ArrayToString!( typeof(*T.ptr), (T).length)(value) ); else static if (is (typeof(T.init.ptr))) return ArrayToString!(typeof(*T.init.ptr))(value); else return std.string.toString(value); } } template ArrayToString(T) { char ArrayToString(T[ ] array) { char buffer = "["; foreach(T value; array) buffer ~= ToString!(T)(value) ~ ","; buffer = chop(buffer); buffer ~= "]"; return buffer; } } template ArrayToString(T, uint N) { char ArrayToString(T[N] array) { char buffer = "["; foreach(T value; array) buffer ~= ToString!(T)(value) ~ ","; buffer = chop(buffer); buffer ~= "]"; return buffer; } } template MapToString(Key, T) { char MapToString (T[Key] map) { char buffer = "["; foreach(Key key, T value; map) { buffer ~= "("; buffer ~= ToString!(Key)(key); buffer ~= ":"; buffer ~= ToString!(T )(value); buffer ~= "),"; } buffer = chop(buffer); buffer ~= "]"; return buffer; } }
改良点:
・toString の型チェック
・静的配列の文字列化の型パラメータを typeof(T.init) -> typeof(*T.ptr) に変更
writefln("type = %-12s, init = %-12s, ptr = %-12s", typeid(T), typeid(typeof(T.init)), typeid(typeof(T.ptr)));
といったテンプレートを書いてみて解ったのだが、配列宣言の外側が定数サイズだと、initの次元が1つ減るのだ。int[3][2]といった2次元とも固定長の配列だと、initの型は int になってしまう。これが、2/14版でうまくいかなかった理由。
これでようやく文字列化できるものは全て ToString!(typeof(val))(val)でできるようになった。ふひ〜。