@@ -9522,6 +9522,7 @@ Statement rules:
95229522* [ES.84: Don't (try to) declare a local variable with no name](#Res-noname)
95239523* [ES.85: Make empty statements visible](#Res-empty)
95249524* [ES.86: Avoid modifying loop control variables inside the body of raw for-loops](#Res-loop-counter)
9525+ * [ES.87: Don't add redundant `==` or `!=` to conditions](#Res-if)
95259526
95269527Arithmetic rules:
95279528
@@ -11211,6 +11212,70 @@ The loop control up front should enable correct reasoning about what is happenin
1121111212
1121211213Flag variables that are potentially updated (have a non-`const` use) in both the loop control iteration-expression and the loop body.
1121311214
11215+
11216+ ### <a name="es-if"></a>ES.87: Don't add redundant `==` or `!=` to conditions
11217+
11218+ ##### Reason
11219+
11220+ Doing so avoids verbosity and eliminats some opportunities for mistakes.
11221+ Helps make style consistent and conventional.
11222+
11223+ ##### Example
11224+
11225+ By definition, a condition in an `if`-statement, `while`-statement, or a `for`-statement selects between `true` and `false`.
11226+ A numeric value is compared to `0` and a pointer value to `nullptr`.
11227+
11228+ if (p) { ... } // means "if `p` is not `nullptr`, good
11229+ if (p!=0) { ... } // means "if `p` is not `nullptr`, redundant `!=0`; bad: don't use 0 for pointers
11230+ if (p!=nullptr) { ... } // means "if `p` is not `nullptr`, redundant `!=nullptr`, not recommended
11231+
11232+ Often, `if (p)` is read as "if `p` is valid" which is a direct expression of the programmers intent,
11233+ whereas `if (p!=nullptr)` would be a long-winded workaround.
11234+
11235+ ##### Example
11236+
11237+ This rule is especially useful when a declaration is used as a condition
11238+
11239+ if (auto pc = dynamic_cast<Circle>(ps)) { ... } // execute is ps points to a kind of Circle, good
11240+
11241+ if (auto pc = dynamic_cast<Circle>(ps); pc!=nullptr) { ... } // not recommended
11242+
11243+ ##### Example
11244+
11245+ Note that implicit conversions to bool are applied in conditions.
11246+ For example:
11247+
11248+ for (string s; cin>>s; ) v.push_back(s);
11249+
11250+ This invokes `istream`'s `operator bool()`.
11251+
11252+ ##### Example, bad
11253+
11254+ It has been noted that
11255+
11256+ if(strcmp(p1,p2)) { ... } // are the two C-style strings equal? (mistake!)
11257+
11258+ is a common beginners error.
11259+ If you use C-style strings, you must know the `<cstring>` functions well.
11260+ Being verbose and writing
11261+
11262+ if(strcmp(p1,p2)!=0) { ... } // are the two C-style strings equal? (mistake!)
11263+
11264+ would not save you.
11265+
11266+ ##### Note
11267+
11268+ The opposite condition is most easily expressed using a negation:
11269+
11270+ if (!p) { ... } // means "if `p` is`nullptr`, good
11271+ if (p==0) { ... } // means "if `p` is `nullptr`, redundant `!=0`; bad: don't use `0` for pointers
11272+ if (p==nullptr) { ... } // means "if `p` is `nullptr`, redundant `==nullptr`, not recommended
11273+
11274+ ##### Enforcement
11275+
11276+ Easy, just check for redundant use of `!=` and `==` in conditions.
11277+
11278+
1121411279## ES.expr: Expressions
1121511280
1121611281Expressions manipulate values.
0 commit comments