for(T* ptr = begin; ptr != end; ++ptr)
{ destroy(ptr); }
For many types, 'destroy' will be empty (for example integers), so this just turns into: for(T* ptr = begin; ptr != end; ++ptr)
{ }
Which is an empty loop and can be optimised away -- assuming we can prove it isn't an infinite loop! Which can be quite hard sometimes (in this case, it needs that 'end' is some multiple of sizeof(T) bigger than begin).Now in many cases you can prove these loops are finite, but in full generality it's quite hard, and it was considered easier to just let the compiler remove them.
He just told you. Because the only way to prevent it in general is to solve the halting problem.
> When does the loop exactly terminate?
In the general case this is provably impossible to determine.
(all you're seeing here is that the compiler authors felt no need to add special case logic to handle "trivial" cases of the halting problem. If the compiler sees any expression in a loop test, it assumes the loop will halt some of the time)
I'm aware. I think that I might have misunderstood what the optimization really does.