Copy elements from std :: vector to std :: stack c ++

I need to copy std :: vector to std :: stack.

  • Moving around the vector and pushing onto the stack is just the way to go?

  • If there is another way, the best choice in terms of performance?

std::stack<A> m_stack; std::vector<A> m_vec; for (auto& elem : m_vec) { m_stack.push(elem); } 
+6
source share
3 answers

Since the stack is a container adapter, you can create a stack from a base container:

 std::vector<A> m_vec = /* ... */; std::stack<A, std::vector<A>> m_stack(m_vec); 

Or, if you want your stack to be deque -backed:

 std::stack<A> m_stack(std::deque<A>(m_vec.begin(), m_vec.end())); 
+11
source

Some fun with stacks demonstrating various methods of getting values ​​onto the stack from another container.

Assuming we have provided an appropriate definition for:

 template<class T, class Container> auto stack_pusher(std::stack<T, Container>& stack); 

Then we could write:

 int main() { using namespace std; // construct an initial vector vector<int> init { 7,6 }; // construct a stack using a copy of the initial vector elements // note that the stack storage is automatically deduced stack<int> stack1 { { begin(init), end(init) } }; // construct a stack directly from a container initialised with an initialiser list stack<int> stack2 { { 3,4,5 } }; // another vector vector<int> myvector { 1, 2, 3, 4, 5, 6, 7, 8 }; // copy vector onto stack using a forward iterator copy(begin(myvector), end(myvector), stack_pusher(stack1)); // copy vector onto stack using a reverse iterator copy(rbegin(myvector), rend(myvector), stack_pusher(stack2)); // display the stacks while (stack1.size() or stack2.size()) { // function to encode an optional T as a string auto encode = [](const auto& opt) { return opt ? std::to_string(opt.value()) : std::string("*"); }; // function to pop a value from a stack if it not empty. // return an optional auto maybe_pop = [](auto& stack) { using element_type = std::decay_t<decltype(stack.top())>; boost::optional<element_type> result; if (stack.size()) { result = stack.top(); stack.pop(); } return result; }; cout << encode(maybe_pop(stack1)) << "\t" << encode(maybe_pop(stack2)) << endl; } return 0; } 

for which the output will be:

 8 1 7 2 6 3 5 4 4 5 3 6 2 7 1 8 6 5 7 4 * 3 

Here is the full list (C ++ 14):

 #include <iostream> #include <stack> #include <vector> #include <deque> #include <iterator> #include <utility> #include <boost/optional.hpp> // an iterator that pushes values onto a stack template<class Stack> struct push_iterator : std::iterator<std::output_iterator_tag,void,void,void,void> { push_iterator(Stack& stack) : pstack(std::addressof(stack)) {} template<class T> auto& operator=(T&& t) { pstack->push(std::forward<T>(t)); return *this; } auto& operator*() { return *this; } auto& operator++() { return *this; } private: Stack* pstack; }; // convenience class to make a push_iterator of the correct type template<class T, class Container> auto stack_pusher(std::stack<T, Container>& stack) { return push_iterator<std::stack<T, Container>>(stack); } int main() { using namespace std; // construct an initial vector vector<int> init { 7,6 }; // construct a stack using a copy of the initial vector elements // note that the stack storage is automatically deduced stack<int> stack1 { { begin(init), end(init) } }; // construct a stack directly from a container initialises with an initialiser list stack<int> stack2 { { 3,4,5 } }; // another vector vector<int> myvector { 1, 2, 3, 4, 5, 6, 7, 8 }; // copy vector onto stack using a forward iterator copy(begin(myvector), end(myvector), stack_pusher(stack1)); // copy vector onto stack using a reverse iterator copy(rbegin(myvector), rend(myvector), stack_pusher(stack2)); // display the stacks while (stack1.size() or stack2.size()) { // function to encode an optional T as a string auto encode = [](const auto& opt) { return opt ? std::to_string(opt.value()) : std::string("*"); }; // function to pop a value from a stack if it not empty. // return an optional auto maybe_pop = [](auto& stack) { using element_type = std::decay_t<decltype(stack.top())>; boost::optional<element_type> result; if (stack.size()) { result = stack.top(); stack.pop(); } return result; }; cout << encode(maybe_pop(stack1)) << "\t" << encode(maybe_pop(stack2)) << endl; } return 0; } 
+1
source

See this question about ways to use std::copy on the stack, but out of the box there is no more obvious way than looping with calls to press.

As for performance, the only way to say it is to measure it. (First, code for clarity and correctness, and then worry about speed.)

0
source

All Articles