Skip to content

Commit a6c6fa3

Browse files
committed
Replace gcc's normal_iterator with boost/stl_interfaces/iterator_interface
1 parent 09a1750 commit a6c6fa3

File tree

7 files changed

+1170
-162
lines changed

7 files changed

+1170
-162
lines changed

etc/gcc-flags.cmake

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ include_guard(GLOBAL)
33
set(CMAKE_CXX_STANDARD 23)
44

55
set(CMAKE_CXX_FLAGS
6-
"-Wall -Wextra "
6+
"-std=c++23 -Wall -Wextra "
77
CACHE STRING "CXX_FLAGS" FORCE)
88

99
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE)

include/Beman/Optional26/detail/iterator.hpp

+27-120
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,28 @@
22
#ifndef BEMAN_OPTIONAL26_OPTIONAL_DETAIL_ITERATOR_HPP
33
#define BEMAN_OPTIONAL26_OPTIONAL_DETAIL_ITERATOR_HPP
44

5+
#include <Beman/Optional26/detail/stl_interfaces/iterator_interface.hpp>
6+
57
#include <iterator>
6-
#include <type_traits>
78

89
namespace beman::optional::detail {
9-
// Implementation inspired by libstdc++'s normal_iterator
10-
// (https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_iterator.h)
11-
//
12-
//
13-
// This iterator adapter is a normal iterator in the sense that it does not
14-
// change the semantics of any of the operators of its iterator
15-
// parameter. Its primary purpose is to convert an iterator that is
16-
// not a class, e.g. a pointer, into an iterator that is a class.
17-
//
18-
// The ContainerType parameter exists solely so that different containers
19-
// using this template can instantiate different types, even if the
20-
// IteratorType parameter is the same.
10+
11+
// This is a minimal contiguous iterator. It uses stl_interfaces library from Boost
12+
// (current implementation based on https://wg21.link/P2727R4).
2113
//
22-
// FUTURE Use std::iterator_interface from https://wg21.link/P2727R4.
23-
// Adopt Boost's iterator_interface (https://github.com/boostorg/stl_interfaces) into a Beman library.
14+
// TODO: Change this to use the stl_interfaces library from Beman when available.
2415
//
25-
template <typename IteratorType, typename ContainerType>
26-
class normal_iterator {
27-
public:
28-
using iterator_type = IteratorType;
16+
// @tparam T - The type of the elements the iterator points to.
17+
// @tparam Container - The type of the container the iterator points to. This parameter exists solely so that different
18+
// containers using this template can instantiate different types, even if the T parameter is the same.
19+
template <class T, class Container>
20+
struct contiguous_iterator : boost::stl_interfaces::iterator_interface<
21+
#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
22+
contiguous_iterator<T, Container>,
23+
#endif
24+
std::contiguous_iterator_tag,
25+
T> {
26+
using iterator_type = T*;
2927
using iterator_category = std::iterator_traits<iterator_type>::iterator_category;
3028
using iterator_concept = std::iterator_traits<iterator_type>::iterator_concept;
3129
using value_type = std::iterator_traits<iterator_type>::value_type;
@@ -34,114 +32,23 @@ class normal_iterator {
3432
using pointer = std::iterator_traits<iterator_type>::pointer;
3533

3634
// Default constructor.
37-
constexpr normal_iterator() noexcept : m_current(IteratorType()) {}
38-
39-
// Constructor from an iterator.
40-
explicit constexpr normal_iterator(const IteratorType& iter) noexcept : m_current(iter) {}
41-
42-
// Allow iterator to const_iterator conversion.
43-
template <typename OtherIteratorType,
44-
typename = std::enable_if_t<std::is_convertible_v<OtherIteratorType, IteratorType>>>
45-
constexpr normal_iterator(const normal_iterator<OtherIteratorType, ContainerType>& iter) noexcept
46-
: m_current(iter.base()) {}
47-
48-
constexpr const auto& base() const noexcept { return m_current; }
35+
contiguous_iterator() noexcept : m_current() {}
4936

50-
// Forward iterator requirements
51-
constexpr reference operator*() const noexcept { return *m_current; }
37+
// Pointer to iterator constructor.
38+
contiguous_iterator(pointer it) noexcept : m_current(it) {}
5239

53-
constexpr pointer operator->() const noexcept { return m_current; }
54-
55-
constexpr normal_iterator& operator++() noexcept {
56-
++m_current;
57-
return *this;
58-
}
59-
60-
constexpr normal_iterator operator++(int) noexcept { return normal_iterator(m_current++); }
61-
62-
// Bidirectional iterator requirements
63-
constexpr normal_iterator& operator--() noexcept {
64-
--m_current;
40+
// As per P2727R4, for contiguous iterator we only need to provide operator*, operator+= and operator-.
41+
reference operator*() const noexcept { return *m_current; }
42+
auto& operator+=(difference_type pos) noexcept {
43+
m_current += pos;
6544
return *this;
6645
}
46+
difference_type operator-(contiguous_iterator other) const noexcept { return m_current - other.m_current; }
6747

68-
constexpr normal_iterator operator--(int) noexcept { return normal_iterator(m_current--); }
69-
70-
// Random access iterator requirements
71-
constexpr reference operator[](difference_type n) const noexcept { return m_current[n]; }
72-
73-
constexpr normal_iterator& operator+=(difference_type n) noexcept {
74-
m_current += n;
75-
return *this;
76-
}
77-
78-
constexpr normal_iterator operator+(difference_type n) const noexcept { return normal_iterator(m_current + n); }
79-
80-
constexpr normal_iterator& operator-=(difference_type n) noexcept {
81-
m_current -= n;
82-
return *this;
83-
}
84-
85-
constexpr normal_iterator operator-(difference_type n) const noexcept { return normal_iterator(m_current - n); }
86-
87-
protected:
88-
// The underlying pointer iterator.
89-
IteratorType m_current;
48+
private:
49+
T* m_current;
9050
};
9151

92-
// Forward iterator requirements
93-
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
94-
[[nodiscard]] constexpr inline bool operator==(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
95-
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
96-
return lhs.base() == rhs.base();
97-
}
98-
99-
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
100-
[[nodiscard]] constexpr inline bool operator!=(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
101-
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
102-
return lhs.base() != rhs.base();
103-
}
104-
105-
// Random access iterator requirements
106-
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
107-
[[nodiscard]] inline bool operator<(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
108-
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
109-
return lhs.base() < rhs.base();
110-
}
111-
112-
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
113-
[[nodiscard]] inline bool operator>(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
114-
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
115-
return lhs.base() > rhs.base();
116-
}
117-
118-
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
119-
[[nodiscard]] inline bool operator<=(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
120-
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
121-
return lhs.base() <= rhs.base();
122-
}
123-
124-
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
125-
[[nodiscard]] inline bool operator>=(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
126-
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
127-
return lhs.base() >= rhs.base();
128-
}
129-
130-
// According to the resolution of DR179 not only the various comparison
131-
// operators but also operator- must accept mixed iterator/const_iterator
132-
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
133-
[[nodiscard]] constexpr inline auto operator-(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
134-
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
135-
return lhs.base() - rhs.base();
136-
}
137-
138-
template <typename IteratorType, typename ContainerType>
139-
[[nodiscard]] constexpr inline normal_iterator<IteratorType, ContainerType>
140-
operator+(typename normal_iterator<IteratorType, ContainerType>::difference_type n,
141-
const normal_iterator<IteratorType, ContainerType>& iter) noexcept {
142-
return normal_iterator(iter.base() + n);
143-
}
144-
14552
} // namespace beman::optional::detail
14653

14754
#endif // BEMAN_OPTIONAL26_OPTIONAL_DETAIL_ITERATOR_HPP
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (C) 2020 T. Zachary Laine
2+
//
3+
// Distributed under the Boost Software License, Version 1.0. (See
4+
// accompanying file LICENSE_1_0.txt or copy at
5+
// http://www.boost.org/LICENSE_1_0.txt)
6+
#ifndef BOOST_STL_INTERFACES_CONFIG_HPP
7+
#define BOOST_STL_INTERFACES_CONFIG_HPP
8+
9+
// Included for definition of __cpp_lib_concepts.
10+
#include <iterator>
11+
12+
#if defined(__cpp_lib_concepts) && defined(__cpp_lib_ranges) && !defined(BOOST_STL_INTERFACES_DISABLE_CONCEPTS)
13+
#define BOOST_STL_INTERFACES_USE_CONCEPTS 1
14+
#else
15+
#define BOOST_STL_INTERFACES_USE_CONCEPTS 0
16+
#endif
17+
18+
#if defined(__cpp_explicit_this_parameter) && BOOST_STL_INTERFACES_USE_CONCEPTS && \
19+
!defined(BOOST_STL_INTERFACES_DISABLE_DEDUCED_THIS)
20+
#define BOOST_STL_INTERFACES_USE_DEDUCED_THIS 1
21+
#else
22+
#define BOOST_STL_INTERFACES_USE_DEDUCED_THIS 0
23+
#endif
24+
25+
// The inline namespaces v1, v2, and v3 represent C++14, C++20, and C++23 and
26+
// later, respectively. v1 is inline for standards before C++20, and v2 is
27+
// inline for C++20 and later. Note that this only applies to code for which
28+
// multiple vI namespace alternatives exist. For example, some instances of
29+
// the v1 namespace may still be inline, if there is no v2 version of its
30+
// contents.
31+
#if !BOOST_STL_INTERFACES_USE_CONCEPTS && !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
32+
#define BOOST_STL_INTERFACES_NAMESPACE_V1 inline namespace v1
33+
#define BOOST_STL_INTERFACES_NAMESPACE_V2 namespace v2
34+
#define BOOST_STL_INTERFACES_NAMESPACE_V3 namespace v3
35+
#elif BOOST_STL_INTERFACES_USE_CONCEPTS && !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
36+
#define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1
37+
#define BOOST_STL_INTERFACES_NAMESPACE_V2 inline namespace v2
38+
#define BOOST_STL_INTERFACES_NAMESPACE_V3 namespace v3
39+
#else
40+
#define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1
41+
#define BOOST_STL_INTERFACES_NAMESPACE_V2 namespace v2
42+
#define BOOST_STL_INTERFACES_NAMESPACE_V3 inline namespace v3
43+
#endif
44+
45+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright (C) 2019 T. Zachary Laine
2+
//
3+
// Distributed under the Boost Software License, Version 1.0. (See
4+
// accompanying file LICENSE_1_0.txt or copy at
5+
// http://www.boost.org/LICENSE_1_0.txt)
6+
#ifndef BOOST_STL_INTERFACES_FWD_HPP
7+
#define BOOST_STL_INTERFACES_FWD_HPP
8+
9+
#include <Beman/Optional26/detail/stl_interfaces/config.hpp>
10+
11+
#if BOOST_STL_INTERFACES_USE_CONCEPTS
12+
#include <ranges>
13+
#endif
14+
#if defined(__cpp_lib_three_way_comparison)
15+
#include <compare>
16+
#endif
17+
18+
#ifndef BOOST_STL_INTERFACES_DOXYGEN
19+
20+
#if defined(_MSC_VER) || defined(__GNUC__) && __GNUC__ < 8
21+
#define BOOST_STL_INTERFACES_NO_HIDDEN_FRIEND_CONSTEXPR
22+
#define BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR
23+
#else
24+
#define BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR constexpr
25+
#endif
26+
27+
#if defined(__GNUC__) && __GNUC__ < 9
28+
#define BOOST_STL_INTERFACES_CONCEPT concept bool
29+
#else
30+
#define BOOST_STL_INTERFACES_CONCEPT concept
31+
#endif
32+
33+
#endif
34+
35+
namespace boost {
36+
namespace stl_interfaces {
37+
38+
/** An enumeration used to indicate whether the underlying data have a
39+
contiguous or discontiguous layout when instantiating `view_interface`
40+
and `sequence_container_interface`. */
41+
enum class element_layout : bool { discontiguous = false, contiguous = true };
42+
43+
BOOST_STL_INTERFACES_NAMESPACE_V1 {
44+
45+
namespace v1_dtl {
46+
template <typename... T>
47+
using void_t = void;
48+
49+
template <typename Iter>
50+
using iter_difference_t = typename std::iterator_traits<Iter>::difference_type;
51+
52+
template <typename Range, typename = void>
53+
struct iterator;
54+
template <typename Range>
55+
struct iterator<Range, void_t<decltype(std::declval<Range&>().begin())>> {
56+
using type = decltype(std::declval<Range&>().begin());
57+
};
58+
template <typename Range>
59+
using iterator_t = typename iterator<Range>::type;
60+
61+
template <typename Range, typename = void>
62+
struct sentinel;
63+
template <typename Range>
64+
struct sentinel<Range, void_t<decltype(std::declval<Range&>().end())>> {
65+
using type = decltype(std::declval<Range&>().end());
66+
};
67+
template <typename Range>
68+
using sentinel_t = typename sentinel<Range>::type;
69+
70+
template <typename Range>
71+
using range_difference_t = iter_difference_t<iterator_t<Range>>;
72+
73+
template <typename Range>
74+
using common_range = std::is_same<iterator_t<Range>, sentinel_t<Range>>;
75+
76+
template <typename Range, typename = void>
77+
struct decrementable_sentinel : std::false_type {};
78+
template <typename Range>
79+
struct decrementable_sentinel<Range, void_t<decltype(--std::declval<sentinel_t<Range>&>())>> : std::true_type {};
80+
} // namespace v1_dtl
81+
}
82+
} // namespace stl_interfaces
83+
} // namespace boost
84+
85+
#endif

0 commit comments

Comments
 (0)