Refactor iterators and views allowing to pass them as temporaries.

Do not store pointers to ranges in iterators and views.

Implement copy ctors in iterators allowing to convert compatible
iterators.

In copy ctors use enable_if instead of static_assert.
This commit is contained in:
Adam Wulkiewicz 2021-06-05 00:35:47 +02:00
parent 2fc1a3fe8f
commit cad76bf9a0
11 changed files with 273 additions and 259 deletions

View File

@ -4,7 +4,7 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2020, Oracle and/or its affiliates. // Copyright (c) 2020-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -24,9 +24,10 @@
#include <boost/range/end.hpp> #include <boost/range/end.hpp>
#include <boost/range/difference_type.hpp> #include <boost/range/difference_type.hpp>
#include <boost/range/reference.hpp> #include <boost/range/reference.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp> #include <boost/range/value_type.hpp>
#include <boost/geometry/core/assert.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -66,31 +67,52 @@ public:
typedef typename base_type::difference_type difference_type; typedef typename base_type::difference_type difference_type;
/// Constructor including the range it is based on /// Constructor including the range it is based on
explicit inline closing_iterator(Range& range) explicit inline closing_iterator(Range const& range)
: m_range(&range) : m_iterator(boost::begin(range))
, m_iterator(boost::begin(range)) , m_begin(boost::begin(range))
, m_end(boost::end(range)) , m_end(boost::end(range))
, m_size(static_cast<difference_type>(boost::size(range))) , m_size(m_end - m_begin)
, m_index(0) , m_index(0)
{} {}
/// Constructor to indicate the end of a range /// Constructor to indicate the end of a range
explicit inline closing_iterator(Range& range, bool) explicit inline closing_iterator(Range const& range, bool)
: m_range(&range) : m_iterator(boost::end(range))
, m_iterator(boost::end(range)) , m_begin(boost::begin(range))
, m_end(boost::end(range)) , m_end(boost::end(range))
, m_size(static_cast<difference_type>(boost::size(range))) , m_size(m_end - m_begin)
, m_index((m_size == 0) ? 0 : m_size + 1) , m_index((m_size == 0) ? 0 : m_size + 1)
{} {}
/// Default constructor /// Default constructor
explicit inline closing_iterator() inline closing_iterator()
: m_range(NULL) : m_size(0)
, m_size(0)
, m_index(0) , m_index(0)
{} {}
template
<
typename OtherRange,
std::enable_if_t
<
std::is_convertible
<
typename boost::range_iterator<OtherRange const>::type,
typename boost::range_iterator<Range const>::type
>::value,
int
> = 0
>
inline closing_iterator(closing_iterator<OtherRange> const& other)
: m_iterator(other.m_iterator)
, m_begin(other.m_begin)
, m_end(other.m_end)
, m_size(other.m_size)
, m_index(other.m_index)
{}
private: private:
template <typename OtherRange> friend struct closing_iterator;
friend class boost::iterator_core_access; friend class boost::iterator_core_access;
inline reference dereference() const inline reference dereference() const
@ -105,8 +127,8 @@ private:
inline bool equal(closing_iterator<Range> const& other) const inline bool equal(closing_iterator<Range> const& other) const
{ {
return this->m_range == other.m_range BOOST_GEOMETRY_ASSERT(m_begin == other.m_begin && m_end == other.m_end);
&& this->m_index == other.m_index; return this->m_index == other.m_index;
} }
inline void increment() inline void increment()
@ -150,14 +172,14 @@ private:
inline void update_iterator() inline void update_iterator()
{ {
this->m_iterator = m_index <= m_size this->m_iterator = m_index <= m_size
? boost::begin(*m_range) + (m_index % m_size) ? m_begin + (m_index % m_size)
: boost::end(*m_range) : m_end
; ;
} }
Range* m_range; typename boost::range_iterator<Range const>::type m_iterator;
typename boost::range_iterator<Range>::type m_iterator; typename boost::range_iterator<Range const>::type m_begin;
typename boost::range_iterator<Range>::type m_end; typename boost::range_iterator<Range const>::type m_end;
difference_type m_size; difference_type m_size;
difference_type m_index; difference_type m_index;
}; };

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -16,8 +16,6 @@
#include <boost/iterator/iterator_facade.hpp> #include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -49,7 +47,7 @@ public:
typedef Iterator2 second_iterator_type; typedef Iterator2 second_iterator_type;
// default constructor // default constructor
concatenate_iterator() {} concatenate_iterator() = default;
// for begin // for begin
concatenate_iterator(Iterator1 it1, Iterator1 end1, concatenate_iterator(Iterator1 it1, Iterator1 end1,
@ -67,7 +65,13 @@ public:
typename OtherIt1, typename OtherIt1,
typename OtherIt2, typename OtherIt2,
typename OtherValue, typename OtherValue,
typename OtherReference typename OtherReference,
std::enable_if_t
<
std::is_convertible<OtherIt1, Iterator1>::value
&& std::is_convertible<OtherIt2, Iterator2>::value,
int
> = 0
> >
concatenate_iterator(concatenate_iterator concatenate_iterator(concatenate_iterator
< <
@ -80,15 +84,7 @@ public:
, m_end1(other.m_end1) , m_end1(other.m_end1)
, m_begin2(other.m_begin2) , m_begin2(other.m_begin2)
, m_it2(other.m_it2) , m_it2(other.m_it2)
{ {}
static const bool are_conv
= std::is_convertible<OtherIt1, Iterator1>::value
&& std::is_convertible<OtherIt2, Iterator2>::value;
BOOST_GEOMETRY_STATIC_ASSERT((are_conv),
"Other iterators have to be convertible to member iterators.",
OtherIt1, OtherIt2);
}
private: private:
friend class boost::iterator_core_access; friend class boost::iterator_core_access;

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020. // This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020 Oracle and/or its affiliates. // Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -18,6 +18,9 @@
#ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP #ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP #define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
#include <type_traits>
#include <boost/iterator/iterator_adaptor.hpp> #include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
@ -26,8 +29,11 @@
#include <boost/range/size.hpp> #include <boost/range/size.hpp>
#include <boost/range/value_type.hpp> #include <boost/range/value_type.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/iterators/base.hpp> #include <boost/geometry/iterators/base.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -49,7 +55,7 @@ struct ever_circling_iterator :
Iterator Iterator
> >
{ {
friend class boost::iterator_core_access; ever_circling_iterator() = default;
explicit inline ever_circling_iterator(Iterator begin, Iterator end, explicit inline ever_circling_iterator(Iterator begin, Iterator end,
bool skip_first = false) bool skip_first = false)
@ -69,6 +75,17 @@ struct ever_circling_iterator :
this->base_reference() = start; this->base_reference() = start;
} }
template
<
typename OtherIterator,
std::enable_if_t<std::is_convertible<OtherIterator, Iterator>::value, int> = 0
>
inline ever_circling_iterator(ever_circling_iterator<OtherIterator> const& other)
: m_begin(other.m_begin)
, m_end(other.m_end)
, m_skip_first(other.m_skip_first)
{}
/// Navigate to a certain position, should be in [start .. end], if at end /// Navigate to a certain position, should be in [start .. end], if at end
/// it will circle again. /// it will circle again.
inline void moveto(Iterator it) inline void moveto(Iterator it)
@ -78,6 +95,8 @@ struct ever_circling_iterator :
} }
private: private:
template <typename OtherIterator> friend struct ever_circling_iterator;
friend class boost::iterator_core_access;
inline void increment(bool possibly_skip = true) inline void increment(bool possibly_skip = true)
{ {
@ -125,8 +144,8 @@ private:
public: public:
/// Constructor including the range it is based on /// Constructor including the range it is based on
explicit inline ever_circling_range_iterator(Range& range) explicit inline ever_circling_range_iterator(Range const& range)
: m_range(&range) : m_begin(boost::begin(range))
, m_iterator(boost::begin(range)) , m_iterator(boost::begin(range))
, m_size(boost::size(range)) , m_size(boost::size(range))
, m_index(0) , m_index(0)
@ -134,15 +153,35 @@ public:
/// Default constructor /// Default constructor
explicit inline ever_circling_range_iterator() explicit inline ever_circling_range_iterator()
: m_range(NULL) : m_size(0)
, m_size(0)
, m_index(0) , m_index(0)
{} {}
template
<
typename OtherRange,
std::enable_if_t
<
std::is_convertible
<
typename boost::range_iterator<OtherRange const>::type,
typename boost::range_iterator<Range const>::type
>::value,
int
> = 0
>
inline ever_circling_range_iterator(ever_circling_range_iterator<OtherRange> const& other)
: m_begin(other.m_begin)
, m_iterator(other.m_iterator)
, m_size(other.m_size)
, m_index(other.m_index)
{}
typedef typename base_type::reference reference; typedef typename base_type::reference reference;
typedef typename base_type::difference_type difference_type; typedef typename base_type::difference_type difference_type;
private: private:
template <typename OtherRange> friend struct ever_circling_range_iterator;
friend class boost::iterator_core_access; friend class boost::iterator_core_access;
inline reference dereference() const inline reference dereference() const
@ -157,8 +196,8 @@ private:
inline bool equal(ever_circling_range_iterator<Range> const& other) const inline bool equal(ever_circling_range_iterator<Range> const& other) const
{ {
return this->m_range == other.m_range BOOST_GEOMETRY_ASSERT(m_begin == other.m_begin);
&& this->m_index == other.m_index; return this->m_index == other.m_index;
} }
inline void increment() inline void increment()
@ -209,11 +248,11 @@ private:
m_index += m_size; m_index += m_size;
} }
m_index = m_index % m_size; m_index = m_index % m_size;
this->m_iterator = boost::begin(*m_range) + m_index; this->m_iterator = m_begin + m_index;
} }
Range* m_range; typename boost::range_iterator<Range const>::type m_begin;
typename boost::range_iterator<Range>::type m_iterator; typename boost::range_iterator<Range const>::type m_iterator;
difference_type m_size; difference_type m_size;
difference_type m_index; difference_type m_index;
}; };

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -10,13 +10,14 @@
#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP #ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP #define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
#include <type_traits> #include <type_traits>
#include <boost/iterator/iterator_facade.hpp> #include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -58,7 +59,7 @@ public:
typedef InnerIterator inner_iterator_type; typedef InnerIterator inner_iterator_type;
// default constructor // default constructor
flatten_iterator() {} flatten_iterator() = default;
// for begin // for begin
flatten_iterator(OuterIterator outer_it, OuterIterator outer_end) flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
@ -77,7 +78,13 @@ public:
typename OtherOuterIterator, typename OtherInnerIterator, typename OtherOuterIterator, typename OtherInnerIterator,
typename OtherValue, typename OtherValue,
typename OtherAccessInnerBegin, typename OtherAccessInnerEnd, typename OtherAccessInnerBegin, typename OtherAccessInnerEnd,
typename OtherReference typename OtherReference,
std::enable_if_t
<
std::is_convertible<OtherOuterIterator, OuterIterator>::value
&& std::is_convertible<OtherInnerIterator, InnerIterator>::value,
int
> = 0
> >
flatten_iterator(flatten_iterator flatten_iterator(flatten_iterator
< <
@ -91,21 +98,7 @@ public:
: m_outer_it(other.m_outer_it), : m_outer_it(other.m_outer_it),
m_outer_end(other.m_outer_end), m_outer_end(other.m_outer_end),
m_inner_it(other.m_inner_it) m_inner_it(other.m_inner_it)
{ {}
static const bool are_conv
= std::is_convertible
<
OtherOuterIterator, OuterIterator
>::value
&& std::is_convertible
<
OtherInnerIterator, InnerIterator
>::value;
BOOST_GEOMETRY_STATIC_ASSERT((are_conv),
"Other iterators have to be convertible to member iterators.",
OtherOuterIterator, OtherInnerIterator);
}
flatten_iterator& operator=(flatten_iterator const& other) flatten_iterator& operator=(flatten_iterator const& other)
{ {

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -19,7 +19,6 @@
#include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tags.hpp> #include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/dispatch/point_iterator.hpp> #include <boost/geometry/iterators/dispatch/point_iterator.hpp>
@ -263,28 +262,24 @@ private:
: point_iterator::iterator_adaptor_(base_it) {} : point_iterator::iterator_adaptor_(base_it) {}
public: public:
inline point_iterator() {} inline point_iterator() = default;
template <typename OtherGeometry> template
<
typename OtherGeometry,
std::enable_if_t
<
std::is_convertible
<
typename detail::point_iterator::iterator_type<OtherGeometry>::type,
typename detail::point_iterator::iterator_type<Geometry>::type
>::value,
int
> = 0
>
inline point_iterator(point_iterator<OtherGeometry> const& other) inline point_iterator(point_iterator<OtherGeometry> const& other)
: point_iterator::iterator_adaptor_(other.base()) : point_iterator::iterator_adaptor_(other.base())
{ {}
static const bool is_conv
= std::is_convertible<
typename detail::point_iterator::iterator_type
<
OtherGeometry
>::type,
typename detail::point_iterator::iterator_type
<
Geometry
>::type
>::value;
BOOST_GEOMETRY_STATIC_ASSERT((is_conv),
"Other iterator has to be convertible to member iterator.",
point_iterator<OtherGeometry>);
}
}; };

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -13,7 +13,6 @@
#include <iterator> #include <iterator>
#include <type_traits> #include <type_traits>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/iterators/point_iterator.hpp> #include <boost/geometry/iterators/point_iterator.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -39,23 +38,24 @@ private:
: base_type(base_it) {} : base_type(base_it) {}
public: public:
inline point_reverse_iterator() {} inline point_reverse_iterator() = default;
template <typename OtherGeometry> template
inline <
point_reverse_iterator(point_reverse_iterator<OtherGeometry> const& other) typename OtherGeometry,
: base_type(other.base()) std::enable_if_t
{
static const bool is_conv = std::is_convertible
< <
std::reverse_iterator<point_iterator<Geometry> >, std::is_convertible
std::reverse_iterator<point_iterator<OtherGeometry> > <
>::value; std::reverse_iterator<point_iterator<OtherGeometry> >,
std::reverse_iterator<point_iterator<Geometry> >
BOOST_GEOMETRY_STATIC_ASSERT((is_conv), >::value,
"Other iterator has to be convertible to member iterator.", int
point_reverse_iterator<OtherGeometry>); > = 0
} >
inline point_reverse_iterator(point_reverse_iterator<OtherGeometry> const& other)
: base_type(other.base())
{}
}; };

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -18,7 +18,6 @@
#include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tags.hpp> #include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp> #include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>
@ -285,25 +284,24 @@ public:
// correct iterator category. // correct iterator category.
typedef std::bidirectional_iterator_tag iterator_category; typedef std::bidirectional_iterator_tag iterator_category;
inline segment_iterator() {} inline segment_iterator() = default;
template <typename OtherGeometry> template
<
typename OtherGeometry,
std::enable_if_t
<
std::is_convertible
<
typename detail::segment_iterator::iterator_type<OtherGeometry>::type,
typename detail::segment_iterator::iterator_type<Geometry>::type
>::value,
int
> = 0
>
inline segment_iterator(segment_iterator<OtherGeometry> const& other) inline segment_iterator(segment_iterator<OtherGeometry> const& other)
: base(*other.base_ptr()) : base(*other.base_ptr())
{ {}
static const bool is_conv
= std::is_convertible<
typename detail::segment_iterator::iterator_type
<
OtherGeometry
>::type,
typename detail::segment_iterator::iterator_type<Geometry>::type
>::value;
BOOST_GEOMETRY_STATIC_ASSERT((is_conv),
"Other iterator has to be convertible to member iterator.",
segment_iterator<OtherGeometry>);
}
inline segment_iterator& operator++() // prefix inline segment_iterator& operator++() // prefix
{ {

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020. // This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020 Oracle and/or its affiliates. // Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -43,21 +43,24 @@ namespace detail
template <typename Range> template <typename Range>
struct closing_view struct closing_view
{ {
using iterator = closing_iterator<Range>;
using const_iterator = closing_iterator<Range const>;
// Keep this explicit, important for nested views/ranges // Keep this explicit, important for nested views/ranges
explicit inline closing_view(Range& r) explicit inline closing_view(Range& r)
: m_range(r) : m_begin(r)
, m_end(r, true)
{} {}
typedef closing_iterator<Range> iterator; inline const_iterator begin() const { return m_begin; }
typedef closing_iterator<Range const> const_iterator; inline const_iterator end() const { return m_end; }
inline const_iterator begin() const { return const_iterator(m_range); } inline iterator begin() { return m_begin; }
inline const_iterator end() const { return const_iterator(m_range, true); } inline iterator end() { return m_end; }
inline iterator begin() { return iterator(m_range); } private:
inline iterator end() { return iterator(m_range, true); } iterator m_begin;
private : iterator m_end;
Range& m_range;
}; };
} }

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020. // This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -28,6 +28,7 @@
#include <boost/geometry/views/reversible_view.hpp> #include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/views/closeable_view.hpp> #include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/util/order_as_direction.hpp> #include <boost/geometry/util/order_as_direction.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry { namespace boost { namespace geometry {
@ -39,53 +40,30 @@ namespace detail {
template <typename Geometry> template <typename Geometry>
struct normalized_view struct normalized_view
{ {
static const bool is_const = std::is_const<Geometry>::value; using range_type = typename detail::range_type<Geometry>::type;
using range = util::transcribe_const_t<Geometry, range_type>;
//typedef typename ring_type<Geometry>::type ring_type; using reversible_type = typename reversible_view
typedef typename detail::range_type<Geometry>::type range_type;
typedef std::conditional_t
<
is_const,
range_type const,
range_type
> range;
typedef typename
reversible_view
< <
range, range,
order_as_direction order_as_direction
< <
geometry::point_order<Geometry>::value geometry::point_order<Geometry>::value
>::value >::value
>::type reversible_type; >::type;
typedef std::conditional_t using reversible = util::transcribe_const_t<Geometry, reversible_type>;
<
is_const,
reversible_type const,
reversible_type
> reversible;
typedef typename using closeable_type = typename closeable_view
closeable_view
< <
reversible, reversible,
geometry::closure<Geometry>::value geometry::closure<Geometry>::value
>::type closeable_type; >::type;
typedef std::conditional_t using closeable = util::transcribe_const_t<Geometry, closeable_type>;
<
is_const,
closeable_type const,
closeable_type
> closeable;
explicit inline normalized_view(range & r) explicit inline normalized_view(range & r)
: m_reversible(r) : m_closeable(reversible_type(r))
, m_closeable(m_reversible)
{} {}
typedef typename boost::range_iterator<closeable>::type iterator; typedef typename boost::range_iterator<closeable>::type iterator;
@ -98,7 +76,6 @@ struct normalized_view
inline iterator end() { return boost::end(m_closeable); } inline iterator end() { return boost::end(m_closeable); }
private: private:
reversible_type m_reversible;
closeable_type m_closeable; closeable_type m_closeable;
}; };

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020. // This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020 Oracle and/or its affiliates. // Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -18,6 +18,7 @@
#ifndef BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP #ifndef BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP
#define BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP #define BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
#include <boost/range/end.hpp> #include <boost/range/end.hpp>
@ -40,20 +41,23 @@ namespace boost { namespace geometry
template <typename Range> template <typename Range>
struct identity_view struct identity_view
{ {
typedef typename boost::range_iterator<Range const>::type const_iterator; using const_iterator = typename boost::range_iterator<Range const>::type;
typedef typename boost::range_iterator<Range>::type iterator; using iterator = typename boost::range_iterator<Range>::type;
explicit inline identity_view(Range& r) explicit inline identity_view(Range& r)
: m_range(r) : m_begin(boost::begin(r))
, m_end(boost::end(r))
{} {}
inline const_iterator begin() const { return boost::begin(m_range); } inline const_iterator begin() const { return m_begin; }
inline const_iterator end() const { return boost::end(m_range); } inline const_iterator end() const { return m_end; }
inline iterator begin() { return boost::begin(m_range); } inline iterator begin() { return m_begin; }
inline iterator end() { return boost::end(m_range); } inline iterator end() { return m_end; }
private :
Range& m_range; private:
iterator m_begin;
iterator m_end;
}; };
#if defined(_MSC_VER) #if defined(_MSC_VER)

View File

@ -5,6 +5,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -14,21 +17,49 @@
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <sstream>
#include <string>
#include <geometry_test_common.hpp> #include <geometry_test_common.hpp>
#include <boost/geometry/iterators/closing_iterator.hpp> #include <boost/geometry/iterators/closing_iterator.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/io/wkt/read.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/range/adaptor/transformed.hpp> #include <boost/range/adaptor/transformed.hpp>
void test_concept()
{
std::vector<int> v = {1, 2, 3};
using iterator = bg::closing_iterator<std::vector<int>>;
using const_iterator = bg::closing_iterator<std::vector<int> const>;
iterator it, it2(v);
const_iterator cit, cit2(v);
BOOST_CHECK((std::is_same<decltype(*it2), const int&>::value));
BOOST_CHECK((std::is_same<decltype(*cit2), const int&>::value));
it = it2;
cit = cit2;
BOOST_CHECK_EQUAL(*it, 1);
BOOST_CHECK_EQUAL(*cit, 1);
cit = ++it;
BOOST_CHECK_EQUAL(*it, 2);
BOOST_CHECK_EQUAL(*cit, 2);
// This is ok because both of these iterators are in fact const iterators
it = ++cit;
BOOST_CHECK_EQUAL(*it, 3);
BOOST_CHECK_EQUAL(*cit, 3);
// Check compilations, it is (since Oct 2010) random access
it--;
--it;
it += 2;
it -= 2;
}
// The closing iterator should also work on normal std:: containers // The closing iterator should also work on normal std:: containers
void test_empty_non_geometry() void test_empty_non_geometry()
{ {
@ -39,48 +70,32 @@ void test_empty_non_geometry()
std::vector<int> const std::vector<int> const
> closing_iterator; > closing_iterator;
closing_iterator it(v); closing_iterator it(v);
closing_iterator end(v, true); closing_iterator end(v, true);
std::ostringstream out; BOOST_CHECK(it == end);
for (; it != end; ++it)
{
out << *it;
}
BOOST_CHECK_EQUAL(out.str(), "");
} }
void test_non_geometry() void test_non_geometry()
{ {
std::vector<int> v; std::vector<int> v = {1, 2, 3};
v.push_back(1); std::vector<int> closed_v = { 1, 2, 3, 1 };
v.push_back(2);
v.push_back(3);
typedef bg::closing_iterator typedef bg::closing_iterator
< <
std::vector<int> const std::vector<int> const
> closing_iterator; > closing_iterator;
closing_iterator it(v); closing_iterator it(v);
closing_iterator end(v, true); closing_iterator end(v, true);
std::ostringstream out; BOOST_CHECK(std::equal(it, end, closed_v.begin(), closed_v.end()));
for (; it != end; ++it)
{
out << *it;
}
BOOST_CHECK_EQUAL(out.str(), "1231");
} }
void test_transformed_non_geometry() void test_transformed_non_geometry()
{ {
std::vector<int> v; std::vector<int> v = {-1, -2, -3};
v.push_back(-1); std::vector<int> closed_v = { 1, 2, 3, 1 };
v.push_back(-2);
v.push_back(-3);
typedef boost::transformed_range typedef boost::transformed_range
< <
@ -97,78 +112,50 @@ void test_transformed_non_geometry()
closing_iterator it(v2); closing_iterator it(v2);
closing_iterator end(v2, true); closing_iterator end(v2, true);
std::ostringstream out; BOOST_CHECK(std::equal(it, end, closed_v.begin(), closed_v.end()));
for (; it != end; ++it)
{
out << *it;
}
BOOST_CHECK_EQUAL(out.str(), "1231");
} }
template <typename P>
void test_geometry()
template <typename Geometry>
void test_geometry(std::string const& wkt)
{ {
Geometry geometry; bg::model::ring<P> geometry = { {1, 1}, {1, 4}, {4, 4}, {4, 1} };
bg::read_wkt(wkt, geometry); bg::model::ring<P> closed = { {1, 1}, {1, 4}, {4, 4}, {4, 1}, {1, 1} };
typedef bg::closing_iterator<Geometry const> closing_iterator;
using closing_iterator = bg::closing_iterator<bg::model::ring<P> const>;
auto pred = [](P const& p1, P const& p2)
{
return bg::get<0>(p1) == bg::get<0>(p2) && bg::get<1>(p1) == bg::get<1>(p2);
};
// 1. Test normal behaviour // 1. Test normal behaviour
{ {
closing_iterator it(geometry); closing_iterator it(geometry);
closing_iterator end(geometry, true); closing_iterator end(geometry, true);
std::ostringstream out; BOOST_CHECK((std::equal(it, end, closed.begin(), closed.end(), pred)));
for (; it != end; ++it)
{
out << " " << bg::get<0>(*it) << bg::get<1>(*it);
}
BOOST_CHECK_EQUAL(out.str(), " 11 14 44 41 11");
// Check compilations, it is (since Oct 2010) random access
it--;
--it;
it += 2;
it -= 2;
} }
// 2: check copy behaviour // 2: check copy behaviour
{ {
typedef typename boost::range_iterator<Geometry const>::type normal_iterator; bg::model::ring<P> copy;
Geometry copy;
std::copy<closing_iterator>( std::copy(closing_iterator(geometry), closing_iterator(geometry, true),
closing_iterator(geometry), std::back_inserter(copy));
closing_iterator(geometry, true),
std::back_inserter(copy));
std::ostringstream out; BOOST_CHECK((std::equal(copy.begin(), copy.end(), closed.begin(), closed.end(), pred)));
for (normal_iterator cit = boost::begin(copy); cit != boost::end(copy); ++cit)
{
out << " " << bg::get<0>(*cit) << bg::get<1>(*cit);
}
BOOST_CHECK_EQUAL(out.str(), " 11 14 44 41 11");
} }
} }
template <typename P>
void test_all()
{
test_empty_non_geometry();
test_non_geometry();
test_transformed_non_geometry();
test_geometry<bg::model::ring<P> >("POLYGON((1 1,1 4,4 4,4 1))");
}
int test_main(int, char* []) int test_main(int, char* [])
{ {
test_all<bg::model::d2::point_xy<double> >(); test_concept();
test_empty_non_geometry();
test_non_geometry();
test_transformed_non_geometry();
test_geometry<bg::model::d2::point_xy<double>>();
return 0; return 0;
} }