質問: 0; i < t; i++) { cout << i<<'\n'; } cout << t; _getch(); return 0; } ```
回答: まず`template<> constexpr int sunto<0>()`がない場合のコンパイラの動きを確認してみます。 例えば `sunto<2>();` という式が現れた時、コンパイラはテンプレートのnに2を当てはめて、 ``` int sunto<2>() { return 2 + sunto<1>(); } ``` という関数を生成します(テンプレートの実体化)。生成した関数の中に`sunto<1>()`があるので、今度は ``` int sunto<1>() { return 1 + sunto<0>(); } ``` を生成します。今度は`sunto<0>()`が出来たので、更に ``` int sunto<0>() { return 0 + sunto<-1>(); } ``` を生成します。今度は`sunto<-1>()`が出来たので... という具合に、これはいつまでも無限に続きます。実際には無限に関数を生成することは不可能なので、いつかはメモリ不足か何かでコンパイルが失敗します。これが`template<> constexpr int sunto<0>()`を消した時のエラーの理由です。 次に ``` template<> constexpr int sunto<0>(){ //cout << "template<>を使用\n"; return 0; } ``` があるときのコンパイラの動作を説明します。これはテンプレートの特殊化といい、`n==0`の時に限って、特別なコードを使うように指示するものです。前と同じように `sunto<2>();` を呼び出すと、`n==2`と`n==1`の時は、先ほどと同じですが、`n==0`の時に特殊化されたコードを生成します。つまり ``` int sunto<2>() { return 2 + sunto<1>(); } int sunto<1>() { return 1 + sunto<0>(); } int sunto<0>(){ //cout << "template<>を使用\n"; return 0; } ``` というコードが生成され、無事にコンパイルできるようになります。 ちなみに`template<> constexpr int sunto<0>()`の中で`std::cout`を使うとエラーになるのは、`constexpr`がついているからです。`constexpr`がついていると、関数の結果はコンパイル時に決定しなければなりませんが、`std::cout`は実行時に値を出力するので、コンパイル時には呼び出せません。`constexpr`と矛盾してしまうのでエラーになります。 だからと言って、`constexpr`を取ってしまうと、`sunto<>()`自体の生成はうまくいきますが、今度は別のところ `int array3[sunto<3>()];` でエラーになってしまいます。配列のサイズは、コンパイル時に分かっていなければなりません。`sunto`に`constexpr`がついていれば、コンパイル時に計算結果が出せることが保証されるのでコンパイルが通りますが、ついていなければ保証がないのでエラーになります。