How would you fix this code?
template <typename T> void closed_range(T begin, T end)
{
for (T i = begin; i <= end; ++i) {
// do something
}
}
-
T is constrained to be an integer type, can be the wider of such types and can be signed or unsigned
-
begincan benumeric_limits<T>::min() -
endcan benumeric_limits<T>::max()(in which case++iwill overflow in the above code)
I’ve several ways, but none I really like.
Maybe,
Curses, my first attempt was wrong, and the fix above isn’t as pretty as I’d hoped. How about:
There’s no ambiguity with
std::advanceeven if T isn’t an integer type, sincestd::advancetakes 2 parameters. So the template would also work with for instance a random-access iterator, if for some reason you wanted a closed range of those.Or how about a bit of set theory? Obviously this is massive overkill if you’re only writing one loop over a closed range, but if it’s something that you want to do a lot, then it makes the loop code about right. Not sure about efficiency: in a really tight loop you might want make sure the call to
endofis hoisted:Output:
Be a bit careful using other operators on
omega<T>objects. I’ve only implemented the absolute minimum for the demonstration, andomega<T>implicitly converts toT, so you’ll find that you can write expressions which potentially throw away the “infiniteness” of omega objects. You could fix that by declaring (not necessarily defining) a full set of arithmetic operators; or by throwing an exception in the conversion if isInfinite is true; or just don’t worry about it on grounds that you can’t accidentally convert the result back to an omega, because the constructor is explicit. But for example,omega<int>(2) < endof(2)is true, butomega<int>(INT_MAX) < endof(INT_MAX)is false.