加算を定義したクラスがあるとします.
class C{ public: C operator+(C const &rhs) const { // 実装 } C &operator+=(C const &rhs) { // 実装 return *this; } };
『Effective C++』でのScott Meyersの名言「intのように振舞え」,あるいは『Exceptional C++』(第何項か番号は忘れましたが,ちゃっちいcomplexクラスの実装を引き合いに出して「このクラスの誤りをできる限り挙げよ」とかいう問題で,最初の回答が「std::complexがあるのに再発明するなヴォケ!」というあの項)に書いてあるように,通常,operator+は以下のようにほぼお決まりのパターンでoperator+=に委譲する形で書くのが原則になっています.
C C::operator+(C const &rhs) const { C tmp(*this); // まぁ,コピーコンストラクタはあるとしましょう tmp += rhs; // ここでoperator+=に委譲している return tmp; }
こういう決まりきった形式をとるものは,できることなら自動化してしまおうと考えるのが再利用の基本ってものです.そこで,次のようなクラスを作ります.
templatestruct addable{ T operator+(T const &rhs) const { T tmp(static_cast (*this)); tmp += rhs; return tmp; } };
このクラスを利用すると先ほどのclass Cは以下のように書けます.
class C : public addable{ public: C &operator+=(C const &rhs){ // 実装 return *this; } };
先ほどのCの定義との違いがお分かりいただけるでしょうか?たった1行addableから継承するというコードを書くだけで,Cにoperator+を定義することができてしまっています.もちろんCには最低限のコードとしてoperator+=は書かなければいけません.しかし,それさえ書いてしまえば後はaddableが自動でCに他の機能を提供してくれるわけです.別の言い方をすれば,addableはoperator+=の定義を色々取り替えられるようにしておいて,それに依存するoperator+の定義を自動で行ってしまうクラスとも言えます.これはまさに『デザインパターン』でいうところのTemplate Methodパターンと言えませんか?(なので,タイトルは上のようにしてみましたがどうでしょか?)特に,addableの部分がライブラリとして提供されていれば,class Cを定義しようとするユーザはこのようなライブラリを利用して低コストでCの実装を行うことができます.
boostでこのようなCRTPの使い方をしている例を挙げてみるとboost::operators(上の例はここから取らせてもらいました), boost::iterator_facade, boost::iterator_adaptorなどが挙げられると思います.こういうiteratorや演算子といった軽量になる傾向のあるオブジェクトや関数に対しては(仮想関数を持ち出すことはほぼ論外になりますので),このようなCRTPの利用は非常に有効であると思われます.また,上記のライブラリとは若干文脈が違うとは思いますがboost::spiritのgrammarなどもこれに属するCRTPの使い方をしていると思われます.