当生成类模板的虚拟方法的代码时,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,它在涉及虚拟方法时有点不明确:
如果一个模板、一个成员模板或一个类模板的成员是显式特化的,那么该特化应在第一次使用该特化之前声明,这将导致隐式实例化发生,在每个翻译单元中使用发生;不需要诊断。如果程序没有为显式特化提供定义,并且该特化的使用方式会导致发生隐式实例化,或者该成员是虚拟成员函数,则该程序是格式错误的,不需要诊断。永远不会为已声明但未定义的显式特化生成隐式实例化