Last active
April 3, 2020 08:13
-
-
Save poyenc/dddf25331f6ca2aa11425cdd5f94073c to your computer and use it in GitHub Desktop.
Iterator adaptor for random access range which has not provided iterator interfaces (C++17)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <iterator> | |
#include <type_traits> | |
#include <utility> | |
template <typename RandomAccessRange> | |
class index_iterator { | |
public: | |
using target_type = RandomAccessRange; | |
using target_pointer_type = std::add_pointer_t<RandomAccessRange>; | |
using size_type = decltype(size(std::declval<target_type>())); | |
using reference = decltype(std::declval<target_type>()[std::declval<size_type>()]); | |
using value_type = std::remove_reference_t<reference>; | |
using signed_size_type = std::make_signed_t<size_type>; | |
using difference_type = signed_size_type; | |
index_iterator() noexcept : target_(nullptr), index_(0) {} | |
explicit index_iterator(target_type &target, signed_size_type index) noexcept | |
: target_(std::addressof(target)), index_(index) {} | |
reference operator*() const { | |
return (*target_)[static_cast<size_type>(index())]; | |
} | |
index_iterator &operator++() noexcept { | |
++index_; | |
return *this; | |
} | |
index_iterator operator++(int) noexcept { | |
index_iterator copy = *this; | |
++(*this); | |
return copy; | |
} | |
index_iterator &operator--() noexcept { | |
--index_; | |
return *this; | |
} | |
index_iterator operator--(int) noexcept { | |
index_iterator copy = *this; | |
--(*this); | |
return copy; | |
} | |
signed_size_type index() const noexcept { return index_; } | |
private: | |
target_pointer_type target_; | |
signed_size_type index_; | |
}; | |
// specialization for std::bitset | |
template <std::size_t N> | |
inline index_iterator<std::bitset<N>> begin(std::bitset<N> &bitset) { | |
return index_iterator<std::bitset<N>>(bitset, 0); | |
} | |
template <std::size_t N> | |
inline index_iterator<std::bitset<N>> end(std::bitset<N> &bitset) { | |
return index_iterator<std::bitset<N>>(bitset, size(bitset)); | |
} | |
template <std::size_t N> | |
inline bool operator==(const index_iterator<std::bitset<N>> &lhs, | |
const index_iterator<std::bitset<N>> &rhs) { | |
return lhs.index() == rhs.index(); | |
} | |
template <std::size_t N> | |
inline bool operator!=(const index_iterator<std::bitset<N>> &lhs, | |
const index_iterator<std::bitset<N>> &rhs) { | |
return !(lhs == rhs); | |
} | |
namespace std { | |
template <std::size_t N> | |
class iterator_traits<index_iterator<std::bitset<N>>> { | |
using iterator = index_iterator<std::bitset<N>>; | |
public: | |
using value_type = typename iterator::value_type; | |
using reference = typename iterator::reference; | |
using difference_type = typename iterator::difference_type; | |
using iterator_category = std::bidirectional_iterator_tag; | |
}; | |
} // namespace std |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment