Home > other >  Is there a way to reference/index/pointer an item in a std::stack?
Is there a way to reference/index/pointer an item in a std::stack?

Time:07-25

As the title says, using std::stack is there a way to reference any item by reference/index/pointer without popping? If not how could I achieve this?

My use case is, I am making a vm for learning and I want to reference the stack items in the std::stack so I can push and access my local stack variables. I originally was going to just make a stack implementation - but I have the stl! I am guessing I may have to roll my own because the items are immutable, and I haven't seen any docs stating it :(

My use case (asm ; c )

mov DWORD PTR [rbp-4], 123  ; stack.push(123);
mov DWORD PTR [rbp-8], 321  ; stack.push(321);
add DWORD PTR [rbp-4], 1    ; stack[?] = stack[?]   1;

CodePudding user response:

Yes, there is an easy way to access the data through its underlying container.

Normally, all this is not necessary because you always can use the underlying container in the first place.

But if you want to do that for exceptional purposes, then simply take the address of the top(). This will be the last element in the underlying container. And if you subtract the size() of the stack (corrected by 1), then you have a pointer to the beginning of the underlying container.

And then you can use the subscript operator [] as expected.

Please see the following example:

#include <vector>
#include <stack>
#include <iostream>
#include <algorithm>
#include <iterator>

using Number = int;
using UnderlyingContainer = std::vector<Number>;
using Stack = std::stack< Number, UnderlyingContainer>;

using StackIterator = Number *const;

int main()
{
    // Put the test data onto the stack
    Stack myStack{ UnderlyingContainer {1,2,3,4,5} };

    if (not myStack.empty()) {

        // Get "iterators"
        StackIterator end = &myStack.top()   1;
        StackIterator begin = end - myStack.size();

        Number *const & stk = begin;

        for (size_t i{}; i < myStack.size();   i)
            stk[i] = stk[i]   10;

        for (size_t i{}; i < myStack.size();   i)
            std::cout << stk[i] << '\n';

        std::transform(begin, end, begin, [](const Number n) {return n - 10; });
        std::copy(begin, end, std::ostream_iterator<Number>(std::cout, "\n"));
    }
}

So, it looks like we found what you want to have, but in reality, we simply work on the underlying container.

But as said, there are sometimes reasons to do so . . .

  • Related