views:

544

answers:

8

I found the following rule in a coding standards sheet :

Do not rely on implicit conversion to bool in conditions.

if (ptr) // wrong

if (ptr != NULL) // ok

How reasonable/usefull is this rule?

How much overload on the compiled code?

A: 

This won't affect the compiled code at all.

As for how useful it is - it'll certainly aid comprehension for people coming from languages such as Java/C#. It'll make it more explicit what you're checking for. It'll throw a warning if you start comparing ints to NULL (and thereby indicate that you're hazy about the type of the variable in question). I personally prefer the first form, but it's not a totally unreasonable requirement.

Jon Bright
+3  A: 

In most cases, it's not horrible, but it can be more readable if you type exactly what you mean.

Matthew Scharley
I can't find a reference immediately, but I don't think what you say is correct. I think the standard defines NULL as being equivalent to zero. Either way, I couldn't name a single system where that isn't the case...
Jon Bright
NULL is 0 (up to casting) on all remotely standards compliant systems.Some esoteric implementations might compile pointer 0 to something other than 0, but it's still 0 in the code.
Captain Segfault
http://c-faq.com/null/ptrtest.html disagrees.
wrang-wrang
What Capt. Segfault said is a good summary.
wrang-wrang
Jon Bright
I stand corrected, the language covers up this implementation detail. That said, not all systems use 0 internally, but most do because it enforces null dereference errors by causing memory errors.
Matthew Scharley
Well, the standard says "The macro NULL is an implementation-defined C++ null pointer constant". And also, in pointer conversions, "A null pointer constant is an integral constant expression rvalue of integer type that evaluates to zero."
Rüdiger Hanke
strager
A: 

Sometimes I think this rule can be broken, when e.g. dealing with standard libraries which return int instead of bool (for compatibility with C89).

However, this rule generally leads to easier-to-understand code. It's even enforced in languages like C# and it's not complained about too much there, so there are no major downsides to following this rule other than having to get used to it.

strager
A: 

A rule that adds zero benefit is a rule you can profitably delete.

soru
But there are benefits, not least of all to readability. Just because you don't like it doesn't mean it doesn't have it's upsides.
Matthew Scharley
how does it improve readability though?
jalf
I neither like it not dislike it, just don't think it has a valid reason to exist as a rule.You only get about 40 or 50 rules in a manageable coding standard - don't waste them.
soru
I'm not clear that it doesn't add benefit. For pointers it's marginal, but I've dealt with a lot of code where folks do this all the time with ints and it's a damned nuisance when it has to be changed.
Michael Kohne
It also adds a risk... if you meant to type "if (ptr != NULL)" and you accidentally drop the exclamation point and type "if (ptr = NULL)" instead, you've added a rather nasty bug into your program. If you type "if (ptr)", you don't run that risk. (OTOH, you should get a compiler warning in any case)
Jeremy Friesner
However one could similarly mean to write "if (!ptr)" and accidentally miss the keystroke, resulting in "if (ptr)". A different bug, but just as nasty, and which the compiler cannot warn about.
TheUndeadFish
@Jeremey: Another coding rule: "Always place the rvalue on the left of the equality operators so that it will fail to compile if you make the mistake -> "if (NULL = ptr)" ;)
Richard Corden
+8  A: 

In the strictest sense, you can rely on implicit conversions to bool. Backwards compatibility with C demands it.

Thus it becomes a question of code readability. Often the purpose of code standards is to enforce a sameness to the code style, whether you agree with the style or not. If you're looking at someone else's standard and wondering if you should incorporate it into your own, go ahead and debate it - but if it's your company's long-standing rule, learn to live with it.

Mark Ransom
Yea, the worst thing is someone follows it while others not
lz_prgmr
A: 

I dislike this rule very much. It is idiomatic in C++ to use the implicit conversion to bool for pointer types (and of course for boolean types). IMO, it is much easier to read

bool conditionMet = false;

while (!conditionMet) // read as "while condition is not met"
{
    /* do something */
}

than it is to read this:

bool conditionMet = false;

while (conditionMet == false) // read as "while conditionMet is false"
{
    /* do something */
}

It's the same for pointers. Also, by introducing the unnecessary comparison, you're introducing yet another opportunity to mistype and end up with an assignment instead of a comparison, which of course will produce undesired results. In cases where you're using ints as bools, as with old C code, I think you should also use the implicit conversion to bool.

rmeador
I'd argue that for `bool` types it's not coercing anything (despite what the compiler may or may not do). For pointer types it's a little more grey. With anything else, you should be using a comparison operator.
Matthew Scharley
+4  A: 

That rule puts you in a bind if you ever want to use a class that has an implicit conversion to bool, such as std::istream. This code reads a word at a time from a file until EOF is reached:

std::ifstream file("foo.txt");
std::string word;

while (file >> word)
{
    // do stuff
}

The stream extraction operator returns a reference to the file stream, which is implicitly converted to bool to indicate whether the stream is still in a good state. When you reach the end of the file, the test fails. Your coding standard precludes you from using this common construct.

For pointer types, it's not a big deal. The compiler will probably produce about the same code for the implicit conversion to bool and the explicit test against NULL. It's a matter of taste at that point - neither one is "better" in an absolute sense. The coding standard is simply trying to enforce a consistent style.

With that in mind, you should absolutely follow the coding standard when dealing with built-in types (pointers, ints, etc.). If you run into a similar situation to the above with a class having a legitimate conversion to bool, I would raise the issue with your teammates.

Kristo
It should be noted that there is some debate as to whether constructs such as the one you've shown are a good idea or not. Hiding non-type conversion functionality behind an overloaded operator falls into the category of 'neat trick', but does it really make things easier to read? Or does it actually make them harder to read until you know about the trick in the library? Similarly with the >> and << operators on the input and output streams - why do bitwise operations do i/o in this special case? It's utterly unreadable until you know the trick.
Michael Kohne
It's in the online FAQ (http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.4) and it's pretty common code, so a good C++ programmer needs to be able to understand it. I do agree, however, the we can debate the merits of it until the cows come home. :) It served as a convenient counterexample for the OP's coding standard.
Kristo
You can still use this feature while following the rule: `while(static_cast<bool>(file>>word))`. At that point the style guide author might want to reword the rule: "Do not rely on the *default* implicit conversion from pointer to bool in conditions", which is probably what was intended in the first place based on the example given. Or he might want to require that the `static_cast` be there, to remind readers that a conversion occurs. You don't need to use implicit conversions, in order to use conversions.
Steve Jessop
This is an interesting case. Maybe the coding standard should add an exception for where the implicit conversion results in a call to a conversion operator, as in essence a type with such a conversion operator is intended to operate exactly as a bool object. It doesn't make sense to have "b == true" (where b is a boolean) so this logically applies to the conversion operator case.
Richard Corden
@onebyone: I look at the original code and I think "this reads words from a file", because I know the standard library (like any C++ programmer should; that construct is idiomatic). I look at your code and I think you're trying to force it to do something it doesn't want to do, and that makes me scared. If I saw your code in real life, I'd probably spend 10 minutes trying to verify that it wasn't a major bug, and once satisfied that it wasn't broken, replace it with Kristo's version.
rmeador
I'm just saying how to follow the rule, not advocating the code. That's why the style guide should be updated to address it one way or the other. If you haven't read the guide, you won't be dealing with the code either. If you have, then local idioms have priority over general C++ style. The author of this style guide appears to want programmers to pay attention when conversions occur. I might not have that goal myself, but if people find my code snippet confusing, that suggests they don't readily understand what conversion the usual idiom performs. If anything that supports the author's case.
Steve Jessop
A: 

That's an impressively stupid rule.

if (ptr != NULL) // ok

then why not

 if ((ptr != NULL)==true)
Martin Beckett
Because comparing bools to bools is just stupid. Comparing a pointer to a constant is less so.
Matthew Scharley