libdl  0.0.1
Simple yet powerful deep learning
Loading...
Searching...
No Matches
generic_iterator.hpp
1#pragma once
2
3#include <iterator>
4#include <memory>
5
6namespace dl::utils {
7
23 template <typename T>
25 private:
33 class AIter {
34 public:
36 virtual ~AIter() noexcept = default;
42 virtual T deref() const noexcept = 0;
47 virtual void advance() noexcept = 0;
55 virtual bool equals(const AIter& other) const noexcept = 0;
72 virtual const std::type_info& type() const = 0;
79 virtual std::unique_ptr<AIter> clone() const = 0;
80 };
81
88 template <std::input_or_output_iterator TIt>
89 class Iter final : public AIter {
90 private:
94 TIt iterator;
107 std::shared_ptr<void> userdata;
108
109 public:
116 explicit Iter(TIt& iterator) noexcept : iterator(iterator), userdata(nullptr) {}
117
125 Iter(TIt& iterator, std::shared_ptr<auto> userdata) : iterator(iterator), userdata(userdata) {}
126
127 T deref() const noexcept override { return *iterator; }
128 void advance() noexcept override { std::ranges::advance(iterator, 1); }
129 bool equals(const AIter& other) const noexcept override {
130 return other.type() == type() && static_cast<const Iter<TIt>&>(other).iterator == iterator;
131 }
132 const std::type_info& type() const override { return typeid(this); }
133 std::unique_ptr<AIter> clone() const override { return std::make_unique<Iter<TIt>>(*this); }
134 };
135
140
141 public:
144 using value_type = T;
145 using pointer = T*;
146 using reference = T&;
147
151 GenericIterator() : impl(nullptr) {}
152
158 GenericIterator(const GenericIterator<T>& other) : impl(other.impl->clone()) {}
159
165 GenericIterator(GenericIterator<T>&& other) : impl(std::move(other.impl)) {}
166
175 template <std::input_or_output_iterator TIt>
176 explicit GenericIterator(TIt iterator) noexcept : impl(std::make_unique<Iter<TIt>>(iterator)) {}
177
188 template <std::input_or_output_iterator TIt>
189 GenericIterator(TIt iterator, std::shared_ptr<auto> userdata) noexcept
190 : impl(std::make_unique<Iter<TIt>>(iterator, userdata)) {}
191
199 impl = other.impl;
200 return *this;
201 }
202
210 impl = std::move(other.impl);
211 return *this;
212 }
213
219 T operator*() const { return impl->deref(); }
226 impl->advance();
227 return *this;
228 }
236 auto copy = *this;
237 (*this)++;
238 return copy;
239 }
246 bool operator==(const GenericIterator<T>& other) const { return impl->equals(*other.impl); }
247 };
248
249 static_assert(std::input_iterator<GenericIterator<int>>);
250} // namespace dl::utils
Represents a generic iterator that can be initialized to hold any other class instance that satisfies...
bool operator==(const GenericIterator< T > &other) const
Checks if this iterator is equal to the provided one.
GenericIterator()
Default constructor that creates a nullptr-iterator.
GenericIterator< T > & operator=(GenericIterator< T > &&other) noexcept
Move-assignment operator.
GenericIterator(const GenericIterator< T > &other)
Copy-constructs a new generic iterator.
GenericIterator< T > operator++(int) noexcept
Late increments the iterator. That is, advances the iterator by one but returns a copy of the iterato...
GenericIterator< T > & operator++() noexcept
Increments the iterator. That is, advancing it forward by one.
GenericIterator< T > & operator=(const GenericIterator< T > &other) noexcept
Assignment opterator.
GenericIterator(GenericIterator< T > &&other)
Move-constructs a new generic iterator.
T operator*() const
Dereferences the iterator. That is, returns the data it currently points at.
GenericIterator(TIt iterator) noexcept
Constructs a new GenericIterator from the provided arbitrary object that satisfies the std::input_or_...
GenericIterator(TIt iterator, std::shared_ptr< auto > userdata) noexcept
Constructs a new GenericIterator from the provided arbitrary object that satisfies the std::input_or_...
T move(T... args)