Make osrm::util::range a model of SinglePassRangeConcept

References:
- http://www.boost.org/doc/libs/1_63_0/libs/range/doc/html/range/concepts/single_pass_range.html
This commit is contained in:
Michael Krasnyk 2017-01-02 09:38:46 +01:00 committed by Moritz Kobitzsch
parent b8e13d9b1b
commit 8645d8c7fc

View File

@ -2,6 +2,7 @@
#define INTEGER_RANGE_HPP #define INTEGER_RANGE_HPP
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <type_traits> #include <type_traits>
@ -12,6 +13,50 @@ namespace osrm
namespace util namespace util
{ {
// Ported from Boost.Range 1.56 due to required fix
// https://github.com/boostorg/range/commit/9e6bdc13ba94af4e150afae547557a2fbbfe3bf0
// Can be removed after dropping support of Boost < 1.56
template <typename Integer>
class integer_iterator : public boost::iterator_facade<integer_iterator<Integer>,
Integer,
boost::random_access_traversal_tag,
Integer>
{
typedef boost::iterator_facade<integer_iterator<Integer>,
Integer,
boost::random_access_traversal_tag,
Integer>
base_t;
public:
typedef typename base_t::value_type value_type;
typedef typename base_t::difference_type difference_type;
typedef typename base_t::reference reference;
typedef std::random_access_iterator_tag iterator_category;
integer_iterator() : m_value() {}
explicit integer_iterator(value_type x) : m_value(x) {}
private:
void increment() { ++m_value; }
void decrement() { --m_value; }
void advance(difference_type offset) { m_value += offset; }
bool equal(const integer_iterator &other) const { return m_value == other.m_value; }
reference dereference() const { return m_value; }
difference_type distance_to(const integer_iterator &other) const
{
return std::is_signed<value_type>::value
? (other.m_value - m_value)
: (other.m_value >= m_value)
? static_cast<difference_type>(other.m_value - m_value)
: -static_cast<difference_type>(m_value - other.m_value);
}
friend class ::boost::iterator_core_access;
value_type m_value;
};
// Warning: do not try to replace this with Boost's irange, as it is broken on Boost 1.55: // Warning: do not try to replace this with Boost's irange, as it is broken on Boost 1.55:
// auto r = boost::irange<unsigned int>(0, 15); // auto r = boost::irange<unsigned int>(0, 15);
// std::cout << r.size() << std::endl; // std::cout << r.size() << std::endl;
@ -19,28 +64,21 @@ namespace util
template <typename Integer> class range template <typename Integer> class range
{ {
private:
const Integer last;
Integer iter;
public: public:
range(Integer start, Integer end) noexcept : last(end), iter(start) typedef integer_iterator<Integer> const_iterator;
{ typedef integer_iterator<Integer> iterator;
BOOST_ASSERT_MSG(start <= end, "backwards counting ranges not suppoted");
static_assert(std::is_integral<Integer>::value, "range type must be integral");
}
// Iterable functions range(Integer begin, Integer end) : iter(begin), last(end) {}
const range &begin() const noexcept { return *this; }
const range &end() const noexcept { return *this; } iterator begin() const noexcept { return iter; }
Integer front() const noexcept { return iter; } iterator end() const noexcept { return last; }
Integer back() const noexcept { return last - 1; } Integer front() const noexcept { return *iter; }
Integer back() const noexcept { return *last - 1; }
std::size_t size() const noexcept { return static_cast<std::size_t>(last - iter); } std::size_t size() const noexcept { return static_cast<std::size_t>(last - iter); }
// Iterator functions private:
bool operator!=(const range &) const noexcept { return iter < last; } iterator iter;
void operator++() noexcept { ++iter; } iterator last;
Integer operator*() const noexcept { return iter; }
}; };
// convenience function to construct an integer range with type deduction // convenience function to construct an integer range with type deduction