Reputation: 2907
I want to iterate all possible values of an integer. This code does not work as the termination condition never becomes false:
for (uint32_t i = 0; i <= 0xFFFFFFFF; i++)
std::cout << i << std::endl;
I've come up with this:
auto loopBody = [](uint32_t value)
{
std::cout << value << std::endl;
};
uint32_t last = 0xFFFFFFFF;
for (uint32_t i = 0; i < last; i++)
loopBody(i);
loopBody(last);
It is fairly ugly, though. Is there a prettier way to do this?
Upvotes: 5
Views: 2888
Reputation: 51930
You cannot check for the break condition in the loop header, since for that you would need to exclude the maximum value.
Instead, do the check in the loop body and leave the check in the header empty:
for (auto i = std::numeric_limits<int>::lowest(); ; ++i) {
std::cout << i << '\n';
if (i == std::numeric_limits<int>::max())
break;
}
With a do-while loop, you don't need to check inside the loop body, but you need to move the counter variable to the outer scope, and if you want to avoid undefined behavior, you can only use unsigned integer types:
auto i = std::numeric_limits<unsigned>::lowest();
do {
std::cout << i << '\n';
} while (i++ < std::numeric_limits<unsigned>::max());
Note that the i++
will overflow, but that only happens after acquiring the current value (we're using postfix increment.) With signed integers however, this overflow would be undefined behavior, and even though we're not using the value after the overflow occurs, undefined behavior can have unpredictable results, even before it actually occurred.
Upvotes: 1
Reputation: 96959
I would use something like this:
uint32_t i = 0;
do
{
// Your code here.
i++;
}
while (i != 0);
I personally find it more elegant than a solution involving std::numeric_limits
.
Upvotes: 5
Reputation: 20130
Well, it call for condition test at the end of the loop, which means using do {} while()
#include <limits>
#include <iostream>
int main() {
auto beg = std::numeric_limits<unsigned>::lowest();
auto end = std::numeric_limits<unsigned>::max();
std::cout << beg << " " << end << std::endl;
long long count = 0LL;
auto i = beg;
do {
++count;
if ((count % (1024LL*1024LL)) == 0)
std::cout << count << std::endl;
} while(i++ != end);
std::cout << count << std::endl;
return 0;
}
Upvotes: 1
Reputation: 1269
I would use std::numeric_limits
as it states your intent best.
int lowest = std::numeric_limits<int>::lowest();
int max = std::numeric_limits<int>::max();
for (int i = lowest; i < max; ++i)
cout << i << '\n';
cout << max << '\n';
or in a function see this Demo
#include <iostream>
#include <limits>
#include <functional>
template <class T>
void for_all(std::function<void(T)> fn)
{
T lowest = std::numeric_limits<T>::lowest();
T max = std::numeric_limits<T>::max();
for (T i{lowest}; i < max; ++i)
fn(i);
fn(max);
}
int main()
{
for_all<int>([](int i) {
std::cout << i << std::endl;
});
}
Edit: I edited the comparison
Edit 2: See comments. Props to kec ;-)
Upvotes: 0