次のコードを検討してください。
template < class A >
class XX {
public:
template <int (*CC)() >
int bla (){ return CC(); }
int stam() {return 0;}
int f() {
return bla<stam>();
}
};
int main()
{
XX<int> xx;
printf(" this is %d\n", xx.f());
return 0;
}
失敗する
test.cpp: In member function ‘int XX<A>::f() [with A = int]’:
test.cpp:14: instantiated from here
test.cpp:8: error: ‘int XX<A>::stam() [with A = int]’ cannot appear in a constant-expression**
考えてみれば明らかです。stam
テンプレートがインスタンス化されるまで存在しないため、関数アドレスはありません。テンプレートがインスタンス化されると、インスタンスはコードのどこかで分解されstam
、アドレスが取得されます。したがって、アドレスはコンパイル時に一定ではありません (作業によってはそうなる可能性もありますが、これはサポートされていません)。
では、なぜ私はこれをやろうとしているのでしょうか。関数ポインターまたは仮想関数を使用できます。実際bla
には、それを使用するstam
(stam1
とが存在するstam2
) ことは無数の回数と呼ばれ、マイナーなパフォーマンスの改善 (間接参照を使用しないなど) でさえ歓迎されます。
もちろん解決策はあります: Createbla1
とbla2
which はほぼ同じです。プリプロセッサ マクロを記述します。エレガントな解決策があるかどうか疑問に思っています。