Does std::stack expose iterators?

后端 未结 5 1218
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-29 08:57

Does the std::stack in the C++ STL expose any iterators of the underlying container or should I use that container directly?

相关标签:
5条回答
  • 2020-11-29 09:27

    Stack does not have iterators, by definition of stack. If you need stack with iterators, you'll need to implement it yourself on top of other container (std::list, std::vector, etc). Stack doc is here.

    P.S. According to a comment i got from Iraimbilanja, std::stack by default uses std::deque for implementation.

    0 讨论(0)
  • 2020-11-29 09:32

    If you need a stack with iterators, you have two choices:

    • std::vector using push_back(), pop_back().

    • std::deque with either push_back()/pop_back() or push_front()/pop_front().

    0 讨论(0)
  • 2020-11-29 09:32

    In SGI, MSDN and GNU documentations, stack doesn't provide an iterator.

    0 讨论(0)
  • 2020-11-29 09:32

    Yor are asking

    Does std::stack expose iterators?

    Many people gave answers. If my English would be better, I would maybe also understand the exact meaning of 'expose'.

    If we are referring to the STL and the class std::stack and the pre defined functions defined herein, the answer is NO.

    My guess would be that you are asking, because you want to have iterators.

    So, if we go one step further, we have the function top(). And top() can be interpreted as a dereferenced iterator. With that, we can easily define Iterators to stack elements. The memory of the stack is guaranteed to be contiguous.

    See below. We are defining and using iterators for std::copy:

    #include <vector>
    #include <stack>
    #include <iostream>
    #include <algorithm>
    #include <iterator>
    #include <sstream>
    
    using Number = int;
    using UnderlyingContainer = std::vector<Number>;
    using Stack = std::stack< Number, UnderlyingContainer>;
    
    using StackIterator = const Number *;
    
    std::istringstream testData("5 8 1 4 9 3");
    
    int main()
    {
        // Put the test data onto the stack
        Stack stack{ UnderlyingContainer {std::istream_iterator<Number>(testData),std::istream_iterator<Number>()} };
    
        // Print the test data
        // Get iterators
        StackIterator end = &stack.top() + 1;
        StackIterator begin = end - stack.size();
    
        if (not stack.empty())
            std::copy(begin, end, std::ostream_iterator<Number>(std::cout, "\n"));
        return 0;
    }
    
    

    So you can create iterators for a stack. But, caveat:

    The std::stack intentionally hides its elements under the hood. So, if you write-access the data, I would see it as a design fault. Read-access through const pointers/iterators is for me OK. But maybe you should better use a std::vector . . .

    0 讨论(0)
  • 2020-11-29 09:44

    The std::stack does expose its underlying container (and therefore iterators) to subclasses through its protected interface. The std::stack's underlying container object corresponds to the (protected) data member c. So if you want to access them, you could extend std::stack a little.

    template<typename T, typename Container = std::deque<T>>
    class iterable_stack
    : public std::stack<T, Container>
    {
        using std::stack<T, Container>::c;
    
    public:
    
        // expose just the iterators of the underlying container
        auto begin() { return std::begin(c); }
        auto end() { return std::end(c); }
    
        auto begin() const { return std::begin(c); }
        auto end() const { return std::end(c); }
    };
    
    int main()
    {
        iterable_stack<int> st;
    
        st.push(2);
        st.push(5);
        st.push(3);
        st.push(7);
        st.push(9);
    
        for(auto i: st)
            std::cout << i << ' ';
        std::cout << '\n';
    }
    

    Output:

    2 5 3 7 9 
    
    0 讨论(0)
提交回复
热议问题