いまさらですが、コンパイラの動きでも確認してみましょうか。
えっ?タイトルと内容が違う?
いえいえ、タイトルと関係あるんです。
コンパイラは大体『プリプロセス→パース→コードジェネレート→アセンブル→リンク』といった流れで動いています。この後に出来上がった実行ファイルやdllなどを私たちは使うことになります。
ところでC++には現在2つの表明(詳しくはWikipedia参照)が存在し、1つは#error、もう1つはassertです。これがコンパイルや実行のどの時点で検証を行うかを確認します。
#errorはプリプロセッサであることからもわかるとおり、プリプロセス時に検証を行います。
assertは実行時に検証を行います。
ところで、テンプレートの実体化の時点での(たとえば、テンプレート引数として渡された型の検証)はどのようにすればよいでしょうか。テンプレートの実体化はコードジェネレートの時点で行われるので、検証を行うとすればこのタイミングです。
しかし先ほど述べたように、現在のC++にある表明はプリプロセス時か、実行時の検証しか行うことができません。これではテンプレートの実体化の時点では適切な検証を行うことができないということになります。
そこで、C++0xでは"Static assertions"(静的な表明)を導入します。
新しいキーワードstatic_assertで(プリプロセス後の)コンパイル時に検証を行うことができます。
たとえば次のようにして使うことができます。
template <class T> class Check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); };
これによって、テンプレート仮引数の型がint型よりも大きい場合にはコンパイルエラーとなり、"not big enough"というメッセージが出ます
やはりこのあたりはしっかりとコンパイラの動きを理解していないといけませんね。私自身そこまで自信がなかったところでもあります。
ちなみに上のコードはhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.htmlに書いてあるコードをtypenameをclassに、structをclassに変えたものです。他にあまりわかりやすいコードを思いつかなかったということで、例を同じコードにしました。