
I created a "bounded_iterator" concept that seems really useful. A bounded_iterator behaves just like a regular iterator, except that the termination condition can be checked by just casting the iterator to a bool. Here's an example: int array_range[] = { 1, 1, 2, 3, 5 }; for (bounded_iterator<int *> i(array_range); i; ++i) { std::fill_n(std::ostream_iterator<int>(std::cout), *i, *i); } I like it for the same reason that I like iterator_range: it frees the developer from having to worry about both a begin and an end iterator. It can be used as a wrapper for operations on a container or a sub-range. Just like iterator_range simplifies the invocation of functions for ranges, bounded_iterator simplifies the traversal of ranges. In my application I was storing lots of iterators in containers, and using bounded_iterator proved to be a better abstraction than storing iterator pairs or ranges. The main disadvantage to using a bounded_iterator is that it competes with the standard iterator concept, and it's usually more confusing to support many ways to do the same thing. Here is a simple implementation: template<typename base_iterator> class bounded_iterator : public boost::iterator_adaptor<bounded_iterator<base_iterator>, base_iterator> { base_iterator const end; typedef boost::iterator_adaptor<bounded_iterator, base_iterator> super_type; struct unspecified_bool_helper { int true_tag; }; typedef int unspecified_bool_helper::*unspecified_bool_type; public: template<typename source_iterator> bounded_iterator(source_iterator begin, source_iterator end) : super_type(begin), end(end) { } template<typename source_range> bounded_iterator(source_range &range) : super_type(boost::begin(range)), end(boost::end(range)) { } template<typename source_range> bounded_iterator(source_range const &range) : super_type(boost::begin(range)), end(boost::end(range)) { } operator unspecified_bool_type() const { return super_type::base() == end ? 0 : &unspecified_bool_helper::true_tag; } }; -- chad

From: Neal Becker 10 January 2008 12:16 To: boost@lists.boost.org Subject: Re: [boost] bounded_iterator
Sounds interesting.
What is the point of unspecified_bool_helper?
It's generally agreed that unspecified_bool_type should be a pointer-to-member of some class. unspecified_bool_helper is that class. If you use bounded_iterator as the class, then you have to consider what the "true" value is going to be. You either have to point at a member which you have introduced for the purpuse (which adds space overhead), or you have to point at an existing member - but once you have pointed at an existing member, then people can return access that member via the pointer. So if unspecified_bool_helper was declared as: typedef base_iterator bounded_iterator::*unspecified_bool_type; (which avoids the extra helper class), then Machiavelli could write: bounded_iterator::*base_iterator pm = it; it.*pm = new_end; I can't immediately see how Murphy could come to grief, but given his ingenuity, there may be a way. Using unspecified_bool_helper, there cannot be a problem. -- Martin Bonner Senior Software Engineer/Team Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com disclaimer

Maybe add these: template<typename range_type> inline bounded_iterator<typename boost::range_iterator<range_type>::type> make_bounded_iterator (range_type & r) { return bounded_iterator<typename boost::range_iterator<range_type>::type> (r); } template<typename range_type> inline bounded_iterator<typename boost::range_iterator<range_type>::type> make_bounded_iterator (range_type const& r) { return bounded_iterator<typename boost::range_iterator<range_type>::type> (r); } Now you can do: template<typename out_t, typename in_t> inline out_t Map (in_t const& in) const { out_t out (boost::size (in)); typename boost::range_iterator<out_t>::type o = boost::begin (out); typename bounded_iterator_type<in_t>::type i = make_bounded_iterator<in_t> (in); for (; i; ++i, ++o) *o = Map1 (*i); return out; }

Oops, forgot to send this: template<typename range_type> struct bounded_iterator_type { typedef bounded_iterator<typename boost::range_iterator<range_type>::type> type; }; Neal Becker wrote:
Maybe add these:
template<typename range_type> inline bounded_iterator<typename boost::range_iterator<range_type>::type> make_bounded_iterator (range_type & r) { return bounded_iterator<typename boost::range_iterator<range_type>::type> (r); }
template<typename range_type> inline bounded_iterator<typename boost::range_iterator<range_type>::type> make_bounded_iterator (range_type const& r) { return bounded_iterator<typename boost::range_iterator<range_type>::type> (r); }
Now you can do:
template<typename out_t, typename in_t> inline out_t Map (in_t const& in) const { out_t out (boost::size (in)); typename boost::range_iterator<out_t>::type o = boost::begin (out); typename bounded_iterator_type<in_t>::type i = make_bounded_iterator<in_t> (in);
for (; i; ++i, ++o) *o = Map1 (*i);
return out; }
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (3)
-
Chad Parry
-
Martin Bonner
-
Neal Becker