Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unqualified access to member of dependent base class results in "A declaration of [x] must be available"

Code:

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

Error message (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]

Functions empty(), top() and pop() are functions of std::stack, so, why gcc doesn't find them?

like image 731
Peregring-lk Avatar asked Mar 19 '13 16:03

Peregring-lk


1 Answers

You should explicitly invoke base class member functions in a class template through the this pointer.

// ...

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

// ...

This is due to the way the two-phase name lookup works for templates. Without the this-> indirection, the compiler will look try to resolve unqualified names as names of global functions. Since no global functions named empty(), top(), and pop() exist, the compiler will emit an error.

When you are using this->, the compiler will delay the name lookup to the moment when the template is actually instantiated: at that point, the function calls to members of the base class will be correctly resolved.

like image 125
Andy Prowl Avatar answered Nov 13 '22 04:11

Andy Prowl