汎用関数においてコンセプトの不整合に対するFirewallを構成する

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

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

上の2つの最大の違いは,後者があらゆる型Tに対してsome_processが定義されているように見えるのに対して,前者はbase<T>(の派生型)に対してのみ定義されていることです.
後者の場合,想定していない型,たとえばintに対してもsome_processが定義されているように見えます.が,実際には後者に対してintで実体化するとintのオブジェクトにはr.method()なんていうコードは定義されていませんので,その部分でエラーを引き起こすことになります.上のようにsome_processが単純な場合ならまだしも,some_processが複雑な場合,コンパイル時に大量の意味不明のエラーが吐き出されエラーの特定が非常に困難になります.皆さんもSTLやboostを使っていてしばしばこのような経験をしていることと思います.
一方,前者はbase<T>(の派生型)に対してのみ定義されています.base<T>(の派生型)には,some_processにおいて要求されるmethodメンバ関数が必ず定義されているという制約があります.これはsome_processにおける,引数に対するコンセプトの要求が関数の宣言に明示されていると考えることができると思います.これによってsome_processが要求するコンセプトに合わない型,たとえばintなどに対してsome_processを適用しようとするとただ一言「intに対してsome_processは定義されていない」というエラー(もしくはsome_processに対するintのoverloadが解決しないという類のエラー)が吐き出されるだけで済みます.
このようなCRTPの作用も非常に重要であると思うのですが,実際にはコードの再利用のためのCRTPの利用に付随してくるだけの効果であることが多く,目立たないものだとは思います.
また,同等の機能を提供する他の機構,たとえばboost::concept_checkなどとの比較も色々考えて見ましたが,あまりまとまった答えは出せませんでした.この部分についてある程度考えがまとまったらまたこのことについて書くかもしれません.