对从属基类成员的非限定访问会导致"[x]的声明必须可用"

Per*_*-lk 14 c++ stack templates

码:

// test3.cpp

#include <stack>

using namespace std;

template<typename T>
struct ptr_stack_tp;

template<typename T>
struct ptr_stack_tp<T*> : public stack<T*>
{
    ~ptr_stack_tp()
    {
        while (!empty()) {
            operator delete(top());
            pop();
        }
    }
};

int main()
{}
Run Code Online (Sandbox Code Playgroud)

错误消息(gcc 4.7.2):

test3.cpp: In destructor 'ptr_stack_tp<T*>::~ptr_stack_tp()':
test3.cpp:15:23: error: there are no arguments to 'empty' that depend on a template parameter, so a declaration of 'empty' must be available [-fpermissive]
test3.cpp:15:23: note: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)
test3.cpp:16:33: error: there are no arguments to 'top' that depend on a template parameter, so a declaration of 'top' must be available [-fpermissive]
test3.cpp:17:17: error: there are no arguments to 'pop' that depend on a template parameter, so a declaration of 'pop' must be available [-fpermissive]
Run Code Online (Sandbox Code Playgroud)

功能empty(),top()pop()有功能的std::stack,所以,为什么GCC并没有找到他们呢?

And*_*owl 26

您应该通过this指针在类模板中显式调用基类成员函数.

// ...

template<typename T>
struct ptr_stack_tp<T*> : public stack<T*>
{
    ~ptr_stack_tp()
    {
        while (!this->empty()) {
        //      ^^^^^^
            operator delete(this->top());
            //              ^^^^^^
            this->pop();
        //  ^^^^^^
        }
    }
};

// ...
Run Code Online (Sandbox Code Playgroud)

这是由于两阶段名称查找对模板的工作方式.如果没有this->间接,编译器将尝试将非限定名称解析为全局函数的名称.由于没有名为empty(),top()pop()存在的全局函数,编译器将发出错误.

在使用时this->,编译器会将名称查找延迟到实际实例化模板的那一刻:此时,将正确解析对基类成员的函数调用.