styko
styko

Reputation: 701

Get container behind std::stack

I am using a std::stack to keep a list of possibilities in my program.

std::stack<int, std::deque<int> > myStack;

Now, for debugging purposes only, I want to have access to all the elements of my std::stack (for instance as a std::deque). But the following syntax is illegal:

std::deque<int> myDeque = myStack; // Does not compile

What is the simplest way to do it?


The way I would do it is:

std::stack<int, std::deque<int> > newStack = myStack;
std::deque<int> myDeque;
while(!newStack.empty()){
    myDeque.push_back(newStack.top());
    newStack.pop();
}

but it looks a bit ugly.

Upvotes: 5

Views: 2243

Answers (2)

oats
oats

Reputation: 467

Adding to Maxim's answer (not enough rep to comment):

std::stack doesn't have a virtual destructor, so attempting to delete MyStack from a base-class pointer to std::stack is unsafe. You can decide to trust that your compiler will generate warnings in these cases, or use private inheritance to prevent this scenario in most cases.

template<class T, class C>
struct MyStack : private std::stack<T, C> 
{
    typedef std::stack<T, C> Stack;
    using Stack::Stack;
    using Stack::operator=;
    using Stack::c; // expose as public
    // Private inheritance, explicitly forward functions we need
    using Stack::size;
    using Stack::push;
    using Stack::pop;
    // etc
};

Upvotes: 2

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136306

The underlying container of std::stack is accessible as protected member c. Hence:

template<class T, class C>
struct MyStack : std::stack<T, C> 
{
    typedef std::stack<T, C> Stack;
    using Stack::Stack;
    using Stack::operator=;
    using Stack::c; // expose as public
};

And if you cannot change definitions and recompile, then:

template<class T, class C>
C& get_underlying_container(std::stack<T, C>& s) {
    static_assert(sizeof s == sizeof(MyStack<T, C>), "Size mismatch.");
    static_assert(alignof s == alignof(MyStack<T, C>), "Alignment mismatch.");
    return static_cast<MyStack<T, C>&>(s).c;
}

Upvotes: 11

Related Questions