Modern C++ Design(Loki)のTypeList(これは古い日記です)

今日の日記はModern C++ Designを読んだ人とかLoki(Modern C++ Designで解説されているライブラリ)を使ったことのある人しか意味がわからないと思うのでご了承ください。

Modern C++ Designでは、型のリスト「TypeList」を可変長に扱うため、TYPELIST_1 〜 TYPELIST_50まで、要素の数に応じたマクロを用いることで対応している。つまり、

#define TYPELIST_1(T1) Typelist<T1, NullType>
#define TYPELIST_2(T1, T2) Typelist<T1, TYPELIST_1(T2)>
#define TYPELIST_3(T1, T2, T3) Typelist<T1, TYPELIST_2(T2, T3)>
// ...
#define TYPELIST_50(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
        T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) \
    Typelist<T1, TYPELIST_49(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
        T41, T42, T43, T44, T45, T46, T47, T48, T49, T50)>

こういった感じで、要素数50までに対応している。

これによって、

typedef TypeList<a, TypeList<b, TypeList<c, TypeList<d, TypeList<e, NullType> > > > > List5;

typedef TYPELIST_5(a, b, c, d, e) List5;

と書けるようになる。

しかし、C++的にはマクロは敵なので、できれば排除すべきだ。

で、ちょっとtemplateを使ったプログラムを書いていたら、このマクロは消すことができることに気付いた。ためしに書いてみたらちゃんと動くようだ。Modern C++ Designの著者は俺なんかより頭がいいはずだし、これに気付かないはずないと思っていたら、Lokiの中にちゃんとあった。

typedef MakeTypeList<a, b, c, d, e> List5;

これでいける。これでマクロは不要なはずだ。しかもTYPELISTマクロが力技で50個並べてるのに対して、こちらは再帰してるものと再帰を終わらせてるものの2つだけで、コードも短い。

MakeTypeListで検索しても中国語ばかりヒットしてほとんど見つからないが、Modern C++ Designを書いた後で追加されたものなのか?だとしたら、改訂版とかでマクロを使わない説明に変えて欲しい。templateを使ったコードの説明にマクロを使ってると、説得力が半減するし。

Modern C++ Designを読んでたときはTypeListは難しくてわけがわからないと思っていたが、自分で似たようなコードを書いてみたら、これは単純な再帰プログラミングみたいなもので、それほど難しいものではないことに気付いた。関数型プログラムの経験がある人間なら、書くのは難しくないと思う。しかし慣れないと、典型的なWrite Onlyプログラムというか、読むのは難しい気がする。