考虑以下示例:
template <typename T>
class A {
public:
void f() {
cout << "A::f()\n";
}
};
template<>
class A<int> {
};
template<typename T>
class B: public A<T> {
public:
void g() {
cout << "B::g()\n";
A<T>::f();
}
};
int main() {
B<int> b; // (1)
b.g(); // (2)
return 0;
}
显然,对于int模板类型,对B :: g()内部的A :: f()的调用将失败。我的问题是呼叫在什么时候失败了?在(1)或(2)?我认为它应该是(1)因为在那时编译器创建一个模板类型为int的新类并编译它。那个编译应该在f()中失败吗?
答案 0 :(得分:4)
它将在(2)失败,这由标准保证。在第14.7.1 / 1节中,它说实例化模板类不实例化它的成员定义。只有在使用该成员后才会发生这种情况。
如果从代码中删除(2),它将编译。
14.7.1 / 1摘录:
类模板特化的隐式实例化会导致隐式 实例化类成员函数,成员类,静态数据成员和成员模板的声明,但不是定义或默认参数;它会导致成员匿名联合的定义的隐式实例化。
强调我的。
Visual Studio的诊断具有误导性。它会说see reference to class template instantiation 'B<T>' being compiled
。它的含义不是“我在B<T>
的实例化失败”,而是“我没有实例化类B<T>
的成员”
答案 1 :(得分:3)
2)失败。模板的成员函数在被调用时被实例化。
更准确地说:当实例化类模板时,实例化其成员函数的声明,但不是它们的定义。使用该函数时,将实例化该定义。