【问题标题】:Why does function calls to templatized base classes not work?为什么对模板化基类的函数调用不起作用?
【发布时间】:2010-02-19 21:00:20
【问题描述】:

考虑以下示例:

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() 中失败,对吗?

【问题讨论】:

  • @John:没有,因为编译会失败。
  • 哦,好的。我很困惑,因为你在谈论“调用在什么时候失败”——并在代码中注释了一些点——就好像它已经编译了一样。

标签: c++ templates


【解决方案1】:

它将在 (2) 处失败,这是由标准保证的。在第 14.7.1/1 节中,它说实例化模板类并实例化它的成员定义。只有在使用该成员时才会发生这种情况。

如果您从代码中删除 (2),它将编译。

14.7.1/1 节选:
类模板特化的隐式实例化导致隐式 类成员函数、成员类、静态数据成员和成员模板的声明,但不是定义或默认参数的实例化;它会导致成员匿名联合定义的隐式实例化。

强调我的。


Visual Studio 的诊断具有误导性。它会说see reference to class template instantiation 'B&lt;T&gt;' being compiled。它的意思不是“我在实例化B&lt;T&gt; 时失败”,而是“我在实例化B&lt;T&gt; 类的成员时失败”

【讨论】:

  • 最好的是VC只指向实例化B的行。无论如何,我现在应该学会怀疑 VC 并先查一下。
【解决方案2】:

它在 2) 处失败。模板的成员函数在调用时被实例化。

更准确地说:当一个类模板被实例化时,它的成员函数的声明被实例化,而不是它们的定义。该定义在使用函数时被实例化。

【讨论】:

  • 一个有趣的事实是,如果你从所有模板定义中删除函数 f 或在该 TU 中显式特化 A,则允许编译器标记成员函数 @987654323 的定义@ 格式错误并发出诊断,即使从未使用过 B,因为无法为该成员函数 (14.7/8) 生成有效的特化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 2014-07-20
  • 2013-03-15
  • 2019-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多