Skip to content

Instantly share code, notes, and snippets.

@poyenc
Last active April 3, 2020 08:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save poyenc/dddf25331f6ca2aa11425cdd5f94073c to your computer and use it in GitHub Desktop.
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)
#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