-
Notifications
You must be signed in to change notification settings - Fork 214
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add enumerate to prepare for 17 and 23
- Loading branch information
1 parent
713fe69
commit 3dbee5d
Showing
6 changed files
with
276 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// 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: | ||
// Private iterator implementation | ||
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 should include the range it handles | ||
explicit inline enumerating_iterator(Range& range) | ||
: m_iterator(boost::begin(range)) | ||
, m_begin(boost::begin(range)) | ||
, m_end(boost::end(range)) | ||
{} | ||
|
||
// Constructor to indicate the end of a range | ||
explicit inline enumerating_iterator(Range& range, bool) | ||
: m_iterator(boost::end(range)) | ||
, m_begin(boost::begin(range)) | ||
, m_end(boost::end(range)) | ||
{} | ||
|
||
// There is no default constructor | ||
enumerating_iterator() = delete; | ||
|
||
inline reference dereference() const | ||
{ | ||
const std::size_t index = std::max(0L, 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> | ||
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> | ||
auto enumerate(Range& range) | ||
{ | ||
return util::enumerated_view<Range>(range); | ||
} | ||
|
||
}}} // boost::geometry::util | ||
|
||
|
||
#endif // BOOST_GEOMETRY_VIEWS_ENUMERATE_VIEW_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,3 +49,4 @@ endif() | |
|
||
add_subdirectory(algorithms) | ||
add_subdirectory(util) | ||
add_subdirectory(views) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |