名前空間に対して汎用関数の名前の導入を制限する

上とかなり重複するCRTPの効果になると思いますが,タイトルのような効果も期待できます.上に書いたsome_processの二つの宣言

template<class T>
void some_process(base<T> &r);

template<class T>
void some_process(T &r);

では,前者の方がsome_processという関数名の導入を制限した形になっています.これによって,前者ではsome_processという関数名に対する他のoverloadが可能になってきます.

template<class T>
void some_process(hoge<T> &r);

template<class T>
void some_process(huga<T> &r);

もちろんこれらはsome_processの後者の宣言に対する特殊化でも可能ですが,後者の宣言では最も汎用な宣言を一度書いたが最後,あとはすべて特殊化で書かなければならず,結局同じことをしなければならなくなります.
このことはExpression Templateの実装においては特に重要です.というのも,演算子に対して最も汎用的な形を宣言するわけにはいかないからです.

template<class LHS, class RHS>
plus<LHS, RHS> operator+(LHS const &lhs, RHS const &rhs);
// plusは演算子が返す式オブジェクトです

このような演算子のoverloadは他のクラスに対しても定義されるでしょうから,この宣言を特定のクラスのために書くことは許されません.(id:Cryolite:20040507#p1で「議論は後回しにします」と書いておいて結局書いてなかった問題とはこのことです.)なので,ETの実装では演算子のoverloadを制限することがほぼ必須になります.

template<class LHS, class RHS>
plus<LHS, RHS> operator+(base<LHS> const &lhs, base<RHS> const &rhs);

boost::numeric::ublass, boost::lambda, boost::spiritなどExpression Templateを用いたboostのライブラリではCRTPによるこの効果を享受しています.が,実際にはこの効果もコードの再利用のためにCRTPを使った結果の副産物としての意味合いが強いかも知れません.(そもそもこの効果だけが必要ならCRTPでなくても実現可能です.)