模板化超类的受保护成员应该在子类中可见,但(有时)不是

时间:2012-01-07 01:29:55

标签: c++ templates inheritance

  

可能重复:
  Accessing inherited variable from templated parent class

我一直在实现二进制堆作为priority_queue的子类,尽管付出了相当大的努力,但仍遇到了我无法理解的情况。以下是代码的工作版本。 (背景:c是priority_queue的支持向量。)

#include <queue>
using namespace std;

template <class nodetype>
class BinaryHeap : public priority_queue<int> {
public:
    BinaryHeap() { vec = &c; }
    vector<nodetype> *vec;
};

int main() {
    BinaryHeap<int> b;
}

但是,当您将超类更改为:

class BinaryHeap : public priority_queue<nodetype>

...编译器抱怨使用c

h.cpp: In constructor ‘BinaryHeap<nodetype>::BinaryHeap()’:
h.cpp:10: error: ‘c’ was not declared in this scope

这似乎更奇怪,因为:

  1. “[c]相当于this-&gt; c”(ref) - 如果你使用vec = &this->c,它确实可以编译。

  2. 如果您再次向BinaryHeap添加using声明using priority_queue<nodetype>::c,则会进行编译。但是这个使用声明应该是不必要的。

  3. 修改

    所以,显然这是因为“编译器在查找非依赖名称时不查找依赖基类”(ref) - “c”不依赖于模板参数,因此是非独立的,priority_queue<nodetype>确实依赖于模板参数 - nodetype - 所以是依赖的。

    另一方面,

    priority_queue<int>不依赖于nodetype,因此是非独立的,因此编译器 在解析其他时查找名称非独立名称。

    这是对的吗?如果是这样的话:

    为什么标准要求这种行为,当“在查找非依赖名称时查找依赖基类”显然可能。有什么好处?编译时性能优化?

1 个答案:

答案 0 :(得分:2)

最后,它只是定义模板的这种行为的标准问题。 (C ++ 11)标准在 [temp.nondep](14.6.3)中说明了非依赖名称解析的以下内容:

  

模板定义中使用的非依赖名称可以使用通常的名称查找找到并在使用它们时绑定。

由于c显然不依赖于模板参数,因此编译器会将其视为非依赖名称。所以会发生什么基本上如下:当编译器查看BinaryHeapnotetype的实际类型未知,因此priority_queue<nodetype>也是nodetype,因为它取决于c(它可能是部分专业化)。因此,编译器无法查看该类型的解析(因为我们讨论的是定义模板的点,而不是实例化的位置)。因此,它在包含范围内查找名为this->c的内容,找不到任何内容,因此拒绝代码。使用using priority_queue<nodetype>::c(或c)会使BinaryHeap成为一个从属名称(因为它不是priority_queue<nodetype>的成员,它必须是notetype的成员),所以名称查找被延迟到模板实例化的时间点,其中priority_queue<nodetype>已知,因此编译器可以在{{1}}中搜索。

对于你的编辑:是的,这是正确的