Express intent
Reason
Unless the intent of some code is stated (e.g., in names or comments), it is impossible to tell whether the code does what it is supposed to do.
Example
gsl::index i = 0;
while (i < v.size()) {
// ... do something with v[i] ...
}
The intent of "just" looping over the elements of v is not expressed here. The implementation detail of an index is exposed (so that it might be misused), and i outlives the scope of the loop, which might or might not be intended. The reader cannot know from just this section of code.
Better:
for (const auto& x : v) { /* do something with the value of x */ }
Now, there is no explicit mention of the iteration mechanism, and the loop operates on a reference to const elements so that accidental modification cannot happen. If modification is desired, say so:
for (auto& x : v) { /* modify x */ }
For more details about for-statements, see ES.71. Sometimes better still, use a named algorithm. This example uses the for_each from the Ranges TS because it directly expresses the intent:
for_each(v, [](int x) { /* do something with the value of x */ });
for_each(par, v, [](int x) { /* do something with the value of x */ });
The last variant makes it clear that we are not interested in the order in which the elements of v are handled.
A programmer should be familiar with
- The guidelines support library
- The ISO C++ Standard Library
- Whatever foundation libraries are used for the current project(s)
Note
Alternative formulation: Say what should be done, rather than just how it should be done.
Note
Some language constructs express intent better than others.
Example
If two ints are meant to be the coordinates of a 2D point, say so:
draw_line(int, int, int, int); // obscure: (x1,y1,x2,y2)? (x,y,h,w)? ...?
// need to look up documentation to know
draw_line(Point, Point); // clearer
Enforcement
Look for common patterns for which there are better alternatives
- simple
forloops vs. range-forloops f(T*, int)interfaces vs.f(span<T>)interfaces- loop variables in too large a scope
- naked
newanddelete - functions with many parameters of built-in types
There is a huge scope for cleverness and semi-automated program transformation.