[Range] Range adaptors and compatibility with non-adapted iterators

Consider something like this: themap_type::iterator search_for (int val) { return boost::find_if (themap|map_values, my_predicate(val)); } The return from the function chokes because the adapted iterator type cannot be convered back to the original type of iterator in the parent collection. This is more general. If I wasn't just returning through but using the result within the function, how do I test against end to see if find_if was successful? auto it2= boost::find_if (themap|map_values, my_predicate(val)); if (it2 == themap::end()) // same problem! This seems to be a problem with any algorithm that returns an iterator or otherwise makes the iterators used within the algorithm visible outside of it, even if such usage is just as an "end" flag and not really used to locate the element within the original collection for subsequent iteration. Am I missing something? Is there a good reason why the filtered iterator can't give up the inner original iterator? How do you use range adaptors in these situations? —John

Hi John,
2012/1/11 John M. Dlugosz
Consider something like this:
themap_type::iterator search_for (int val) { return boost::find_if (themap|map_values, my_predicate(val)); }
... Is there a good reason why the filtered iterator can't give up the inner original iterator? How do you use range adaptors in these situations?
I think this situation's better way is wrap by function template and
use boost::optional.
example:
#include <iostream>
#include <map>
#include
======================== Akira Takahashi blog : http://d.hatena.ne.jp/faith_and_brave/

On 1/10/2012 11:48 PM, Akira Takahashi wrote:
I think this situation's better way is wrap by function template and use boost::optional.
I agree that returning the the item (using optional, if necessary) is better in this case than returning an iterator, when the iterator is only used as a pointer that will not be used for traversing in any manner. Nice idea about wrapping the function (algorithm) first, and then using the range adaptor on the outer. —John

Hi,
2012/1/11 John M. Dlugosz
Consider something like this:
themap_type::iterator search_for (int val) { return boost::find_if (themap|map_values, my_predicate(val)); }
The return from the function chokes because the adapted iterator type cannot be convered back to the original type of iterator in the parent collection.
Adapted iterators have base() method that returns underlying iterator. For every level of adaptation just call base() on resulting iterator to get to the base one. Cheers, Simon -- Szymon Gatner The Lordz Games Studio www.thelordzgamesstudio.com

On 1/11/2012 4:11 AM, Szymon Gatner wrote:
Adapted iterators have base() method that returns underlying iterator. For every level of adaptation just call base() on resulting iterator to get to the base one.
That is exactly what I needed, thanks. Perhaps someone could update the documentation? I'm not set up at all for Boost development or submitting patches. http://www.boost.org/doc/libs/1_47_0/libs/range/doc/html/range/reference/ada... “ 1. Applying operator|() to a range R (always left argument) and a range adapter RA (always right argument) yields a new range type which may not conform to the same range concept as R. 2. The return-type of operator|() is otherwise unspecified. ” ==> The return type … has a member function called base() …

On 1/11/2012 4:11 AM, Szymon Gatner wrote:
Adapted iterators have base() method that returns underlying iterator. For every level of adaptation just call base() on resulting iterator to get to the base one.
Hmm, I think that is making use of implementation-specific details that are documented as off-limits. The docs say that the return type of operator| is unspecified. If you happen to know that it's really built using Boost iterator facade and Boost iterator adaptors, sure you can use the features of those. Now the iterators made using the adaptors library have various features: (1) essential features needed by something that works as an adapted iterator; (2) gee-wiz extra features beyond that; (3) incidentals due to the particular implementation. Since the iterator on an adapted range is logically an adapted iterator in principle, it makes sense that the "essential features" would be the same. That is, the implementation could promise the features in (1) above without breaking the abstraction or getting cornered if the implementation changes, or when migrating to a similar feature that is part of a future standard range library. Looking at the Iterators library, it seems that the iterator_adaptor does have a base() member but the iterator_facade does not.

Den 11-01-2012 06:23, John M. Dlugosz skrev:
Consider something like this:
themap_type::iterator search_for (int val) { return boost::find_if (themap|map_values, my_predicate(val)); }
[snip]
auto it2= boost::find_if (themap|map_values, my_predicate(val)); if (it2 == themap::end()) // same problem!
As stated, iter.base() should work. That said, it is still somewhat of a usability problem. We should seriously consider to add A. an implicit conversion operator to the underlying iterator (explicit in C++0x) B. overloaded comparison opearators between iterators and wrapped iterators. -Thorsten
participants (4)
-
Akira Takahashi
-
John M. Dlugosz
-
Szymon Gatner
-
Thorsten Ottosen