Re: When int meets bool over ==
* Gennaro Prota:
On Sun, 25 Feb 2007 06:31:55 CST, Alf P. Steinbach wrote:
In short, unless the type of v is bool (and perhaps not even then),
don't compare v to true or false: instead of "v == true" write
just "v"
(or for other type than bool, perhaps "!!v", an idiom to suppress
silly-warnings), and instead of "v == false" write "!v".
Why do you say "perhaps not even then"?
Writing "v == true" is a habit that's not, in general, portable to
other boolean types or other languages.
For example, if C++ 'bool' is changed to Windows 'BOOL', as might
happen in code that's maintained, then in an otherwise correct
program there are more possible values than 'FALSE' and 'TRUE'.
Then there is the operator precedence question.
Consider e.g.
if( a && b == true ) { ... }
which in C++ has very different effect from
if( a && b ) { ... }
The full-blown corresponding "=="-notation would be
if( ((a == true) && (b == true)) == true ) { ... }
Which illustrates a third point, that comparision with 'false' or
'true' is redundant.
[...]
Second, in order to communicate an error code, a function that
returns a
logically boolean success/failure often has logical false denoting
success, and logical true denoting failure.
In such cases I use to introduce a named constant, e.g.:
const bool failure( true );
if( f() != failure )
...
Yes, naming is good, when the values can be named. But, I used
'main' as an example. Note that 'main' has result type 'int'. On
most systems 0 (logical false) as 'main' result means success and /
any/ other value (logical true), not just a single value, means
failure. Hence naming of individual values can work for providing
the value in the first place, but not for checking the returned value
in a concise and dependable way.
A naming scheme that takes this into account:
template< typename T >
bool failed( T const& v ) { return !v; }
template< typename T >
bool succeeded( T const& v ) { return !!v; }
...
if( failed( f() ) ) { throw std::runtime_error( "f failed" ); }
With the definition
bool throwX( char const s[] ) { throw std::runtime_error( s ); }
this allows one to write e.g.
succeeded( f() ) || throwX( "f failed" );
which as I understand it most people think is horrible but which I
personally like a lot (concise, allows clear formatting, assertion-
like).
I once experimented with another notation for converting error codes
to exceptions, like
Thrower( "f failed" ) << f();
and subsequently
f() >> Thrower( "f failed" );
but as I recall it's not as easy to automatically add e.g. file and
line information via macros. Anyway, there were practical problems.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]