Reputation: 1407
I have below code:
#include<iostream>
#include <vector>
using namespace std;
template<class T>
class Stack
{
private:
vector<T> stack;
public:
T Pop()
{
if (stack.size()!=0)
{
T temp;
temp=stack[stack.size()-1];
stack.erase(stack.begin()+stack.size()-1);
return temp;
}
else
//return nothing
^^^^^^^^^^^^^^^^
//How i can do above by code
}
In pop function: I want if stack.size==0
; Pop function return nothing
How I can do it?
Upvotes: 3
Views: 7681
Reputation: 54979
This is basically a question of how to handle non-total functions—functions that are not necessarily defined for all possible inputs. There are many ways to go about it, though none of them is type-safe:
Have two separate functions for retrieving and erasing the top element of the stack, much like std::stack::top()
and std::stack::pop()
.
Use a reference parameter and return a bool
indicating whether an element was returned:
bool pop(T& value) {
if (stack.empty())
return false;
value = stack.back();
stack.pop_back();
return true;
}
The caller can write:
T value;
if (stack.pop(value)) {
use(value);
}
Return a boost::optional<T>
.
Return a default-constructed T
instance. This requires that T
be default-constructible, which is already imposed by some std::vector
member functions.
Throw an exception, documenting that a precondition was violated.
Leave the behaviour of popping an empty stack undefined.
I recommend #1, #2, or #3, depending on preference and what fits best with the surrounding code.
Upvotes: 6
Reputation: 45410
You probably still want to do the same way as std::stack that to split into std::stack::top
and std::stack::pop
. You don't want to pop
to return a value.
Here is the explaination from http://cpptruths.blogspot.com.au/2005/10/why-does-stdstackpop-returns-void.html
http://www.sgi.com/tech/stl/stack.html explains
[3] One might wonder why pop() returns void, instead of value_type. That is, why must one use top() and pop() to examine and remove the top element, instead of combining the two in a single member function? In fact, there is a good reason for this design. If pop() returned the top element, it would have to return by value rather than by reference: return by reference would create a dangling pointer. Return by value, however, is inefficient: it involves at least one redundant copy constructor call. Since it is impossible for pop() to return a value in such a way as to be both efficient and correct, it is more sensible for it to return no value at all and to require clients to use top() to inspect the value at the top of the stack.
std::stack < T > is a template. If pop() returned the top element, it would have to return by value rather than by reference as per the of above explanation. That means, at the caller side it must be copied in an another T type of object. That involves a copy constructor or copy assignment operator call. What if this type T is sophisticated enough and it throws an exception during copy construction or copy assignment? In that case, the rvalue, i.e. the stack top (returned by value) is simply lost and there is no other way to retrieve it from the stack as the stack's pop operation is successfully completed!
The practice way is to use pop()
, top()
, empty()
together:
T top()
{
return stack[size()-1];
}
void pop()
{
stack.erase(stack.begin()+stack.size()-1);
}
usage:
if (!stack.empty())
{
T t = top();
pop();
}
Upvotes: 2
Reputation: 332
You can also do something like declare the pop method as void or even better, bool to get the status of the operation and pass the T type as an argument by reference in order to store the result in it:
bool Pop (T& item)
{
if (stack.size() != 0)
{
// your code
item = temp; // you can even use item instead of temp from the begining
return true;
}
return false;
}
Upvotes: 1
Reputation: 2985
Here's one way of doing this. The idea is to package a Boolean flag together with the result in a tuple. The flag indicates whether there is a result or not. Notice though that the current implementation requires T to be default constructible.
template<class T>
class Stack
{
private:
std::vector<T> stack;
public:
typedef std::tuple<bool, T> return_t;
void Push(const T& t)
{
stack.push_back(t);
}
return_t Pop()
{
if (stack.size()!=0)
{
T temp;
temp=stack[stack.size()-1];
stack.erase(stack.begin()+stack.size()-1);
return std::make_tuple(true, temp);
}
else
return std::make_tuple(false, T());
}
};
int main()
{
Stack<int> my_stack;
bool has_result;
int result;
my_stack.Push(5);
std::tie(has_result, result) = my_stack.Pop();
std::cout << "has result = " << has_result << "\n";
std::cout << "result = " << result << "\n";
std::tie(has_result, result) = my_stack.Pop();
std::cout << "has_result = " << has_result << "\n";
}
Upvotes: 1
Reputation: 409176
There are a couple of alternatives. One is to return an instance of T
constructed with the standard constructor:
return T();
Another way would be to return a special sentinel wrapper object, that can be implicitly converted to T
, and have a comparison operator so the user can check it.
Upvotes: 1