
Hi, A few days ago, I made a comment about std::distance() and std::advance() being reimplemented for the new style iterator concepts. Dave said that patches are welcome. So I sat down and wrote some preliminary versions of the two functions. They are in the attached file. The file parses cleanly, but I have not tried instantiating any of the templates yet. I have a question, though. Does it make sense to implement boost::distance for single pass iterators? Is there anything useful that could be done with the resulting information? Aside from that, I'd be happy to receive any suggestions for code improvement, adherence to Boost standards, and so on. Sebastian Redl

Sebastian Redl <sebastian.redl@getdesigned.at> writes:
Hi,
A few days ago, I made a comment about std::distance() and std::advance() being reimplemented for the new style iterator concepts. Dave said that patches are welcome.
So I sat down and wrote some preliminary versions of the two functions. They are in the attached file. The file parses cleanly, but I have not tried instantiating any of the templates yet.
I have a question, though. Does it make sense to implement boost::distance for single pass iterators? Is there anything useful that could be done with the resulting information?
Sure, you could (destructively) count the number of elements remaining in a stream. Single-pass iterators are the traversal equivalent of input iterators, and I'm pretty sure std::distance works on those.
Aside from that, I'd be happy to receive any suggestions for code improvement, adherence to Boost standards, and so on.
<snip>
template <class BidirectionalTraversableIterator, class Distance> void advance(boost::bidirectional_traversal_tag, BidirectionalTraversableIterator &i, Distance n)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ That's "traversal," not "traversable" -- Dave Abrahams Boost Consulting www.boost-consulting.com

Sebastian Redl wrote:
Hi,
A few days ago, I made a comment about std::distance() and std::advance() being reimplemented for the new style iterator concepts. Dave said that patches are welcome.
So I sat down and wrote some preliminary versions of the two functions. They are in the attached file. The file parses cleanly, but I have not tried instantiating any of the templates yet.
I have a question, though. Does it make sense to implement boost::distance for single pass iterators? Is there anything useful that could be done with the resulting information?
I have the same question. Range Library Proposal requires Forward, but 'std::distance' requires Input.
Aside from that, I'd be happy to receive any suggestions for code improvement, adherence to Boost standards, and so on.
Sebastian Redl
------------------------------------------------------------------------
#ifndef BOOST_ITERATOR_ITERATOR_OPS_HPP #define BOOST_ITERATOR_ITERATOR_OPS_HPP
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_concepts.hpp>
namespace boost { namespace detail {
template <class IncrementableIterator, class Distance> void advance(boost::incrementable_traversal_tag, IncrementableIterator &i, Distance n) { boost::function_requires< boost_concepts::IncrementableIteratorConcept< IncrementableIterator > >();
while(n) { ++i; --n; } }
FWIW, it seems the new Concept Check library is under construction (cvs head).
// Single pass and forward traversal is the same.
template <class BidirectionalTraversableIterator, class Distance> void advance(boost::bidirectional_traversal_tag, BidirectionalTraversableIterator &i, Distance n) { boost::function_requires< boost_concepts::BidirectionalTraversalConcept< BidirectionalTraversableIterator > >();
if(n > 0) { while(n) { ++i; --n; } } else { while(n) { --i; ++n; } } }
Can't forward it to 'std::advance'?
template <class RandomAccessTraversableIterator, class Distance> void advance(boost::random_access_traversal_tag, RandomAccessTraversableIterator &i, Distance n) { boost::function_requires< boost_concepts::RandomAccessTraversalConcept< RandomAccessTraversableIterator > >();
i += n; } }
// A replacement for std::advance that uses the new iterator categories. template <class IncrementableIterator, class Distance> void advance(IncrementableIterator &i, Distance n) { typedef BOOST_DEDUCED_TYPENAME boost::iterator_traversal< IncrementableIterator >::type traversal; detail::advance(traversal(), i, n); }
namespace detail { template <class SinglePassIterator> BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassIterator>::difference_type distance(boost::single_pass_traversal_tag, SinglePassIterator first, SinglePassIterator last) { boost::function_requires< boost_concepts::SinglePassIteratorConcept< SinglePassIterator > >();
BOOST_DEDUCED_TYPENAME std::iterator_traits<SinglePassIterator>::difference_type n = 0; while(first != last) { ++first; ++n; } return n; }
Can't forward it to 'std::distance'?
// Forward and bidirectional are the same.
template <class RandomAccessTraversableIterator> BOOST_DEDUCED_TYPENAME std::iterator_traits< RandomAccessTraversableIterator>::difference_type distance(boost::random_access_traversal_tag, RandomAccessTraversableIterator first, RandomAccessTraversableIterator last) { boost::function_requires< boost_concepts::RandomAccessTraversalConcept< RandomAccessTraversableIterator > >();
return last - first; } }
// A replacement for std::distance that uses the new iterator categories. template <class SinglePassIterator> BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassIterator>::difference_type distance(SinglePassIterator first, SinglePassIterator last) { typedef BOOST_DEDUCED_TYPENAME boost::iterator_traversal< SinglePassIterator >::type traversal; return detail::distance(traversal(), first, last); } }
Can give the difference_type to 'detail::distance' by using boost::type or explicit template parameter, which makes the code cute?
#endif
IMHO, std::advance is conceptually redundant. First <boost/next_prior.hpp> should be patched with your implementation if possible? Also, I think this 'distance' might be contributed to Boost.Range, which has really 'boost::distance'(cvs head). The current implementation just forwards it to 'std::distance'. -- Shunsuke Sogame

Shunsuke Sogame wrote:
FWIW, it seems the new Concept Check library is under construction (cvs head).
Hmm ... if it's scheduled for 1.35 then I'd better take a look.
Can't forward it to 'std::advance'?
Can't forward it to 'std::distance'?
Good point. Possibly the std versions have some special knowledge about some iterators, too.
Can give the difference_type to 'detail::distance' by using boost::type or explicit template parameter, which makes the code cute?
I could, but does it actually make the code shorter or more readable? It doesn't seem like it to me.
IMHO, std::advance is conceptually redundant.
How so? It's a useful utility for advancing non-random-access iterators more than one step quickly.
First <boost/next_prior.hpp> should be patched with your implementation if possible?
I'm not sure about that. Since they are utilities specifically for the new iterator concepts, I think they should go into the iterator library.
Also, I think this 'distance' might be contributed to Boost.Range, which has really 'boost::distance'(cvs head). The current implementation just forwards it to 'std::distance'.
Sounds good. New version coming up once I've got me a Boost CVS and checked out the new concepts. Thanks, Sebastian

Sebastian Redl wrote:
Shunsuke Sogame wrote:
FWIW, it seems the new Concept Check library is under construction (cvs head).
Hmm ... if it's scheduled for 1.35 then I'd better take a look.
Can't forward it to 'std::advance'?
Can't forward it to 'std::distance'?
Good point. Possibly the std versions have some special knowledge about some iterators, too.
Can give the difference_type to 'detail::distance' by using boost::type or explicit template parameter, which makes the code cute?
I could, but does it actually make the code shorter or more readable? It doesn't seem like it to me.
IMHO, std::advance is conceptually redundant.
How so? It's a useful utility for advancing non-random-access iterators more than one step quickly.
First <boost/next_prior.hpp> should be patched with your implementation if possible?
I'm not sure about that. Since they are utilities specifically for the new iterator concepts, I think they should go into the iterator library.
I prefer <boost/next_prior.hpp> to 'std::advance'. That is nothing but a style(or optimization) issue, though. <boost/next_prior.hpp> also can be patched with your 'advance'. Regards, -- Shunsuke Sogame
participants (3)
-
David Abrahams
-
Sebastian Redl
-
Shunsuke Sogame