Reverse iteration with an unsigned loop variable

Viewed 16939

I've been discussing the use of size_t with colleagues. One issue that has come up is loops that decrement the loop variable until it reaches zero.

Consider the following code:

for (size_t i = n-1; i >= 0; --i) { ... }

This causes an infinite loop due to unsigned integer wrap-around. What do you do in this case? It seems far to easy to write the above code and not realise that you've made a mistake.

Two suggestions from our team are to use one of the following styles:

for (size_t i = n-1; i != -1 ; --i) { ... }

for (size_t i = n; i-- > 0 ; ) { ... }

But I do wonder what other options there are...

11 Answers

From C++20, you can use ranges, and views, like this:

namespace sv = std::views;
    
for (unsigned i : sv::iota(0u, n) | sv::reverse)
    std::cout << i << "\n";  

Here's a demo.

The code is very readable, and it completely avoids any issues with unsigned wrap-around behavior, since i only has values in the range [0,n).

Another solution (available on POSIX compliant systems) that I found to be simple and effective is to replace size_t with ssize_t:

for (ssize_t i = n-1; i >= 0; --i) { ... }

On non-POSIX systems, ssize_t is not difficult to typedef: Alternative to ssize_t on POSIX-unconformant systems

Related