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) 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -24,9 +24,10 @@
#include <boost/range/end.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/reference.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/assert.hpp>
namespace boost { namespace geometry
{
@ -66,31 +67,52 @@ public:
typedef typename base_type::difference_type difference_type;
/// Constructor including the range it is based on
explicit inline closing_iterator(Range& range)
: m_range(&range)
, m_iterator(boost::begin(range))
explicit inline closing_iterator(Range const& range)
: m_iterator(boost::begin(range))
, m_begin(boost::begin(range))
, m_end(boost::end(range))
, m_size(static_cast<difference_type>(boost::size(range)))
, m_size(m_end - m_begin)
, m_index(0)
{}
/// Constructor to indicate the end of a range
explicit inline closing_iterator(Range& range, bool)
: m_range(&range)
, m_iterator(boost::end(range))
explicit inline closing_iterator(Range const& range, bool)
: m_iterator(boost::end(range))
, m_begin(boost::begin(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)
{}
/// Default constructor
explicit inline closing_iterator()
: m_range(NULL)
, m_size(0)
inline closing_iterator()
: m_size(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:
template <typename OtherRange> friend struct closing_iterator;
friend class boost::iterator_core_access;
inline reference dereference() const
@ -105,8 +127,8 @@ private:
inline bool equal(closing_iterator<Range> const& other) const
{
return this->m_range == other.m_range
&& this->m_index == other.m_index;
BOOST_GEOMETRY_ASSERT(m_begin == other.m_begin && m_end == other.m_end);
return this->m_index == other.m_index;
}
inline void increment()
@ -150,14 +172,14 @@ private:
inline void update_iterator()
{
this->m_iterator = m_index <= m_size
? boost::begin(*m_range) + (m_index % m_size)
: boost::end(*m_range)
? m_begin + (m_index % m_size)
: m_end
;
}
Range* m_range;
typename boost::range_iterator<Range>::type m_iterator;
typename boost::range_iterator<Range>::type m_end;
typename boost::range_iterator<Range const>::type m_iterator;
typename boost::range_iterator<Range const>::type m_begin;
typename boost::range_iterator<Range const>::type m_end;
difference_type m_size;
difference_type m_index;
};

View File

@ -1,6 +1,6 @@
// 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 Adam Wulkiewicz, on behalf of Oracle
@ -16,8 +16,6 @@
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
@ -49,7 +47,7 @@ public:
typedef Iterator2 second_iterator_type;
// default constructor
concatenate_iterator() {}
concatenate_iterator() = default;
// for begin
concatenate_iterator(Iterator1 it1, Iterator1 end1,
@ -67,7 +65,13 @@ public:
typename OtherIt1,
typename OtherIt2,
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
<
@ -80,15 +84,7 @@ public:
, m_end1(other.m_end1)
, m_begin2(other.m_begin2)
, 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:
friend class boost::iterator_core_access;

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020-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
@ -18,6 +18,9 @@
#ifndef 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_categories.hpp>
#include <boost/range/begin.hpp>
@ -26,8 +29,11 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/iterators/base.hpp>
namespace boost { namespace geometry
{
@ -49,7 +55,7 @@ struct ever_circling_iterator :
Iterator
>
{
friend class boost::iterator_core_access;
ever_circling_iterator() = default;
explicit inline ever_circling_iterator(Iterator begin, Iterator end,
bool skip_first = false)
@ -69,6 +75,17 @@ struct ever_circling_iterator :
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
/// it will circle again.
inline void moveto(Iterator it)
@ -78,6 +95,8 @@ struct ever_circling_iterator :
}
private:
template <typename OtherIterator> friend struct ever_circling_iterator;
friend class boost::iterator_core_access;
inline void increment(bool possibly_skip = true)
{
@ -125,8 +144,8 @@ private:
public:
/// Constructor including the range it is based on
explicit inline ever_circling_range_iterator(Range& range)
: m_range(&range)
explicit inline ever_circling_range_iterator(Range const& range)
: m_begin(boost::begin(range))
, m_iterator(boost::begin(range))
, m_size(boost::size(range))
, m_index(0)
@ -134,15 +153,35 @@ public:
/// Default constructor
explicit inline ever_circling_range_iterator()
: m_range(NULL)
, m_size(0)
: m_size(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::difference_type difference_type;
private:
template <typename OtherRange> friend struct ever_circling_range_iterator;
friend class boost::iterator_core_access;
inline reference dereference() const
@ -157,8 +196,8 @@ private:
inline bool equal(ever_circling_range_iterator<Range> const& other) const
{
return this->m_range == other.m_range
&& this->m_index == other.m_index;
BOOST_GEOMETRY_ASSERT(m_begin == other.m_begin);
return this->m_index == other.m_index;
}
inline void increment()
@ -209,11 +248,11 @@ private:
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>::type m_iterator;
typename boost::range_iterator<Range const>::type m_begin;
typename boost::range_iterator<Range const>::type m_iterator;
difference_type m_size;
difference_type m_index;
};

View File

@ -1,6 +1,6 @@
// 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 Adam Wulkiewicz, on behalf of Oracle
@ -10,13 +10,14 @@
#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
#include <type_traits>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
@ -58,7 +59,7 @@ public:
typedef InnerIterator inner_iterator_type;
// default constructor
flatten_iterator() {}
flatten_iterator() = default;
// for begin
flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
@ -77,7 +78,13 @@ public:
typename OtherOuterIterator, typename OtherInnerIterator,
typename OtherValue,
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
<
@ -91,21 +98,7 @@ public:
: m_outer_it(other.m_outer_it),
m_outer_end(other.m_outer_end),
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)
{

View File

@ -1,6 +1,6 @@
// 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 Adam Wulkiewicz, on behalf of Oracle
@ -19,7 +19,6 @@
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/dispatch/point_iterator.hpp>
@ -263,28 +262,24 @@ private:
: point_iterator::iterator_adaptor_(base_it) {}
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)
: 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)
// 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 Adam Wulkiewicz, on behalf of Oracle
@ -13,7 +13,6 @@
#include <iterator>
#include <type_traits>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
namespace boost { namespace geometry
@ -39,23 +38,24 @@ private:
: base_type(base_it) {}
public:
inline point_reverse_iterator() {}
inline point_reverse_iterator() = default;
template <typename OtherGeometry>
inline
point_reverse_iterator(point_reverse_iterator<OtherGeometry> const& other)
: base_type(other.base())
{
static const bool is_conv = std::is_convertible
template
<
typename OtherGeometry,
std::enable_if_t
<
std::reverse_iterator<point_iterator<Geometry> >,
std::reverse_iterator<point_iterator<OtherGeometry> >
>::value;
BOOST_GEOMETRY_STATIC_ASSERT((is_conv),
"Other iterator has to be convertible to member iterator.",
point_reverse_iterator<OtherGeometry>);
}
std::is_convertible
<
std::reverse_iterator<point_iterator<OtherGeometry> >,
std::reverse_iterator<point_iterator<Geometry> >
>::value,
int
> = 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)
// 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 Adam Wulkiewicz, on behalf of Oracle
@ -18,7 +18,6 @@
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>
@ -285,25 +284,24 @@ public:
// correct 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)
: 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
{

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020-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
@ -43,21 +43,24 @@ namespace detail
template <typename Range>
struct closing_view
{
using iterator = closing_iterator<Range>;
using const_iterator = closing_iterator<Range const>;
// Keep this explicit, important for nested views/ranges
explicit inline closing_view(Range& r)
: m_range(r)
: m_begin(r)
, m_end(r, true)
{}
typedef closing_iterator<Range> iterator;
typedef closing_iterator<Range const> const_iterator;
inline const_iterator begin() const { return m_begin; }
inline const_iterator end() const { return m_end; }
inline const_iterator begin() const { return const_iterator(m_range); }
inline const_iterator end() const { return const_iterator(m_range, true); }
inline iterator begin() { return m_begin; }
inline iterator end() { return m_end; }
inline iterator begin() { return iterator(m_range); }
inline iterator end() { return iterator(m_range, true); }
private :
Range& m_range;
private:
iterator m_begin;
iterator m_end;
};
}

View File

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

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020-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
@ -18,6 +18,7 @@
#ifndef 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/end.hpp>
@ -40,20 +41,23 @@ namespace boost { namespace geometry
template <typename Range>
struct identity_view
{
typedef typename boost::range_iterator<Range const>::type const_iterator;
typedef typename boost::range_iterator<Range>::type iterator;
using const_iterator = typename boost::range_iterator<Range const>::type;
using iterator = typename boost::range_iterator<Range>::type;
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 end() const { return boost::end(m_range); }
inline const_iterator begin() const { return m_begin; }
inline const_iterator end() const { return m_end; }
inline iterator begin() { return boost::begin(m_range); }
inline iterator end() { return boost::end(m_range); }
private :
Range& m_range;
inline iterator begin() { return m_begin; }
inline iterator end() { return m_end; }
private:
iterator m_begin;
iterator m_end;
};
#if defined(_MSC_VER)

View File

@ -5,6 +5,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// 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
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -14,21 +17,49 @@
#include <algorithm>
#include <iterator>
#include <sstream>
#include <string>
#include <geometry_test_common.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/ring.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
void test_empty_non_geometry()
{
@ -39,49 +70,33 @@ void test_empty_non_geometry()
std::vector<int> const
> closing_iterator;
closing_iterator it(v);
closing_iterator end(v, true);
std::ostringstream out;
for (; it != end; ++it)
{
out << *it;
}
BOOST_CHECK_EQUAL(out.str(), "");
BOOST_CHECK(it == end);
}
void test_non_geometry()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::vector<int> v = {1, 2, 3};
std::vector<int> closed_v = { 1, 2, 3, 1 };
typedef bg::closing_iterator
<
std::vector<int> const
> closing_iterator;
closing_iterator it(v);
closing_iterator end(v, true);
std::ostringstream out;
for (; it != end; ++it)
{
out << *it;
}
BOOST_CHECK_EQUAL(out.str(), "1231");
BOOST_CHECK(std::equal(it, end, closed_v.begin(), closed_v.end()));
}
void test_transformed_non_geometry()
{
std::vector<int> v;
v.push_back(-1);
v.push_back(-2);
v.push_back(-3);
std::vector<int> v = {-1, -2, -3};
std::vector<int> closed_v = { 1, 2, 3, 1 };
typedef boost::transformed_range
<
std::negate<int>,
@ -97,78 +112,50 @@ void test_transformed_non_geometry()
closing_iterator it(v2);
closing_iterator end(v2, true);
std::ostringstream out;
for (; it != end; ++it)
{
out << *it;
}
BOOST_CHECK_EQUAL(out.str(), "1231");
BOOST_CHECK(std::equal(it, end, closed_v.begin(), closed_v.end()));
}
template <typename Geometry>
void test_geometry(std::string const& wkt)
template <typename P>
void test_geometry()
{
Geometry geometry;
bg::read_wkt(wkt, geometry);
typedef bg::closing_iterator<Geometry const> closing_iterator;
bg::model::ring<P> geometry = { {1, 1}, {1, 4}, {4, 4}, {4, 1} };
bg::model::ring<P> closed = { {1, 1}, {1, 4}, {4, 4}, {4, 1}, {1, 1} };
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
{
closing_iterator it(geometry);
closing_iterator end(geometry, true);
std::ostringstream out;
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;
BOOST_CHECK((std::equal(it, end, closed.begin(), closed.end(), pred)));
}
// 2: check copy behaviour
{
typedef typename boost::range_iterator<Geometry const>::type normal_iterator;
Geometry copy;
bg::model::ring<P> copy;
std::copy<closing_iterator>(
closing_iterator(geometry),
closing_iterator(geometry, true),
std::back_inserter(copy));
std::copy(closing_iterator(geometry), closing_iterator(geometry, true),
std::back_inserter(copy));
std::ostringstream out;
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");
BOOST_CHECK((std::equal(copy.begin(), copy.end(), closed.begin(), closed.end(), pred)));
}
}
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* [])
{
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;
}