Un po 'di divertimento con pile che dimostrano vari metodi per ottenere i valori nello stack da un altro contenitore.
Supponendo abbiamo fornito una definizione appropriata per:
template<class T, class Container>
auto stack_pusher(std::stack<T, Container>& stack);
Potremmo quindi scrivere:
int main()
{
using namespace std;
// construct an initial vector
vector<int> init { 7,6 };
// construct a stack using a copy of the initial vector's elements
// note that the stack's 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's 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;
}
per il quale l'uscita sarebbe:
8 1
7 2
6 3
5 4
4 5
3 6
2 7
1 8
6 5
7 4
* 3
Ecco l'elenco completo (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's elements
// note that the stack's 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's 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;
}
si verificherà una copia qui? –
@HumamHelfawi: Sì. Ho pensato che l'OP lo volesse, dal momento che ha detto "Ho bisogno di copiare". Puoi anche spostare il vettore se non hai più bisogno dell'originale. –
la semantica del movimento potrebbe entrare in immagine qui ?? – basav