
David Abrahams wrote:
Thorsten Ottosen <tottosen@dezide.com> writes:
1. leave the return type as it is.
2. return an iterator_range describing the range [found,end) this allows us to do stuff like
namespace br = boost::ranges; br::erase( rng, br::unique(rng) );
3. inspired by John Torjo's range lib, provide a whole list of possible return values:
[snip]
2 is the answer for me.
the default would be the range [found,end), but the you can pick different slices or simply iterators. In the above scheme, "found" is the iterator normally returnes by the algorithm, "next" means boost::next(found) and "prior" means boost::prior(found).
And that works for ranges without bidirectional iterators, e.g. slist?
"prior" can of course not work with bidirectional iterators.
The advantage of the latter approach is
- flexibility/power - safety (we can tjeck that next(found) and prior(found) stays in range)
The disadvantage is that it will require twice as many overloads in C++03 (since we can't put defaults template arguments in function templates).
And it's complex.
implementation wise or interface wise?
I'm wary of introducing any such complexity without a strong catalog of use cases.
basically it makes splitting of ranges way easier and safer. assume I want to find the first occurence of 5 and then copy the range [begin,found] (that is, [begin,next(found)) ) somewhere: std::vector<int> v = ...; std::vector<int>::iterator i = find( v, 5 ); if( i != v.end() ) { ++i; copy( v.begin(), i, out ); } vs copy( find<return_begin_next>( v, 5 ), out ); (*) If found == v.end(), the returned ranges are empty and so you completely avoid forgetting about checking for the end iterator. Having only (2) we can still, however, do a little better than above: copy( find( c, 5 ).advance_end(1), out ) but now we can't be sure we don't iterator past the end. Thus we would be forced to create a temporary. -Thorsten (*) without much extra work, I could probably get a generalized version like xx_next<N> xx_prior<N> to work.