mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-09 23:24:02 +00:00
Add enumerate to prepare for 17 and 23
This commit is contained in:
parent
713fe69938
commit
1f8b6e02ec
@ -59,7 +59,7 @@
|
||||
#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
|
||||
#include <boost/geometry/util/for_each_with_index.hpp>
|
||||
#include <boost/geometry/views/enumerate_view.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
@ -376,16 +376,18 @@ struct buffered_piece_collection
|
||||
|
||||
inline void update_turn_administration()
|
||||
{
|
||||
for_each_with_index(m_turns, [this](std::size_t index, auto& turn)
|
||||
for (auto const& enumerated : util::enumerate(m_turns))
|
||||
{
|
||||
turn.turn_index = index;
|
||||
// enumerated is const, but its value is a non-const reference
|
||||
auto& turn = enumerated.value;
|
||||
turn.turn_index = enumerated.index;
|
||||
|
||||
// Verify if a turn is a linear endpoint
|
||||
if (! turn.is_linear_end_point)
|
||||
{
|
||||
this->check_linear_endpoints(turn);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate properties of piece borders which are not influenced
|
||||
@ -1091,30 +1093,32 @@ struct buffered_piece_collection
|
||||
// Inner rings, for deflate, which do not have intersections, and
|
||||
// which are outside originals, are skipped
|
||||
// (other ones should be traversed)
|
||||
for_each_with_index(offsetted_rings, [&](std::size_t index, auto const& ring)
|
||||
for (auto const& enumerated : util::enumerate(offsetted_rings))
|
||||
{
|
||||
auto const& ring = enumerated.value;
|
||||
if (! ring.has_intersections()
|
||||
&& ! ring.is_untouched_outside_original)
|
||||
{
|
||||
if (! ring.has_intersections()
|
||||
&& ! ring.is_untouched_outside_original)
|
||||
{
|
||||
properties p = properties(ring, m_strategy);
|
||||
if (p.valid)
|
||||
{
|
||||
ring_identifier id(0, index, -1);
|
||||
selected[id] = p;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Select all created rings
|
||||
for_each_with_index(traversed_rings, [&](std::size_t index, auto const& ring)
|
||||
{
|
||||
properties p = properties(ring, m_strategy);
|
||||
properties const p = properties(ring, m_strategy);
|
||||
if (p.valid)
|
||||
{
|
||||
ring_identifier id(2, index, -1);
|
||||
ring_identifier id(0, enumerated.index, -1);
|
||||
selected[id] = p;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Select all created rings
|
||||
for (auto const& enumerated : util::enumerate(traversed_rings))
|
||||
{
|
||||
auto const& ring = enumerated.value;
|
||||
properties p = properties(ring, m_strategy);
|
||||
if (p.valid)
|
||||
{
|
||||
ring_identifier id(2, enumerated.index, -1);
|
||||
selected[id] = p;
|
||||
}
|
||||
}
|
||||
|
||||
detail::overlay::assign_parents<overlay_buffer>(offsetted_rings, traversed_rings,
|
||||
selected, m_strategy);
|
||||
|
@ -27,10 +27,10 @@
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
|
||||
#include <boost/geometry/views/enumerate_view.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
#include <boost/geometry/util/for_each_with_index.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@ -271,25 +271,28 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
std::size_t index_positive = 0; // only used if count_positive>0
|
||||
|
||||
// Copy to vector (this might be obsolete, using the map directly)
|
||||
// The index in the map is also the index in the vector.
|
||||
using helper = ring_info_helper<point_type, area_result_type>;
|
||||
std::vector<helper> vector(count_total);
|
||||
|
||||
for_each_with_index(ring_map, [&](std::size_t index, auto const& pair)
|
||||
for (auto const& enumerated : util::enumerate(ring_map))
|
||||
{
|
||||
vector[index] = helper(pair.first, pair.second.get_area());
|
||||
helper& item = vector[index];
|
||||
switch(pair.first.source_index)
|
||||
auto const& ring_id = enumerated.value.first;
|
||||
auto const& info = enumerated.value.second;
|
||||
vector[enumerated.index] = helper(ring_id, info.get_area());
|
||||
helper& item = vector[enumerated.index];
|
||||
switch(ring_id.source_index)
|
||||
{
|
||||
case 0 :
|
||||
geometry::envelope(get_ring<tag1>::apply(pair.first, geometry1),
|
||||
geometry::envelope(get_ring<tag1>::apply(ring_id, geometry1),
|
||||
item.envelope, strategy);
|
||||
break;
|
||||
case 1 :
|
||||
geometry::envelope(get_ring<tag2>::apply(pair.first, geometry2),
|
||||
geometry::envelope(get_ring<tag2>::apply(ring_id, geometry2),
|
||||
item.envelope, strategy);
|
||||
break;
|
||||
case 2 :
|
||||
geometry::envelope(get_ring<void>::apply(pair.first, collection),
|
||||
geometry::envelope(get_ring<void>::apply(ring_id, collection),
|
||||
item.envelope, strategy);
|
||||
break;
|
||||
}
|
||||
@ -300,9 +303,9 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
if (item.real_area > 0)
|
||||
{
|
||||
count_positive++;
|
||||
index_positive = index;
|
||||
index_positive = enumerated.index;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (! check_for_orientation)
|
||||
{
|
||||
@ -323,15 +326,16 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
// located outside the outer ring, this cannot be done
|
||||
ring_identifier id_of_positive = vector[index_positive].id;
|
||||
ring_info_type& outer = ring_map[id_of_positive];
|
||||
for_each_with_index(vector, [&](std::size_t index, auto const& item)
|
||||
for (auto const& item : util::enumerate(vector))
|
||||
{
|
||||
if (index != index_positive)
|
||||
if (item.index != index_positive)
|
||||
{
|
||||
ring_info_type& inner = ring_map[item.id];
|
||||
auto const id = item.value.id;
|
||||
ring_info_type& inner = ring_map[id];
|
||||
inner.parent = id_of_positive;
|
||||
outer.children.push_back(item.id);
|
||||
outer.children.push_back(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
#include <boost/geometry/views/enumerate_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@ -122,17 +123,17 @@ inline void check_detailed(MetaTurns& meta_turns, MetaTurn const& meta_turn,
|
||||
|
||||
|
||||
template <typename TurnPoints>
|
||||
inline bool check_graph(TurnPoints& turn_points, operation_type for_operation)
|
||||
inline bool check_graph(TurnPoints const& turn_points, operation_type for_operation)
|
||||
{
|
||||
typedef typename boost::range_value<TurnPoints>::type turn_point_type;
|
||||
using turn_point_type = typename boost::range_value<TurnPoints>::type;
|
||||
|
||||
bool error = false;
|
||||
|
||||
std::vector<meta_turn<turn_point_type> > meta_turns;
|
||||
for_each_with_index(turn_points, [&](std::size_t index, auto const& point)
|
||||
for (auto const& item : util::enumerate(turn_points))
|
||||
{
|
||||
meta_turns.push_back(meta_turn<turn_point_type>(index, point));
|
||||
});
|
||||
meta_turns.push_back(meta_turn<turn_point_type>(item.index, item.value));
|
||||
}
|
||||
|
||||
int cycle = 0;
|
||||
for (auto& meta_turn : meta_turns)
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/handle_colocations.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp>
|
||||
@ -42,11 +43,8 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_type.hpp>
|
||||
#include <boost/geometry/util/constexpr.hpp>
|
||||
#include <boost/geometry/util/for_each_with_index.hpp>
|
||||
#include <boost/geometry/views/enumerate_view.hpp>
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@ -112,8 +110,10 @@ template <typename Operations, typename Turns>
|
||||
inline void enrich_assign(Operations& operations, Turns& turns,
|
||||
bool check_consecutive_turns)
|
||||
{
|
||||
for_each_with_index(operations, [&](std::size_t index, auto const& indexed)
|
||||
for (auto const& item : util::enumerate(operations))
|
||||
{
|
||||
auto const& index = item.index;
|
||||
auto const& indexed = item.value;
|
||||
auto& turn = turns[indexed.turn_index];
|
||||
auto& op = turn.operations[indexed.operation_index];
|
||||
|
||||
@ -185,7 +185,7 @@ inline void enrich_assign(Operations& operations, Turns& turns,
|
||||
// Next turn is located further on same segment: assign next_ip_index
|
||||
op.enriched.next_ip_index = static_cast<signed_size_type>(operations[next_index].turn_index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
for (auto const& indexed_op : operations)
|
||||
@ -223,8 +223,10 @@ inline void enrich_adapt(Operations& operations, Turns& turns)
|
||||
bool next_phase = false;
|
||||
std::size_t previous_index = operations.size() - 1;
|
||||
|
||||
for_each_with_index(operations, [&](std::size_t index, auto const& indexed)
|
||||
for (auto const& item : util::enumerate(operations))
|
||||
{
|
||||
auto const& index = item.index;
|
||||
auto const& indexed = item.value;
|
||||
auto& turn = turns[indexed.turn_index];
|
||||
auto& op = turn.operations[indexed.operation_index];
|
||||
|
||||
@ -243,7 +245,7 @@ inline void enrich_adapt(Operations& operations, Turns& turns)
|
||||
}
|
||||
}
|
||||
previous_index = index;
|
||||
});
|
||||
}
|
||||
|
||||
if (! next_phase)
|
||||
{
|
||||
@ -290,12 +292,16 @@ template <typename Turns, typename MappedVector, typename IncludePolicy>
|
||||
inline void create_map(Turns const& turns, MappedVector& mapped_vector,
|
||||
IncludePolicy const& include_policy)
|
||||
{
|
||||
for_each_with_index(turns, [&](std::size_t index, auto const& turn)
|
||||
for (auto const& turn_item : util::enumerate(turns))
|
||||
{
|
||||
auto const& index = turn_item.index;
|
||||
auto const& turn = turn_item.value;
|
||||
if (! turn.discarded)
|
||||
{
|
||||
for_each_with_index(turn.operations, [&](std::size_t op_index, auto const& op)
|
||||
for (auto const& op_item : util::enumerate(turn.operations))
|
||||
{
|
||||
auto const& op_index = op_item.index;
|
||||
auto const& op = op_item.value;
|
||||
if (include_policy.include(op.operation))
|
||||
{
|
||||
ring_identifier const ring_id
|
||||
@ -309,9 +315,9 @@ inline void create_map(Turns const& turns, MappedVector& mapped_vector,
|
||||
index, op_index, op, turn.operations[1 - op_index].seg_id
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
@ -534,9 +540,15 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
//detail::overlay::check_graph(turns, for_operation);
|
||||
constexpr bool do_check_graph = true;
|
||||
#else
|
||||
constexpr bool do_check_graph = false;
|
||||
#endif
|
||||
|
||||
if BOOST_GEOMETRY_CONSTEXPR (do_check_graph)
|
||||
{
|
||||
detail::overlay::check_graph(turns, target_operation);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
@ -59,7 +59,7 @@
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
|
||||
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
|
||||
#include <boost/geometry/io/wkt/wkt.hpp>
|
||||
#include <boost/geometry/util/for_each_with_index.hpp>
|
||||
#include <boost/geometry/views/enumerate_view.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@ -379,10 +379,11 @@ struct intersection_of_linestring_with_areal
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
|
||||
for_each_with_index(turns, [](auto index, auto const& turn)
|
||||
for (auto const& item : util::enumerate(turns))
|
||||
{
|
||||
debug_follow(turn, turn.operations[0], index);
|
||||
});
|
||||
auto const& turn = item.value;
|
||||
debug_follow(turn, turn.operations[0], item.index);
|
||||
}
|
||||
#endif
|
||||
|
||||
return follower::apply
|
||||
|
@ -1,49 +0,0 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2023 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
|
||||
#define BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Utility function to implement a Kotlin like range based for loop
|
||||
template <typename Container, typename Function>
|
||||
inline void for_each_with_index(Container const& container, Function func)
|
||||
{
|
||||
typename boost::range_size<Container>::type index = 0;
|
||||
for (auto it = boost::begin(container); it != boost::end(container); ++it, ++index)
|
||||
{
|
||||
func(index, *it);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container, typename Function>
|
||||
inline void for_each_with_index(Container& container, Function func)
|
||||
{
|
||||
typename boost::range_size<Container>::type index = 0;
|
||||
for (auto it = boost::begin(container); it != boost::end(container); ++it, ++index)
|
||||
{
|
||||
func(index, *it);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
|
159
include/boost/geometry/views/enumerate_view.hpp
Normal file
159
include/boost/geometry/views/enumerate_view.hpp
Normal file
@ -0,0 +1,159 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2024 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_VIEWS_ENUMERATE_VIEW_HPP
|
||||
#define BOOST_GEOMETRY_VIEWS_ENUMERATE_VIEW_HPP
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/difference_type.hpp>
|
||||
#include <boost/range/reference.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/util/type_traits_std.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace util
|
||||
{
|
||||
|
||||
// This view is a range of values, each with an index
|
||||
// It is used to iterate over a range, and to get the index of the value
|
||||
// It is used in the enumerate function
|
||||
// The typename Range can either be const or non-const
|
||||
template <typename Range>
|
||||
struct enumerated_view
|
||||
{
|
||||
// The return value of the iterator
|
||||
struct value_with_index
|
||||
{
|
||||
using type = util::transcribe_const_t
|
||||
<
|
||||
Range,
|
||||
typename boost::range_value<Range>::type
|
||||
>;
|
||||
|
||||
// Member variable index contains the zero-based index of the value in the range
|
||||
std::size_t const index;
|
||||
|
||||
// Member variable value contains a const or non-const reference to the value itself
|
||||
type& value;
|
||||
};
|
||||
|
||||
private:
|
||||
// Iterator implementation, not exposed.
|
||||
struct enumerating_iterator
|
||||
: public boost::iterator_facade
|
||||
<
|
||||
enumerating_iterator,
|
||||
value_with_index const,
|
||||
boost::random_access_traversal_tag,
|
||||
value_with_index const,
|
||||
typename boost::range_difference<Range>::type
|
||||
>
|
||||
{
|
||||
using reference = value_with_index;
|
||||
using difference_type = typename boost::range_difference<Range>::type;
|
||||
|
||||
// Constructor with the range it handles
|
||||
explicit inline enumerating_iterator(Range& range)
|
||||
: m_begin(boost::begin(range))
|
||||
, m_end(boost::end(range))
|
||||
, m_iterator(boost::begin(range))
|
||||
{}
|
||||
|
||||
// Constructor to indicate the end of a range
|
||||
explicit inline enumerating_iterator(Range& range, bool)
|
||||
: m_begin(boost::begin(range))
|
||||
, m_end(boost::end(range))
|
||||
, m_iterator(boost::end(range))
|
||||
{}
|
||||
|
||||
// There is no default constructor
|
||||
enumerating_iterator() = delete;
|
||||
|
||||
inline reference dereference() const
|
||||
{
|
||||
constexpr difference_type zero = 0;
|
||||
const std::size_t index = (std::max)(zero, std::distance(m_begin, m_iterator));
|
||||
const value_with_index result{index, *m_iterator};
|
||||
return result;
|
||||
}
|
||||
|
||||
inline difference_type distance_to(enumerating_iterator const& other) const
|
||||
{
|
||||
return std::distance(other.m_iterator, m_iterator);
|
||||
}
|
||||
|
||||
inline bool equal(enumerating_iterator const& other) const
|
||||
{
|
||||
return
|
||||
m_begin == other.m_begin
|
||||
&& m_end == other.m_end
|
||||
&& m_iterator == other.m_iterator;
|
||||
}
|
||||
|
||||
inline void increment()
|
||||
{
|
||||
++m_iterator;
|
||||
}
|
||||
|
||||
inline void decrement()
|
||||
{
|
||||
--m_iterator;
|
||||
}
|
||||
|
||||
inline void advance(difference_type n)
|
||||
{
|
||||
std::advance(m_iterator, n);
|
||||
}
|
||||
|
||||
const typename boost::range_iterator<Range>::type m_begin;
|
||||
const typename boost::range_iterator<Range>::type m_end;
|
||||
|
||||
typename boost::range_iterator<Range>::type m_iterator;
|
||||
};
|
||||
|
||||
public:
|
||||
using iterator = enumerating_iterator;
|
||||
using const_iterator = enumerating_iterator;
|
||||
|
||||
explicit inline enumerated_view(Range& range)
|
||||
: m_begin(range)
|
||||
, m_end(range, true)
|
||||
{}
|
||||
|
||||
inline iterator begin() const { return m_begin; }
|
||||
inline iterator end() const { return m_end; }
|
||||
|
||||
private:
|
||||
const iterator m_begin;
|
||||
const iterator m_end;
|
||||
};
|
||||
|
||||
// Helper function to create the enumerated view, for a const range
|
||||
template <typename Range>
|
||||
inline auto enumerate(Range const& range)
|
||||
{
|
||||
return util::enumerated_view<Range const>(range);
|
||||
}
|
||||
|
||||
// Helper function to create the enumerated view, for a non-const range
|
||||
template <typename Range>
|
||||
inline auto enumerate(Range& range)
|
||||
{
|
||||
return util::enumerated_view<Range>(range);
|
||||
}
|
||||
|
||||
}}} // boost::geometry::util
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_VIEWS_ENUMERATE_VIEW_HPP
|
@ -49,3 +49,4 @@ endif()
|
||||
|
||||
add_subdirectory(algorithms)
|
||||
add_subdirectory(util)
|
||||
add_subdirectory(views)
|
||||
|
16
test/views/CMakeLists.txt
Normal file
16
test/views/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
# Boost.Geometry
|
||||
# Copyright (c) 2024 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
# Use, modification and distribution is subject to the Boost Software License,
|
||||
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
foreach(item IN ITEMS
|
||||
box_view
|
||||
closeable_view
|
||||
enumerate_view
|
||||
random_access_view
|
||||
reversible_closeable
|
||||
reversible_view
|
||||
segment_view)
|
||||
boost_geometry_add_unit_test("views" ${item})
|
||||
endforeach()
|
@ -17,6 +17,7 @@ test-suite boost-geometry-views
|
||||
:
|
||||
[ run box_view.cpp : : : : views_box_view ]
|
||||
[ run closeable_view.cpp : : : : views_closeable_view ]
|
||||
[ run enumerate_view.cpp : : : : views_enumerate_view ]
|
||||
[ run random_access_view.cpp : : : : views_random_access_view ]
|
||||
[ run reversible_closeable.cpp : : : : views_reversible_closeable ]
|
||||
[ run reversible_view.cpp : : : : views_reversible_view ]
|
||||
|
74
test/views/enumerate_view.cpp
Normal file
74
test/views/enumerate_view.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
// Boost.Geometry
|
||||
// Unit Test
|
||||
|
||||
// Copyright (c) 2024 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/geometry/views/enumerate_view.hpp>
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
void test_const()
|
||||
{
|
||||
const std::vector<std::string> vec{"cat", "mouse", "squirrel"};
|
||||
std::size_t test_index = 0;
|
||||
for (auto const& item : boost::geometry::util::enumerate(vec))
|
||||
{
|
||||
BOOST_CHECK_EQUAL(item.index, test_index++);
|
||||
switch(item.index)
|
||||
{
|
||||
case 0 : BOOST_CHECK_EQUAL(item.value, "cat"); break;
|
||||
case 1 : BOOST_CHECK_EQUAL(item.value, "mouse"); break;
|
||||
case 2 : BOOST_CHECK_EQUAL(item.value, "squirrel"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_non_const()
|
||||
{
|
||||
std::vector<std::string> vec{"Amsterdam", "London", "Paris"};
|
||||
std::size_t index_sum = 0;
|
||||
for (auto const& item : boost::geometry::util::enumerate(vec))
|
||||
{
|
||||
item.value += " is a city";
|
||||
index_sum += item.index;
|
||||
}
|
||||
BOOST_CHECK_EQUAL(vec[0], "Amsterdam is a city");
|
||||
BOOST_CHECK_EQUAL(vec[1], "London is a city");
|
||||
BOOST_CHECK_EQUAL(vec[2], "Paris is a city");
|
||||
BOOST_CHECK_EQUAL(index_sum, 3);
|
||||
}
|
||||
|
||||
// Verifies the usage of the enumerate_view with C++17 structured bindings
|
||||
// See https://en.cppreference.com/w/cpp/ranges/enumerate_view
|
||||
void test_cpp17()
|
||||
{
|
||||
#if __cplusplus >= 201703L
|
||||
std::vector<int> numbers{1, 3, 5, 7};
|
||||
std::size_t sum_indexes = 0;
|
||||
int sum_numbers = 0;
|
||||
for (auto const [index, num] : boost::geometry::util::enumerate(numbers))
|
||||
{
|
||||
sum_indexes += index;
|
||||
sum_numbers += num;
|
||||
// num is mutable even with const, which does not propagate to reference
|
||||
num++;
|
||||
}
|
||||
BOOST_CHECK_EQUAL(sum_indexes, 6);
|
||||
BOOST_CHECK_EQUAL(sum_numbers, 16);
|
||||
BOOST_CHECK_EQUAL(numbers[0], 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
{
|
||||
test_const();
|
||||
test_non_const();
|
||||
test_cpp17();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user