C++ 標準は、クラス テンプレートの仮想メソッドのコードが生成される正確な時点について何か述べていますか?
次の例を検討してください。
class Interface
{
public:
virtual void f() = 0;
};
template <unsigned int V>
class A : public Interface
{
public:
virtual void f()
{
}
};
Interface* instantiate()
{
// class template instantiation with argument V=0
return new A<0>();
}
// specialization of f() for template argument V=0
template <> void A<0>::f()
{
cout << "Output from A<0>::f()" << endl;
};
int main()
{
Interface* i = instantiate();
i->f();
return 0;
}
クラス テンプレート A は、仮想メソッド f() を宣言します。この例では、関数 instantiate() は、A<0>::f() の明示的な特殊化が行われる前に、クラス テンプレート A を暗黙的にインスタンス化します。上記の例では、クラス テンプレート A の暗黙的なインスタンス化が行われた後に特殊化が行われます。これで、少なくとも私の ARM コンパイラと g++ は A<0>::f() の特殊化されたバージョンを選択します。つまり、main() プログラムは「A<0>::f() からの出力」を画面に表示します。
このクラス テンプレートが暗黙的にインスタンス化された後、クラス テンプレートの仮想メソッドの特殊化を定義するだけで十分であると常に確信できますか? 観察された動作が C++ 標準によって裏付けられていれば、気分が良くなるでしょう。このトピックに関する明確な声明は見つかりませんでした。最も近い部分は 14.7.3/6 で、仮想メソッドに関してはやや不明確です。
テンプレート、メンバーテンプレート、またはクラステンプレートのメンバーが明示的に特殊化されている場合、その特殊化は、暗黙的なインスタンス化を引き起こす特殊化を最初に使用する前に宣言する必要があります。使用が発生します。診断は必要ありません。プログラムが明示的な特殊化の定義を提供しておらず、特殊化が暗黙的なインスタンス化を発生させるような方法で使用されているか、メンバーが仮想メンバー関数である場合、プログラムは不正な形式であり、診断は必要ありません。宣言されているが定義されていない明示的な特殊化に対して、暗黙的なインスタンス化が生成されることはありません