
On 29/06/12 12:37, Thorsten Ottosen wrote:
On 28-06-2012 13:57, Dave Abrahams wrote:
on Sun Jun 24 2012, "Jeffrey Lee Hellrung, Jr." <jeffrey.hellrung-AT-gmail.com> wrote:
And, ultimately, if there's ultimately just one call to begin/end on the final adapted range (the common case?), both the present implementation of the Boost.Range adaptors and a lazy implementation would go through the same sequence of iterator constructions, right?
The lazy case is actually able to perform some "optimizations" like eliminating double-reverses. It's not at all clear that these tricks would improve performance in reality, though.
Well, I think we would be going too far if we tried to do that in the library. There is a difference between optimizing common use-cases and, ahem, strange uses.
That said, with some effort, it might be possible to join certain adaptors into one compound adaptor. For example
range | transformed( &Trans ) | filtered( &When )
may become one iterator type, hence simplyfying the task for the compiler.
Also, I'm inclined to think "lazy" is best for other reasons: it allows the cpu to work on one iterator object at a time, instead of interleaving construction of the two iterators all the time. For sufficiently small iterators the interleaving mechanism produces faster code on some architectures due to benefits in instruction
I agree that there is almost certainly room for improvement in this area without breaking backward compatibility. I'll try to find some time to look at this. pipelining. The result of this change is not obvious to me. The only sensible approach is to benchmark the alternatives.
I guess it would be a problem if the iterators are not cached, but recomputed; probably not a problem in practice.
If we are pushing the laziness to the extreme whereby the begin()/end() calls create the iterators we are also changing the exception semantics be delaying throws. I therefore tend to think that we would be better having lazy range adaption by the adaptors creating a class convertible to a range that captures and hence triggers the adaptor evaluation via implicit conversion. I proposed this on the list a few weeks ago. I see no reason to break backward compatibility by loosening the performance guarantees of begin()/end().
-Thorsten
Neil Groves