Skip to content

Commit

Permalink
Use iterator_interface in base_view::iterator definition
Browse files Browse the repository at this point in the history
Define `huffman::detail::iterator_interface`, a CRTP helper class to
synthesize boiler-plate operations necessary to model
`std::random_access_iterator`. This allows `detail::base_view::iterator`
to define only the necessary basis operations, as well simplifying the
implementation of `bit_span::iterator` in a future commit.

Change-Id: I8fe5c4b00a905d60621e84f5396df90668d307a5
  • Loading branch information
oliverlee authored and garymm committed Jun 26, 2023
1 parent 8599340 commit a495431
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 63 deletions.
1 change: 1 addition & 0 deletions huffman/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ cc_library(
"src/bit.hpp",
"src/code.hpp",
"src/detail/base_view.hpp",
"src/detail/iterator_interface.hpp",
"src/detail/static_vector.hpp",
"src/detail/table_node.hpp",
"src/detail/table_storage.hpp",
Expand Down
71 changes: 8 additions & 63 deletions huffman/src/detail/base_view.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "huffman/src/detail/iterator_interface.hpp"

#include <concepts>
#include <iterator>
#include <ranges>
Expand All @@ -11,7 +13,7 @@ namespace gpu_deflate::huffman::detail {
/// @tparam V underlying view
/// @tparam B base class
///
template <std::ranges::forward_range V, class B>
template <std::ranges::random_access_range V, class B>
requires std::ranges::view<V> and
std::same_as<std::ranges::iterator_t<V>,
std::ranges::sentinel_t<V>> and
Expand All @@ -20,15 +22,15 @@ class base_view : public std::ranges::view_interface<base_view<V, B>>
{
// This is largely adapted from `transform_view` (or other views), although we
// apply some simplifications:
// * V must model `forward_range` instead of `input_range`
// * V must model `random_access_range` instead of `input_range`
// * sentinel_t<V> is the same as iterator_t<V>
//
// https://eel.is/c++draft/range.transform

V base_{};

public:
class iterator
class iterator : public iterator_interface<iterator>
{
using base_iterator = std::ranges::iterator_t<V>;
base_iterator base_{};
Expand Down Expand Up @@ -56,78 +58,21 @@ class base_view : public std::ranges::view_interface<base_view<V, B>>
{
return static_cast<reference>(*base_);
}
constexpr auto operator->() const -> pointer { return &**this; }

constexpr auto operator++() -> iterator&
{
++base_;
return *this;
}
constexpr auto operator++(int) -> iterator
{
auto tmp = *this;
++*this;
return tmp;
}

constexpr auto operator--() -> iterator&
requires std::ranges::bidirectional_range<V>
{
--base_;
return *this;
}
constexpr auto operator--(int) -> iterator
requires std::ranges::bidirectional_range<V>
{
auto tmp = *this;
--*this;
return tmp;
}

constexpr auto operator+=(difference_type n) -> iterator&
requires std::ranges::random_access_range<V>
{
base_ += n;
return *this;
}
constexpr auto operator-=(difference_type n) -> iterator&
requires std::ranges::random_access_range<V>
{
base_ -= n;
return *this;
}

constexpr auto operator[](difference_type n) const -> reference
requires std::ranges::random_access_range<V>
{
return static_cast<reference>(base_[n]);
}

friend constexpr auto
operator<=>(const iterator&, const iterator&) = default;

friend constexpr auto operator+(iterator i, difference_type n) -> iterator
requires std::ranges::random_access_range<V>
{
return i += n;
}
friend constexpr auto operator+(difference_type n, iterator i) -> iterator
requires std::ranges::random_access_range<V>
{
return i + n;
}

friend constexpr auto operator-(iterator i, difference_type n) -> iterator
requires std::ranges::random_access_range<V>
{
return i -= n;
}
friend constexpr auto
operator-(const iterator& x, const iterator& y) -> difference_type
requires std::ranges::random_access_range<V>
{
return x.base() - y.base();
}

friend constexpr auto
operator<=>(const iterator&, const iterator&) = default;
};

base_view()
Expand Down
107 changes: 107 additions & 0 deletions huffman/src/detail/iterator_interface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#pragma once

#include <concepts>
#include <iterator>

namespace gpu_deflate::huffman::detail {

/// CRTP helper class used to synthesize operations for a random access iterator
/// @tparam D derived iterator type
///
/// A simplified implementation of `iterator_interface`. This CRTP helper class
/// synthesizes iterator operations given a basis set of operations. This type
/// currently requires `D` to implement the following operations:
/// * operator*() const -> reference
/// * operator+=(difference_type) -> D&
/// and the following static member typedefs
/// * pointer
/// * reference
/// * difference_type
///
/// Note that `D` must also define the following operations to model
/// `std::random_access_iterator`
/// * D()
/// * operator-(const D&, const D&) -> difference_type
/// * operator<=>(const D&, const D&)
/// and static member typedefs
/// * iterator_category
/// * value_type
///
template <class D>
struct iterator_interface
{

template <class I = D>
constexpr auto operator->() const -> typename I::pointer
{
return &*static_cast<const I&>(*this);
}

template <class I = D>
constexpr auto operator++() -> I&
{
return static_cast<I&>(*this) += typename I::difference_type{1};
}

template <class I = D>
constexpr auto operator++(int) -> I
{
auto tmp = *this;
++*this;
return tmp;
}

template <class I = D>
constexpr auto operator--() -> I&
{
return *this -= typename I::difference_type{1};
}

template <class I = D>
constexpr auto operator--(int) -> I
{
auto tmp = *this;
--*this;
return tmp;
}

template <class I = D>
constexpr auto operator-=(typename I::difference_type n) -> I&
{
return static_cast<I&>(*this) += -n;
}

template <class I = D>
constexpr auto
operator[](typename I::difference_type n) const -> typename I::reference
{
return *(*this + n);
}

template <std::same_as<D> I>
friend constexpr auto operator+(I i, typename I::difference_type n) -> I
{
return i += n;
}

template <std::same_as<D> I>
friend constexpr auto operator+(typename I::difference_type n, I i) -> I
{
return i + n;
}

template <std::same_as<D> I>
friend constexpr auto operator-(I i, typename I::difference_type n) -> I
{
return i + -n;
}

/// Default three-way comparison
///
// This must be defined to allow three-way comparison for derived class `I` to
// be defaulted.
friend constexpr auto
operator<=>(const iterator_interface&, const iterator_interface&) = default;
};

} // namespace gpu_deflate::huffman::detail

0 comments on commit a495431

Please sign in to comment.