文字列化関数(もう変えない)


構造体だろうが連想配列だろうが何でも文字列化するための関数テンプレートだが、今後とも使用すること多いので、最新版をあげておく。


完全版とは言い難く、static if なんかで分岐するよりも、同名のディスパッチで分けるもんだろうが、本人不都合はないし、一箇所にまとまってた方が本人わかりやすいので、現状これ以上変えるつもりはない。


契約の部分が解りにくいですが、例えば function だったら、

function なのに
型が char[](*)() ではない
ということがあってはならない

という意味です。


これも複数条件をひとつにまとめられるとこあるのは解ってますが、各型に対するのを各自の条件にしてます。

module house.tostring;

private import std.string;

template ToString(T) {
	char[] ToString(T value)
		in {
			static assert (!(
				 is (T == function)  &&
				!is (T == char[](*)())
			));
			static assert (!(
				 is (T == delegate)  &&
				!is (T == char[] delegate())
			));
			static assert (!(
				 is (T == union)	   &&
				!is (typeof(T.toString))
			));
			static assert (!(
				 is (T == struct)	   &&
				!is (typeof(T.toString))
			));
			static assert (!(
				 is (T == interface) &&
				!is (typeof(T.toString))
			));
		}
		body {
			static		if (is (T : char[]))
				return value;

			else static if (is (T == char[](*)()))
				return value();

			else static if (is (T == char[] delegate()))
				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.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) ~ ",";
		if (array.length > 0) 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) ~ ",";
		if (array.length > 0) 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 ~= "),";
		}
		if (map.length > 0) buffer = chop(buffer);
		buffer ~= "]";
		return buffer;
	}
}