Eiffel "Gotchas"

19 May 1997


Oops!

Gotcha #5 - Answer and Explanation

Here's the question again:

Suppose you wish to test that a pointer is not null before passing it to an external routine. On some Eiffel compilers, the following code will compile and run, but it won't work as expected. What's wrong?

   p: POINTER
   ...
   if p = void then
      print("Nil pointer.%N")
   else
      some_external_routine(p)
   end

The POINTER class is expanded, so entities of type POINTER can never be void references. Therefore, it makes no sense to test the value against 'void', as this test will always return false.

It does make sense to test against the default pointer value (all bits set to zero). Class GENERAL has a feature for just this purpose, which will remove the "gotcha":

   if p = default_pointer then ...

So why do some Eiffel compilers allow the test "if p = void"? It's because there can be generic classes where an actual generic type may be either expanded or reference - the author of the generic class doesn't know how it will be used. It is often useful to be able to say "this object must not be a void reference if it happens to be non-expanded", and this has been done by loosening up the type rules to allow "if e = void" for 'e' an entity of a generically-derived type. For implementation reasons, some compilers (e.g. Visual Eiffel) allow the looser version for any entity of expanded type (even in the absence of genericity).

[I believe the commercial vendors all agree on allowing this loosening in the presence of genericity, although an alternative solution is avaliable in SmallEiffel, which allows, for example:

   require e.is_expanded_type or else e /= void

This only works because SmallEiffel does not evaluate the target of 'is_expanded_type' ('e' in this example).]


Eiffel and NICE are registered trademarks of the Nonprofit International Consortium for Eiffel.

Eiffel "Gotchas"