1

From what I know, stack does not have iterators in C++. For example, this post (Does std::stack expose iterators?) explicitly states that stack does not have iterators. However, I was told by my supervisor that stack in c++ should have iterators since it is a standard data structure and you can do stack.begin() (However, from what I know, there's no such syntax in standard C++). How do I convince him? Why stack does not have iterators in C++?

Question#2: Thank you all for awesome answers. I think the question now comes down to: why doesn't it make sense to have iterators for stack?

Community
  • 1
  • 1
Thenewstockton
  • 443
  • 6
  • 18
  • Just take a look at the documentation ...http://www.cplusplus.com/reference/stack/stack/ Is there iterator ? Nop. begin() ? Nop. – SnoozeTime Jul 01 '16 at 02:38

3 Answers3

6

You can convince your supervisor by advising your supervisor go and read section 23.6.5 of ISO/IEC-14882(2011), the specification for std::stack.

std::stack does not have iterators.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • He might also mention to the supervisor that the STL’s functionality is generally super-punctiliously specified (as this answers’ citation suggests) and so how any part of it “should” behave is, unlike (say) Markdown or PHP, exempt from opinionated subjectivity. – fish2000 Jul 01 '16 at 02:59
3

std::stack provides a strictly last-in-first-out view of the underlying container, and that's the point of it: to restrict the use of the underlying container to LIFO.

And so it does not provide iteration.

However, it does provide the underlying container as a protected member, which means that it's designed for being derived from. In your derived class you can provide iterators, and whatever you want. Also it's possible to just access that protected member of an ordinary std::stack, even without using any cast (namely via implicit conversion of member data pointer).

Re the added 2nd question,

why doesn't it make sense to have iterators for stack?

It can make sense, but in most cases it would provide the non-LIFO access that std::stack is designed to remove, i.e. in most cases it would be at odds with the very purpose of std::stack.

For debugging, one's debugger will show the contents of a std::stack, so there's no big need to have direct support for doing it in code.


Example:

#include <iostream>
#include <stack>

namespace cppx {
    using std::stack;

    namespace hack {
        template< class Item >
        auto container_of( stack<Item> const& st )
            -> typename stack<Item>::container_type const&
        {
            struct Hacked: stack<Item> { using stack<Item>::c; };
            return st.*&Hacked::c;
        }
    }  // namespace hack

    template< class Item >
    auto begin( stack<Item> const& st )
    { return hack::container_of( st ).begin(); }

    template< class Item >
    auto end( stack<Item> const& st )
    { return hack::container_of( st ).end(); }

}  // namespace cppx    

auto main()
    -> int
{
    using namespace std;

    stack<int> st;
    for( int const x : {3, 1, 4, 1, 5, 9, 2, 6, 5, 4} )
    {
        st.push( x );
    }

    using cppx::begin; using cppx::end;
    for( auto it = begin( st ); it != end( st ); ++it )
    {
        cout << *it << " ";
    }
    cout << endl;
}

Since in this example begin and end are not placed in namespace std, a range based loop would not compile.

I didn't do that because the legality (validity) of specializing a standard function for a standard container, in namespace std, is an issue I don't want to get into here. I think it's not permitted, although specializing for one's own type would be OK. But I'm not sure.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Does it always do so by standard? I thought STL containers were not designed to be subclassed. – bipll Jul 01 '16 at 02:41
  • 1
    @bipll: Yes, the standard requires the protected member. And no, it's not true that STL containers are not designed to be derived from. `std::stack` is main counter-example. – Cheers and hth. - Alf Jul 01 '16 at 02:56
  • @Cheersandhth.-Alf do you happen to know why the “don’t derive from STL containers” notion is so strongly held – are there any actually pitfalls in doing it in practice? – fish2000 Jul 01 '16 at 03:01
  • 1
    @fish2000: I think it's tied in with an ungood practice to delete via a pointer to the base class. That would be Undefined Behavior since the destructor isn't virtual. – Cheers and hth. - Alf Jul 01 '16 at 03:02
  • @Cheersandhth.-Alf aha that is a handy caveat then; one should not assume the base destructors are virtual when one is STL-deriving. Good to know. – fish2000 Jul 01 '16 at 03:07
1

std::stack is but a container adapter. It accepts a type of container (std::deque by default) as template parameter, and an instance of stack can be constructed from an instance of this container, but otherwise the underlying private container is not exposed and the stack itself does not have iteration facilities.

bipll
  • 11,747
  • 1
  • 18
  • 32