文字列化できた

文字列化できる型の文字列化テンプレートがようやくできた。

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)でできるようになった。ふひ〜。