-
Notifications
You must be signed in to change notification settings - Fork 0
/
listiterator.hpp
122 lines (94 loc) · 2.48 KB
/
listiterator.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#ifndef XL_LISTITERATOR_HPP
# define XL_LISTITERATOR_HPP
# pragma once
#include <iterator>
#include <type_traits>
#include <utility>
namespace xl
{
namespace detail
{
constexpr auto assign(auto& ...a) noexcept
{ // assign idiom
return [&](auto const ...b) noexcept { assign((a = b)...); };
}
constexpr auto conv(auto const ...n) noexcept
{
return (std::uintptr_t(n) ^ ...);
}
constexpr auto next(auto i, auto n) noexcept
{
for (; n; --n, ++i);
return i;
}
constexpr auto next2(auto i, auto n) noexcept
{
for (; n && i; --n, ++i);
return i;
}
}
template <typename T>
class listiterator
{
using iterator_t = listiterator<std::remove_const_t<T>>;
friend listiterator<T const>;
template <typename U> requires(!std::is_reference_v<U>) friend class list;
using node_t = std::remove_const_t<T>;
node_t* n_, *p_;
public:
using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::intmax_t;
using value_type = std::conditional_t<
std::is_const_v<T>,
typename T::value_type const,
typename T::value_type
>;
using pointer = value_type*;
using reference = value_type&;
public:
listiterator() = default;
listiterator(node_t* const n, node_t* const p) noexcept:
n_(n),
p_(p)
{
}
listiterator(listiterator const&) = default;
listiterator(listiterator&&) = default;
listiterator(iterator_t const& o) noexcept
requires(std::is_const_v<T>):
n_(o.n_),
p_(o.p_)
{
}
// conversion to bool
explicit operator bool() const noexcept { return n_; }
// assignment
listiterator& operator=(listiterator const&) = default;
listiterator& operator=(listiterator&&) = default;
listiterator& operator=(iterator_t const& o) noexcept
requires(std::is_const_v<T>)
{
n_ = o.n_; p_ = o.p_; return *this;
}
// increment, decrement
auto& operator++() noexcept
{
detail::assign(n_, p_)(n_->link(p_), n_); return *this;
}
auto& operator--() noexcept
{
detail::assign(n_, p_)(p_, p_->link(n_)); return *this;
}
auto operator++(int) noexcept { auto const r(*this); ++*this; return r; }
auto operator--(int) noexcept { auto const r(*this); --*this; return r; }
// comparison
bool operator==(listiterator const& o) const noexcept { return n_ == o.n_; }
// member access
auto operator->() const noexcept
{
return std::addressof(std::add_pointer_t<T>(n_)->v_);
}
auto& operator*() const noexcept { return std::add_pointer_t<T>(n_)->v_; }
};
}
#endif // XL_LISTITERATOR_HPP