开发者

C++ templates problem: convert to null

I have a Stack container class and I want to create instances of various types of Stacks. so I do this:开发者_如何学运维

template <typename T>
class MyStack
{
.
.
   T Pop()
   {
      if(!IsEmpty())
      {
         return data[top--];
      }
      else
      {
         return NULL; // I got error here
      }
 .
 .
}

When I try to use Stack like this:

MyStack<GraphNode> blacks;
GraphNode t = blacks.Pop();

I got this error:

conversion from ‘int’ to non-scalar type ‘GraphNode’ requested

But when I use a pointer type like Stack<GraphNode*> there is no problem. I know that NULL is 0 and I understand why error occurs... What is the elegant way to tell program that there is no data to return without changing the code? should I add something like an implicit type conversion operator to class? how?

NOTE: I'm not using STL


By returning a T by value, the contract of your function is that you will return a value. The two alternatives are to change the contract of your function (e.g. return a T* instead) or to fail to return by throwing an exception.

Personally, I think that it is acceptable and appropriate to throw an exception in this case. Returning a pointer, or talking a reference to overwrite and returning a boolean success value are both less clean solutions.

Especially if you provide a public IsEmpty() method there is no reason to choose a less clean solution. Clients that don't want to handle exceptions can make use of IsEmpty to avoid receiving the exception which becomes the equivalent of an assert.


The STL std::stack splits this functionality into top(), which returns a reference to the last element, and pop(). The behaviour is simply undefined if you use either of these and the stack is already empty (i.e. if empty() == true). This doesn't sound like a bad approach.


The canonical pop function returns void for this exact reason. Also, you didn't call the destructor of data[top], which is Bad™.

If in doubt, check the STL.


If you haven't read GoTW #8, you should do so now. It's devoted entirely to the question at hand -- how to design a stack. One of its most basic points is that the design you're currently using for pop can't be made exception safe.

The answer it gives to the question at hand (not necessarily a good one...) is to return a default-constructed T if the stack is empty:

T Pop()
{
  if(!IsEmpty())
  {
     return data[top--];
  }
  else
  {
     return T(); // No more error
  }
}

The problem with this is that in most cases, attempting to pop an empty stack indicates a logic error, and should not be allowed to proceed at all. You can debate endlessly between using an assert or throwing an exception, but there's rarely a value you can return that's really helpful (a possible exception being returning a NaN if you're dealing with F.P. numbers).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜