Неквалифицированный доступ к члену зависимого базового класса приводит к "Объявление [x] должно быть доступно" - программирование
Подтвердить что ты не робот

Неквалифицированный доступ к члену зависимого базового класса приводит к "Объявление [x] должно быть доступно"

код:

// 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()
{}

Сообщение об ошибке (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]

Функции empty(), top() и pop() являются функциями std::stack, поэтому почему gcc их не находит?

4b9b3361

Ответ 1

Вы должны явно ссылаться на функции-члены базового класса в шаблоне класса с помощью указателя this.

// ...

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

// ...

Это связано с тем, как работает двухэтапный поиск имени для шаблонов. Без косвенности this->, компилятор будет пытаться разрешить неквалифицированные имена как имена глобальных функций. Поскольку глобальных функций с именем empty(), top() и pop() не существует, компилятор будет выдавать ошибку.

Когда вы используете this->, компилятор задерживает поиск имени до момента фактического создания шаблона: в этот момент функция вызывает членов базового класса, будет правильно разрешена.