|
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