可変個型引数あれこれ
昨日のちょっと修正。
char[] ToString(T1, T2, TA...)(T1 value1, T2 value2, TA values) { const char[] delim = ", "; char[] buffer = ToString(value1) ~ delim ~ ToString(value2); foreach (v; values) { buffer ~= delim; buffer ~= ToString(v); } return buffer; }
あとですねぇ。
可変個型引数を使って型コンテナを実装しようとしたんだが、どーもウマくいかん。
class TypeArray(TA...) { const int length = TA.length; template typeAt(int n) { alias TA[n] typeAt; } }
これでできればサイコーである。シンプルで美しい(自賛)。
だがそーはいかない。
alias TypeArray!(int, char, double) Types3; writefln(typeid(Types3)); writefln(Types3.length); writefln(typeid(Types3.typeAt!(0))); writefln(typeid(Types3.typeAt!(1))); writefln(typeid(Types3.typeAt!(2))); ... TypeArray 3 TypeInfo[0] TypeInfo[1] TypeInfo[2]
こんな具合。
つまり、ここで言う TA ってのは型の配列ではなく、TypeInfo の配列なのね。欲しいのは型情報ではなく型だ。
納得いかんのでもそっと試してみた。
void testTypes(TA...)(TA values) { foreach (v; values) { writefln(typeid(typeof(v))); } writefln(values.length); writefln(typeid(typeof(values[0]))); writefln(typeid(typeof(values[1]))); writefln(typeid(typeof(values[2]))); } void main() { testTypes(1, 3.14, "ABC"); } ... int double char[3] 3 int double char[3]
よかですね。このように型引数ではなく、引数の typeof を取るとウマくいく。
但し、
writefln(typeid(typeof(values)));
とやると、
Assertion failure: '0' on line 4601 in file 'mtype.c'
となる。
では、型引数の方にアクセスしてみるとどうか?
writefln(TA.length); writefln(typeid(TA)); writefln(typeid(TA[0])); writefln(typeid(TA[1])); writefln(typeid(TA[2])); ... 3 TypeInfo TypeInfo[0] TypeInfo[1] TypeInfo[2]
ダメですな。
引数から型を取ることはできるが、型引数からはとれない。
関数テンプレートの場合、型引数だけでなくホントの引数も取るので、関数内で型情報を取れる。
しかし
alias TypeArray!(int, char, double) Types3;
てった具合に型だけからインスタンス化した場合、テンプレート内で可変個型引数を使って型を取得できない。
可変個型引数は便利だけど、今んとこ威力を発揮すんの関数テンプレートだけだなぁ。
やはり、羅列型で書いたナサケナな TypeArray を再帰を使って書くぐらいが関の山のようである。