0

I'm feeling rather stupid - must be missing something silly --- I wanted to subclass the generic STL stack class so that I could extend it with a combined top followed by pop operation but my compiler is telling me that both top and pop are undeclared identifiers.

template <typename T>
class MyStack : public stack<T>
{
   public:
      T PopTop()  // Convenience - combined top and pop in one go
         {
            T result = top();
            pop();
            return result;
         }
};

I note that I can fix this problem by writing

   T result = stack<T>::top();

but why isn't top seen automatically given the stack class is directly inherited?

Thanks in advance

David
  • 5,991
  • 5
  • 33
  • 39
  • 5
    `this->top()` also works. This happens whenever a base class depends on a template parameter. – HolyBlackCat Jul 28 '22 at 20:45
  • 1
    Be careful about inheriting from STL classes - they lack virtual destructors and are not intended to be inherited from. – StuporMundi Jul 28 '22 at 20:49
  • Templates can be specialized. For this reason, it can not be assumed that `pop()` means `stack::pop()`. For a given `T`, the member function `pop()` might not exist and some other `pop()` would be a better match. – Drew Dormann Jul 28 '22 at 21:39
  • Thank you for all these useful tips – David Jul 28 '22 at 22:37

1 Answers1

5

First, don't descend from std classes, rather use private member (composition) and delegate functions - that's a common warning.

With that said, the error is because a base class with a template argument is not considered in ADL lookup regarding the descendant class. You might have using stack<T>::pop; and similar declarations for each function that you plan to use in MyStack.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
lorro
  • 10,687
  • 23
  • 36
  • I am aware of the arguments for composition, etc --- however, in this case, I did not want to add any fields, simply wanted a single convenience method and composition seemed overkill for the intended purpose. That said, I appreciate the answer (did not remember that ADL won't work in that situation - as I said, I was missing something stupid) – David Jul 28 '22 at 22:36
  • @David Yes, I had that feeling in the past - however, in many cases it turns out to be a maintenance nightmare compared to a public decorator (i.e., `template struct myStack { /* your methods */ operator const std::stack&() const { return s_; } operator std::stack&() { return s_; } std::stack s_; /* note that s_ is publicly accessible */ };`). – lorro Jul 28 '22 at 22:41
  • Sure --- I'm aware of the Decorator design pattern (and trust me, the maintenance consequences of poor decisions!) but for this particular purpose, I just felt it was overkill when all I wanted was the equivalent of "extend" rather than "encapsulate" for a single method that would be useful only locally. Regular inheritance still has some value :-) If I was building something within a corporate environment or that would have to be used by others, I would have gone that way but at least I learned something about ADL that I didn't know. – David Jul 29 '22 at 12:29