Skip to content

Commit

Permalink
Replace gcc's normal_iterator with boost/stl_interfaces/iterator_inte…
Browse files Browse the repository at this point in the history
…rface
  • Loading branch information
neatudarius committed Jun 23, 2024
1 parent 09a1750 commit a6c6fa3
Show file tree
Hide file tree
Showing 7 changed files with 1,170 additions and 162 deletions.
2 changes: 1 addition & 1 deletion etc/gcc-flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include_guard(GLOBAL)
set(CMAKE_CXX_STANDARD 23)

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

set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE)
Expand Down
147 changes: 27 additions & 120 deletions include/Beman/Optional26/detail/iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,28 @@
#ifndef BEMAN_OPTIONAL26_OPTIONAL_DETAIL_ITERATOR_HPP
#define BEMAN_OPTIONAL26_OPTIONAL_DETAIL_ITERATOR_HPP

#include <Beman/Optional26/detail/stl_interfaces/iterator_interface.hpp>

#include <iterator>
#include <type_traits>

namespace beman::optional::detail {
// Implementation inspired by libstdc++'s normal_iterator
// (https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_iterator.h)
//
//
// This iterator adapter is a normal iterator in the sense that it does not
// change the semantics of any of the operators of its iterator
// parameter. Its primary purpose is to convert an iterator that is
// not a class, e.g. a pointer, into an iterator that is a class.
//
// The ContainerType parameter exists solely so that different containers
// using this template can instantiate different types, even if the
// IteratorType parameter is the same.

// This is a minimal contiguous iterator. It uses stl_interfaces library from Boost
// (current implementation based on https://wg21.link/P2727R4).
//
// FUTURE Use std::iterator_interface from https://wg21.link/P2727R4.
// Adopt Boost's iterator_interface (https://github.com/boostorg/stl_interfaces) into a Beman library.
// TODO: Change this to use the stl_interfaces library from Beman when available.
//
template <typename IteratorType, typename ContainerType>
class normal_iterator {
public:
using iterator_type = IteratorType;
// @tparam T - The type of the elements the iterator points to.
// @tparam Container - The type of the container the iterator points to. This parameter exists solely so that different
// containers using this template can instantiate different types, even if the T parameter is the same.
template <class T, class Container>
struct contiguous_iterator : boost::stl_interfaces::iterator_interface<
#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
contiguous_iterator<T, Container>,
#endif
std::contiguous_iterator_tag,
T> {
using iterator_type = T*;
using iterator_category = std::iterator_traits<iterator_type>::iterator_category;
using iterator_concept = std::iterator_traits<iterator_type>::iterator_concept;
using value_type = std::iterator_traits<iterator_type>::value_type;
Expand All @@ -34,114 +32,23 @@ class normal_iterator {
using pointer = std::iterator_traits<iterator_type>::pointer;

// Default constructor.
constexpr normal_iterator() noexcept : m_current(IteratorType()) {}

// Constructor from an iterator.
explicit constexpr normal_iterator(const IteratorType& iter) noexcept : m_current(iter) {}

// Allow iterator to const_iterator conversion.
template <typename OtherIteratorType,
typename = std::enable_if_t<std::is_convertible_v<OtherIteratorType, IteratorType>>>
constexpr normal_iterator(const normal_iterator<OtherIteratorType, ContainerType>& iter) noexcept
: m_current(iter.base()) {}

constexpr const auto& base() const noexcept { return m_current; }
contiguous_iterator() noexcept : m_current() {}

// Forward iterator requirements
constexpr reference operator*() const noexcept { return *m_current; }
// Pointer to iterator constructor.
contiguous_iterator(pointer it) noexcept : m_current(it) {}

constexpr pointer operator->() const noexcept { return m_current; }

constexpr normal_iterator& operator++() noexcept {
++m_current;
return *this;
}

constexpr normal_iterator operator++(int) noexcept { return normal_iterator(m_current++); }

// Bidirectional iterator requirements
constexpr normal_iterator& operator--() noexcept {
--m_current;
// As per P2727R4, for contiguous iterator we only need to provide operator*, operator+= and operator-.
reference operator*() const noexcept { return *m_current; }
auto& operator+=(difference_type pos) noexcept {
m_current += pos;
return *this;
}
difference_type operator-(contiguous_iterator other) const noexcept { return m_current - other.m_current; }

constexpr normal_iterator operator--(int) noexcept { return normal_iterator(m_current--); }

// Random access iterator requirements
constexpr reference operator[](difference_type n) const noexcept { return m_current[n]; }

constexpr normal_iterator& operator+=(difference_type n) noexcept {
m_current += n;
return *this;
}

constexpr normal_iterator operator+(difference_type n) const noexcept { return normal_iterator(m_current + n); }

constexpr normal_iterator& operator-=(difference_type n) noexcept {
m_current -= n;
return *this;
}

constexpr normal_iterator operator-(difference_type n) const noexcept { return normal_iterator(m_current - n); }

protected:
// The underlying pointer iterator.
IteratorType m_current;
private:
T* m_current;
};

// Forward iterator requirements
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
[[nodiscard]] constexpr inline bool operator==(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
return lhs.base() == rhs.base();
}

template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
[[nodiscard]] constexpr inline bool operator!=(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
return lhs.base() != rhs.base();
}

// Random access iterator requirements
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
[[nodiscard]] inline bool operator<(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
return lhs.base() < rhs.base();
}

template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
[[nodiscard]] inline bool operator>(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
return lhs.base() > rhs.base();
}

template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
[[nodiscard]] inline bool operator<=(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
return lhs.base() <= rhs.base();
}

template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
[[nodiscard]] inline bool operator>=(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
return lhs.base() >= rhs.base();
}

// According to the resolution of DR179 not only the various comparison
// operators but also operator- must accept mixed iterator/const_iterator
template <typename IteratorTypeL, typename IteratorTypeR, typename ContainerType>
[[nodiscard]] constexpr inline auto operator-(const normal_iterator<IteratorTypeL, ContainerType>& lhs,
const normal_iterator<IteratorTypeR, ContainerType>& rhs) noexcept {
return lhs.base() - rhs.base();
}

template <typename IteratorType, typename ContainerType>
[[nodiscard]] constexpr inline normal_iterator<IteratorType, ContainerType>
operator+(typename normal_iterator<IteratorType, ContainerType>::difference_type n,
const normal_iterator<IteratorType, ContainerType>& iter) noexcept {
return normal_iterator(iter.base() + n);
}

} // namespace beman::optional::detail

#endif // BEMAN_OPTIONAL26_OPTIONAL_DETAIL_ITERATOR_HPP
45 changes: 45 additions & 0 deletions include/Beman/Optional26/detail/stl_interfaces/config.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under 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_STL_INTERFACES_CONFIG_HPP
#define BOOST_STL_INTERFACES_CONFIG_HPP

// Included for definition of __cpp_lib_concepts.
#include <iterator>

#if defined(__cpp_lib_concepts) && defined(__cpp_lib_ranges) && !defined(BOOST_STL_INTERFACES_DISABLE_CONCEPTS)
#define BOOST_STL_INTERFACES_USE_CONCEPTS 1
#else
#define BOOST_STL_INTERFACES_USE_CONCEPTS 0
#endif

#if defined(__cpp_explicit_this_parameter) && BOOST_STL_INTERFACES_USE_CONCEPTS && \
!defined(BOOST_STL_INTERFACES_DISABLE_DEDUCED_THIS)
#define BOOST_STL_INTERFACES_USE_DEDUCED_THIS 1
#else
#define BOOST_STL_INTERFACES_USE_DEDUCED_THIS 0
#endif

// The inline namespaces v1, v2, and v3 represent C++14, C++20, and C++23 and
// later, respectively. v1 is inline for standards before C++20, and v2 is
// inline for C++20 and later. Note that this only applies to code for which
// multiple vI namespace alternatives exist. For example, some instances of
// the v1 namespace may still be inline, if there is no v2 version of its
// contents.
#if !BOOST_STL_INTERFACES_USE_CONCEPTS && !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
#define BOOST_STL_INTERFACES_NAMESPACE_V1 inline namespace v1
#define BOOST_STL_INTERFACES_NAMESPACE_V2 namespace v2
#define BOOST_STL_INTERFACES_NAMESPACE_V3 namespace v3
#elif BOOST_STL_INTERFACES_USE_CONCEPTS && !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
#define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1
#define BOOST_STL_INTERFACES_NAMESPACE_V2 inline namespace v2
#define BOOST_STL_INTERFACES_NAMESPACE_V3 namespace v3
#else
#define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1
#define BOOST_STL_INTERFACES_NAMESPACE_V2 namespace v2
#define BOOST_STL_INTERFACES_NAMESPACE_V3 inline namespace v3
#endif

#endif
85 changes: 85 additions & 0 deletions include/Beman/Optional26/detail/stl_interfaces/fwd.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (C) 2019 T. Zachary Laine
//
// Distributed under 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_STL_INTERFACES_FWD_HPP
#define BOOST_STL_INTERFACES_FWD_HPP

#include <Beman/Optional26/detail/stl_interfaces/config.hpp>

#if BOOST_STL_INTERFACES_USE_CONCEPTS
#include <ranges>
#endif
#if defined(__cpp_lib_three_way_comparison)
#include <compare>
#endif

#ifndef BOOST_STL_INTERFACES_DOXYGEN

#if defined(_MSC_VER) || defined(__GNUC__) && __GNUC__ < 8
#define BOOST_STL_INTERFACES_NO_HIDDEN_FRIEND_CONSTEXPR
#define BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR
#else
#define BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR constexpr
#endif

#if defined(__GNUC__) && __GNUC__ < 9
#define BOOST_STL_INTERFACES_CONCEPT concept bool
#else
#define BOOST_STL_INTERFACES_CONCEPT concept
#endif

#endif

namespace boost {
namespace stl_interfaces {

/** An enumeration used to indicate whether the underlying data have a
contiguous or discontiguous layout when instantiating `view_interface`
and `sequence_container_interface`. */
enum class element_layout : bool { discontiguous = false, contiguous = true };

BOOST_STL_INTERFACES_NAMESPACE_V1 {

namespace v1_dtl {
template <typename... T>
using void_t = void;

template <typename Iter>
using iter_difference_t = typename std::iterator_traits<Iter>::difference_type;

template <typename Range, typename = void>
struct iterator;
template <typename Range>
struct iterator<Range, void_t<decltype(std::declval<Range&>().begin())>> {
using type = decltype(std::declval<Range&>().begin());
};
template <typename Range>
using iterator_t = typename iterator<Range>::type;

template <typename Range, typename = void>
struct sentinel;
template <typename Range>
struct sentinel<Range, void_t<decltype(std::declval<Range&>().end())>> {
using type = decltype(std::declval<Range&>().end());
};
template <typename Range>
using sentinel_t = typename sentinel<Range>::type;

template <typename Range>
using range_difference_t = iter_difference_t<iterator_t<Range>>;

template <typename Range>
using common_range = std::is_same<iterator_t<Range>, sentinel_t<Range>>;

template <typename Range, typename = void>
struct decrementable_sentinel : std::false_type {};
template <typename Range>
struct decrementable_sentinel<Range, void_t<decltype(--std::declval<sentinel_t<Range>&>())>> : std::true_type {};
} // namespace v1_dtl
}
} // namespace stl_interfaces
} // namespace boost

#endif
Loading

0 comments on commit a6c6fa3

Please sign in to comment.