ローカル変数を非型引数として使用することが違法なのはなぜですか?
たとえば、次のコードでlocal_var
は を引数にすることはできませんX
。
template<int& x> struct X {};
void f(int local_var)
{
X<local_var> x;
}
テンプレート引数はコンパイル時に評価する必要があり、コンパイラは実行時までローカル変数のアドレスを認識しないためです (オブジェクトへの参照をバインドするために、コンパイラはそのオブジェクトのアドレスを認識する必要があります)。
C++11 標準では、パラグラフ 14.3.2/1 で提供できる非型テンプレート引数を正確に示していることに注意してください。
非型、非テンプレートのテンプレート パラメータのテンプレート引数は、次のいずれかになります。
— 整数型または列挙型の非型テンプレート パラメーターの場合、テンプレートパラメーターの型の変換された定数式 (5.19) ; また
— 非型テンプレートパラメータの名前; また
— 静的記憶域期間と外部リンケージまたは内部リンケージを持つオブジェクトのアドレスを指定する定数式 (5.19)、または外部リンケージまたは内部リンケージを持つ関数 (関数テンプレートと関数テンプレート IDを含むが、非静的クラス メンバーを除く) で表される (ただし、名前が関数または配列を参照する場合は & を省略でき、対応する template-parameter が参照の場合は省略しなければなりません。また
— null ポインター値に評価される定数式 (4.10)。また
— null メンバポインタ値に評価される定数式 (4.11); また
- 5.3.1 で説明されているように表現されたメンバーへのポインター。また
— 型のアドレス定数式
std::nullptr_t
。
ご覧のとおり、ローカル変数はこのリストに含まれていません。
テンプレートの「値」は、コンパイル時に存在する必要があります。
template<int x> struct X {};
ここで参照をバインドしたりポインターを渡したりしなくても、コンパイラーは渡された要素の値をコンパイル時に認識している必要があります。
ここでの置き換えint &x
はint x
意図的なものです。int& に関するものは正しく答えられています。型指定されていないすべてのテンプレート引数に適用されることを指摘したかっただけです。
template<int*>
アドレスです...
X<local_var> x; // will not work, local_var does not exist at compile time
X<1> x; // works since 1 is known
(Andyの回答に加えて)参照の代わりに値型を使用することを提案する結論を防ぎたかっただけです。