#pragma once #include #include #include // TODO: Specify the concept of an iterator namespace gp { /** * @brief An abstraction of a pointer to iterate against, in both normal and reverse order * * @tparam T The type of data pointed by the iterator * @tparam sign the direction in which data is scrutinized, should be either 1 or -1, behaviour for other value is left undefined */ template struct pointer_iterator final { T* data; /**< the only data field of the class */ typedef T value_type; /**< The type of which a reference will be returned on dereferencing */ typedef std::intptr_t difference_type; /**< The type of the substraction of two pointers */ static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator; /**< @see iterator_type_t */ /** * @brief Generates an empty iterator */ constexpr pointer_iterator() : data{nullptr} {} constexpr pointer_iterator(const pointer_iterator& oth) : data{oth.data} {} /** * @brief Generates an iterator from any pointer */ constexpr pointer_iterator(T* ptr) : data{ptr} {} /** * @brief Dereference unary operator * * @return constexpr T& returns a reference to the pointed value */ constexpr T& operator*() const { return *data; } constexpr pointer_iterator& operator++() { data += sign; return *this; } constexpr pointer_iterator operator++(int) { auto p = *this; data += sign; return p; } constexpr pointer_iterator& operator--() { data -= sign; return *this; } constexpr pointer_iterator operator--(int) { auto p = *this; data -= sign; return p; } constexpr pointer_iterator operator+(const std::size_t offset) const { return pointer_iterator{data+sign*offset}; } constexpr pointer_iterator operator+(const difference_type offset) const { return pointer_iterator{data+sign*offset}; } constexpr pointer_iterator operator+(const int offset) const { return pointer_iterator{data+sign*offset}; } constexpr pointer_iterator operator-(const std::size_t offset) const { return pointer_iterator{data-sign*offset}; } constexpr pointer_iterator operator-(const difference_type offset) const { return pointer_iterator{data-sign*offset}; } constexpr pointer_iterator operator-(const int offset) const { return pointer_iterator{data-sign*offset}; } constexpr difference_type operator-(const pointer_iterator& oth) const { return (data-oth.data)*sign; } constexpr bool operator==(const pointer_iterator oth) const { return data==oth.data; } constexpr bool operator!=(pointer_iterator oth) const { return data!=oth.data; } constexpr bool before_or_equal(const pointer_iterator oth) const { return reinterpret_cast(data) <= reinterpret_cast(oth.data); } constexpr bool after_or_equal(const pointer_iterator oth) const { return reinterpret_cast(data) >= reinterpret_cast(oth.data); } constexpr bool operator<=(const pointer_iterator oth) const { return before_or_equal(oth); } constexpr bool operator>=(const pointer_iterator oth) const { return after_or_equal(oth); } }; /** * @brief An identical twin to the pointer_iterator, but which dereference to a const reference * * @see pointer_iterator * @tparam T @see pointer_iterator * @tparam sign @see pointer_iterator */ template struct const_pointer_iterator final { const T* data; /**< @see pointer_iterator */ typedef T value_type; /**< @see pointer_iterator */ typedef std::intptr_t difference_type; /**< @see pointer_iterator */ static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator; /**< @see pointer_iterator */ constexpr const_pointer_iterator(const const_pointer_iterator& oth) : data{oth.data} {} /** * @brief @see pointer_iterator */ constexpr const_pointer_iterator(const T* ptr) : data{ptr} {} /** * @brief Dereferencing returns a const version of what a pointer_iterator would return */ constexpr const T& operator*() const { return *data; } constexpr const_pointer_iterator& operator++() { data += sign; return *this; } constexpr const_pointer_iterator operator++(int) { auto p = data; data += sign; return const_pointer_iterator{p}; } constexpr const_pointer_iterator& operator--() { data -= sign; return *this; } constexpr const_pointer_iterator operator--(int) { auto p = data; data -= sign; return const_pointer_iterator{p}; } constexpr const_pointer_iterator operator+(const std::size_t offset) const { return const_pointer_iterator{data+sign*offset}; } constexpr const_pointer_iterator operator+(const difference_type offset) const { return const_pointer_iterator{data+sign*offset}; } constexpr const_pointer_iterator operator+(const int offset) const { return const_pointer_iterator{data+sign*offset}; } constexpr const_pointer_iterator operator-(const difference_type offset) const { return const_pointer_iterator{data-sign*offset}; } constexpr const_pointer_iterator operator-(const std::size_t offset) const { return const_pointer_iterator{data-sign*offset}; } constexpr const_pointer_iterator operator-(const int offset) { return const_pointer_iterator{data-sign*offset}; } constexpr difference_type operator-(const const_pointer_iterator& oth) const { return ((T*)data-(T*)oth.data)*sign; } constexpr bool operator==(const const_pointer_iterator oth) const { return data==oth.data; } constexpr bool operator!=(const_pointer_iterator oth) const { return data!=oth.data; } constexpr bool before_or_equal(const const_pointer_iterator oth) const { return reinterpret_cast(data) <= reinterpret_cast(oth.data); } constexpr bool after_or_equal(const const_pointer_iterator oth) const { return reinterpret_cast(data) >= reinterpret_cast(oth.data); } constexpr bool operator<=(const const_pointer_iterator oth) const { return before_or_equal(oth); } constexpr bool operator>=(const const_pointer_iterator oth) const { return after_or_equal(oth); } }; }