Boost logo

Boost :

From: Reece Dunn (msclrhd_at_[hidden])
Date: 2004-01-02 09:03:08


Dan W. wrote:
>Thorsten Ottosen wrote:
>
>>I recall that one could choose not to remove preconditions
>>from release builds.
>
>In public interfaces no, as the preconditions are in the extracted header,
>but the preconditions in private functions, and all non-public,
>implementation classes in the object code, preconditions are gone.
>Wouldn't make sense to keep them without source code to debug.

Surely, it would make sense to keep them in (disregarding the source code
problem for now). Consider:

int main()
{
   std::cout << "Enter a number: ";
   float f = 0.0f;
   std::cin >> f;
   std::cout << "square root = " << sqrt( f );
   return( 0 );
}

Granted, you could add an explicit check:

   std::cin >> f;
   if( f < 0.0f ) std::cout << "error: cannot perform square root on a
negative nuimber!";
   else // ...

But this defeats the purpose of having the preconditions in the first place?

Defining sqrt to be something like:

float sqrt( float val )
{
   precondition( val >= 0.0f, "cannot take square root of a negative number"
);
   return( _sqrt( val ));
}

where precondition will throw an exception, allows for:

int main()
{
   try
   {
      std::cout << "Enter a number: ";
      float f = 0.0f;
      std::cin >> f;
      std::cout << "square root = " << sqrt( f );
   }
   catch( std::exception e )
   {
      std::cout << "error: " << e.what() << '\n';
      retutn( -1 );
   }
   return( 0 );
}

Yes, this version has a try-catch block around the code - but you should
have that anyway? It will also deal with other errors in a consistent way,
like if you allocated memory using new (which throws by default) and the
allocation failed.

I suppose you could write an assert that called a user-defined function upon
failure. I am thinking here from the PoV of a user running the program. You
would want to:
[1] Display a message that is understandable to the user
[2] Collect as much information as possible for the developers (__FILE__ and
__LINE__ macros?)
e.g.
#define precondition( c, err ) if( !( c )) throw( invariant_exception( err,
__FILE__, __LINE__ ));
or something similar.

The implementation of invariant_exception (or the assert handler - although
this seems more like a C solution than a C++ one) could then perform a stack
dump, along with writing the exception string, file name and line number to
a file (a dump() function?). It could then give an error message something
like:

   error: attempting to use a null pointer
   please report this to the developers (exception.txt)

Having the invariants exposed in the header would aid in self-documentation
(which I am in favor of), as well as allowing the compiler to make several
checks at compile time (like the sqrt( -1 ) example). On the other hand, it
will detract from simple one line function declerations.
   float sqrt( float );
   float sin( float );
   // ...

Regards,
Reece

_________________________________________________________________
Express yourself with cool new emoticons http://www.msn.co.uk/specials/myemo


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk