当生成用于类模板的虚拟方法的代码时,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 ::f()的任何专门化之前,隐式实例化了类模板A。在上面的示例中,特化是在类模板A的隐式实例化发生之后完成的。现在,至少我的ARM编译器和g++选择了A ::f()的专用版本。 e。 main()程序在屏幕上显示“A ::f()的输出”。

我可以始终确定,在隐式实例化该类模板之后,定义一个类模板的虚拟方法的特化就足够了吗?如果观察到的行为得到C++标准的支持,我会感觉更好。我没有找到关于此主题的明确声明。最接近的部分是14.7.3 / 6,对于虚拟方法来说,它没有什么特殊性:

最佳答案

我们非常确定它是UB。

在实践中:

new A<0>()

将生成对构造函数的调用,并且编译器要求可用的定义。如果您在此调用后尝试专门处理A<0>::A(),则gcc会出错:
error: specialization of ‘A<V>::A() [with V = 0]’ after instantiation

构造函数将具有用于设置类的多态 header 的代码,该 header 将包含指向vtable的指针。在该vtable中将是Interface::f的条目,但此时甚至还没有声明将最终填充该插槽的符号,即显式的特化A<0>::f-因此归结为实现质量问题-编译器在完成类类型的同时设计vtable-如果可以的话,它有能力在以后的TU中修复该vtable的新声明的成员。

10-06 10:59