aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/containers/flat_hash/lib/iterator.h
blob: f6b1e74355de6fc7340a02a96f7adc4851c8cec6 (plain) (blame)
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
#pragma once

#include "concepts/container.h"

#include <util/system/yassert.h>

#include <iterator>

namespace NFlatHash {

template <class Container, class T>
class TIterator {
private:
    static_assert(NConcepts::ContainerV<std::decay_t<Container>>);

public:
    using iterator_category = std::forward_iterator_tag;
    using value_type = T;
    using difference_type = ptrdiff_t;
    using pointer = typename std::add_pointer<T>::type;
    using reference = typename std::add_lvalue_reference<T>::type;

private:
    using size_type = typename Container::size_type;

public:
    TIterator(Container* cont)
        : Cont_(cont)
        , Idx_(0)
    {
        if (!cont->IsTaken(Idx_)) {
            Next();
        }
    }

    TIterator(Container* cont, size_type idx)
        : Cont_(cont)
        , Idx_(idx) {}

    template <class C, class U, class = std::enable_if_t<std::is_convertible<C*, Container*>::value &&
                                                         std::is_convertible<U, T>::value>>
    TIterator(const TIterator<C, U>& rhs)
        : Cont_(rhs.Cont_)
        , Idx_(rhs.Idx_) {}

    TIterator(const TIterator&) = default;

    TIterator& operator=(const TIterator&) = default;

    TIterator& operator++() {
        Next();
        return *this;
    }
    TIterator operator++(int) {
        auto idx = Idx_;
        Next();
        return { Cont_, idx };
    }

    reference operator*() {
        return Cont_->Node(Idx_);
    }

    pointer operator->() {
        return &Cont_->Node(Idx_);
    }

    const pointer operator->() const {
        return &Cont_->Node(Idx_);
    }

    bool operator==(const TIterator& rhs) const noexcept {
        Y_ASSERT(Cont_ == rhs.Cont_);
        return Idx_ == rhs.Idx_;
    }

    bool operator!=(const TIterator& rhs) const noexcept {
        return !operator==(rhs);
    }

private:
    void Next() {
        // Container provider ensures that it's not empty.
        do {
            ++Idx_;
        } while (Idx_ != Cont_->Size() && !Cont_->IsTaken(Idx_));
    }

private:
    template <class C, class U>
    friend class TIterator;

    Container* Cont_ = nullptr;

protected:
    size_type Idx_ = 0;
};

}  // namespace NFlatHash