Vague about returning in a stack template
I am implementing a generic set (with an array) in C ++ and am confused about what to return in this situation:
template <class T>
T Stack<T>::pop(void) {
if (size != 0) {
return items[size - 1];
size--;
} else {
cerr << "Cannot pop from empty stack." << endl;
return ???;
}
}
template <class T>
T Stack<T>::peek(void) {
if (size != 0)
return items[size - 1];
else {
cerr << "Cannot peek from empty stack." << endl;
return ???;
}
}
What are my options here? I think it would be messy to do something like declare a new variable T and return it. I am drawing a blank.
source to share
It depends on how you want the behavior (protocol) of your class. Since you are logging into the error stream there, I am assuming that you consider this an error condition to be called pop()
onto an empty stack. The standard C ++ signaling error method is exception. Something like that:
template <class T>
T Stack<T>::pop(void) {
if (size != 0) {
size--;
return items[size];
} else {
throw std::invalid_argument("Cannot pop from empty stack.");
}
}
An alternative would be to say it pop()
has a precondition, "the stack is not empty". Precondition violation is usually undefined, so you can simply assume that the stack is not empty. This is a useful approach for high performance code:
template <class T>
T Stack<T>::pop(void) {
asssert(size > 0); // not necessary, but it good practice to assert preconditions
size--;
return items[size];
}
The above two approaches assume that calling pop()
on an empty stack is an error, that is, it shouldn't. If you want this to be a valid operation with a well-defined result, you have several other parameters.
Returns a flag indicating success:
template <class T>
std::pair<T, bool> Stack<T>::pop(void) {
if (size != 0) {
size--;
return std::make_pair(items[size], true);
} else {
return std::make_pair(T(), false); // requires T to be default-constructible
}
}
Return boost::optional
:
template <class T>
boost::optional<T> Stack<T>::pop(void) {
if (size != 0) {
size--;
return items[size];
} else {
return boost::none;
}
}
Revert the default built T
:
template <class T>
T Stack<T>::pop(void) {
if (size != 0) {
size--;
return items[size];
} else {
return T();
}
}
source to share