空想犬猫記

※当日記では、犬も猫も空想も扱っておりません。(旧・エト記)

火曜日:CRTP

f:id:xoinu:20140107153046j:plain
昼飯は焼きそばとゆで卵。晩飯はホッケの干物に掛け蕎麦。

ようやくC++コンパイラの実装が枯れてきたのもあって、最近はC++を積極的に使った実装技術についてあれこれ調べている。テンプレートというのは型付きのマクロなので、まずはマクロをテンプレートで置き換えることから取り組んでいる。

基本となるイディオムは、Curiously Recurring Template Pattern と呼ばれるもので、これは

class A : publc Base<A> {...};

のように、導出クラスで特殊化されたテンプレートクラスを基底クラスに与える方法。Aの実装にアクセスするときには this ポインタを static_cast して使う。このイディオムは、共通の実装を与えたり、共通のインターフェースを定義したり、その両方を同時に実現したり、マクロで書いてしまいがちな繰り返し現れる実装をエレガントに引き受けてくれる。

これだけではかなり用途が限られてしまうが、以下ように実装テンプレートを継承グラフに挿入するような手法を用いれば、色んな場所で使えるようになる。

class A : publc B {...};

C++というクラスがあったときに

template <typename T, typename Base> class Impl : public Base {...};
class A : publc Impl<A,B> {...};

などとする。ただし、もともとAのコンストラクタからBのデフォルトでないコンストラクタを呼び出している場合は、Impl<T> のコンストラクタを通過して呼び出せるように Impl<T> 内にパラメータ化されたコンストラクタを用意しておく必要がある。