Skip to main content
replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

Following the paradigms of SCARY iteratorsSCARY iterators, there should only be a single iterator-type for contiguous iterators per value-type.
Here my code for that iterator, working with C++11+:

Following the paradigms of SCARY iterators, there should only be a single iterator-type for contiguous iterators per value-type.
Here my code for that iterator, working with C++11+:

Following the paradigms of SCARY iterators, there should only be a single iterator-type for contiguous iterators per value-type.
Here my code for that iterator, working with C++11+:

added three missing const's
Source Link
Deduplicator
  • 19.3k
  • 1
  • 31
  • 65
#include <type_traits>
#include <iterator>

template<class T, class U>
struct is_more_cv_qualified : std::integral_constant<bool, std::is_same<T, const volatile U>{}
    || std::is_same<T, const U>{} || std::is_same<T, volatile U>{}>;

struct contiguous_iterator_tag : std::random_access_iterator_tag {};
struct mutable_contiguous_iterator_tag : contiguous_iterator_tag, std::output_iterator_tag {};

template<class T>
struct contiguous_iterator_base {
    constexpr bool operator==(contiguous_iterator_base other) const noexcept { return _p == other.p; }
    constexpr bool operator!=(contiguous_iterator_base other) const noexcept { return _p != other.p; }
    constexpr bool operator<(contiguous_iterator_base other) const noexcept { return _p < other._p; }
    constexpr bool operator>(contiguous_iterator_base other) const noexcept { return _p > other._p; }
    constexpr bool operator<=(contiguous_iterator_base other) const noexcept { return _p <= other._p; }
    constexpr bool operator>=(contiguous_iterator_base other) const noexcept { return _p >= other._p; }
    constexpr std::ptrdiff_t operator-(contiguous_iterator_base other) const noexcept { return _p - other._p; }
protected:
    constexpr contiguous_iterator_base& operator=(const contiguous_iterator_base&) noexcept = default;
    T* _p = nullptr;
};

template<class T>
struct contiguous_iterator : contiguous_iterator_base<std::remove_cv<T>::type>
, std::iterator<typename std::conditional<std::is_const<T>{}, contiguous_iterator_tag, mutable_contiguous_iterator_tag>::type, T> {
    constexpr contiguous_iterator() noexcept = default;
    template<class U, class = std::enable_if<is_more_cv_qualified<T, U>{}>::type>
    constexpr contiguous_iterator(contiguous_iterator<U> other) noexcept : contiguous_iterator_base<std::remove_cv<T>::type>(other) {}
    constexpr explicit contiguous_iterator(contiguous_iterator_base<std::remove_cv<T>::type> other) noexcept : decltype(other)(other) {}
    constexpr explicit contiguous_iterator(T* p) noexcept { _p = const_cast<decltype(_p)>(p); }
    template<class U>
    constexpr contiguous_iterator<U> rebind() const noexcept { return contiguous_iterator<U>(_p); }
    constexpr T* operator->() const noexcept { return  _p; }
    constexpr T& operator* () const noexcept { return *_p; }
    constexpr T& operator[](std::ptrdiff_t d) const noexcept { return _p[d]; }
    constexpr contiguous_iterator& operator++() noexcept { ++_p; return *this; }
    constexpr contiguous_iterator operator++(int) noexcept { auto r = *this; ++*this; return r; }
    constexpr contiguous_iterator& operator--() noexcept { --_p; return *this; }
    constexpr contiguous_iterator operator--(int) noexcept { auto r = *this; --*this; return r; }
    constexpr contiguous_iterator& operator+=(std::ptrdiff_t d) noexcept { _p += d; return *this; }
    constexpr contiguous_iterator& operator-=(std::ptrdiff_t d) noexcept { _p -= d; return *this; }
    constexpr contiguous_iterator operator+(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) += d; }
    constexpr contiguous_iterator operator-(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) -= d; }
protected:
    using contiguous_iterator_base<std::remove_cv<T>::type>::_p;
};

// smoke test

int main() {
    contiguous_iterator_base<int>{};
    contiguous_iterator<int> a;
    contiguous_iterator<const int> b;
    b = a;
    a = b.rebind<int>();
    //a.rebind<char>(); error
}
#include <type_traits>
#include <iterator>

template<class T, class U>
struct is_more_cv_qualified : std::integral_constant<bool, std::is_same<T, const volatile U>{}
    || std::is_same<T, const U>{} || std::is_same<T, volatile U>{}>;

struct contiguous_iterator_tag : std::random_access_iterator_tag {};
struct mutable_contiguous_iterator_tag : contiguous_iterator_tag, std::output_iterator_tag {};

template<class T>
struct contiguous_iterator_base {
    constexpr bool operator==(contiguous_iterator_base other) const noexcept { return _p == other.p; }
    constexpr bool operator!=(contiguous_iterator_base other) const noexcept { return _p != other.p; }
    constexpr bool operator<(contiguous_iterator_base other) const noexcept { return _p < other._p; }
    constexpr bool operator>(contiguous_iterator_base other) const noexcept { return _p > other._p; }
    constexpr bool operator<=(contiguous_iterator_base other) const noexcept { return _p <= other._p; }
    constexpr bool operator>=(contiguous_iterator_base other) const noexcept { return _p >= other._p; }
    constexpr std::ptrdiff_t operator-(contiguous_iterator_base other) const noexcept { return _p - other._p; }
protected:
    constexpr contiguous_iterator_base& operator=(const contiguous_iterator_base&) noexcept = default;
    T* _p = nullptr;
};

template<class T>
struct contiguous_iterator : contiguous_iterator_base<std::remove_cv<T>::type>
, std::iterator<typename std::conditional<std::is_const<T>{}, contiguous_iterator_tag, mutable_contiguous_iterator_tag>::type, T> {
    constexpr contiguous_iterator() noexcept = default;
    template<class U, class = std::enable_if<is_more_cv_qualified<T, U>{}>::type>
    constexpr contiguous_iterator(contiguous_iterator<U> other) noexcept : contiguous_iterator_base<std::remove_cv<T>::type>(other) {}
    constexpr explicit contiguous_iterator(contiguous_iterator_base<std::remove_cv<T>::type> other) noexcept : decltype(other)(other) {}
    constexpr explicit contiguous_iterator(T* p) noexcept { _p = const_cast<decltype(_p)>(p); }
    template<class U>
    constexpr contiguous_iterator<U> rebind() const noexcept { return contiguous_iterator<U>(_p); }
    constexpr T* operator->() noexcept { return  _p; }
    constexpr T& operator* () noexcept { return *_p; }
    constexpr T& operator[](std::ptrdiff_t d) noexcept { return _p[d]; }
    constexpr contiguous_iterator& operator++() noexcept { ++_p; return *this; }
    constexpr contiguous_iterator operator++(int) noexcept { auto r = *this; ++*this; return r; }
    constexpr contiguous_iterator& operator--() noexcept { --_p; return *this; }
    constexpr contiguous_iterator operator--(int) noexcept { auto r = *this; --*this; return r; }
    constexpr contiguous_iterator& operator+=(std::ptrdiff_t d) noexcept { _p += d; return *this; }
    constexpr contiguous_iterator& operator-=(std::ptrdiff_t d) noexcept { _p -= d; return *this; }
    constexpr contiguous_iterator operator+(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) += d; }
    constexpr contiguous_iterator operator-(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) -= d; }
protected:
    using contiguous_iterator_base<std::remove_cv<T>::type>::_p;
};

// smoke test

int main() {
    contiguous_iterator_base<int>{};
    contiguous_iterator<int> a;
    contiguous_iterator<const int> b;
    b = a;
    a = b.rebind<int>();
    //a.rebind<char>(); error
}
#include <type_traits>
#include <iterator>

template<class T, class U>
struct is_more_cv_qualified : std::integral_constant<bool, std::is_same<T, const volatile U>{}
    || std::is_same<T, const U>{} || std::is_same<T, volatile U>{}>;

struct contiguous_iterator_tag : std::random_access_iterator_tag {};
struct mutable_contiguous_iterator_tag : contiguous_iterator_tag, std::output_iterator_tag {};

template<class T>
struct contiguous_iterator_base {
    constexpr bool operator==(contiguous_iterator_base other) const noexcept { return _p == other.p; }
    constexpr bool operator!=(contiguous_iterator_base other) const noexcept { return _p != other.p; }
    constexpr bool operator<(contiguous_iterator_base other) const noexcept { return _p < other._p; }
    constexpr bool operator>(contiguous_iterator_base other) const noexcept { return _p > other._p; }
    constexpr bool operator<=(contiguous_iterator_base other) const noexcept { return _p <= other._p; }
    constexpr bool operator>=(contiguous_iterator_base other) const noexcept { return _p >= other._p; }
    constexpr std::ptrdiff_t operator-(contiguous_iterator_base other) const noexcept { return _p - other._p; }
protected:
    constexpr contiguous_iterator_base& operator=(const contiguous_iterator_base&) noexcept = default;
    T* _p = nullptr;
};

template<class T>
struct contiguous_iterator : contiguous_iterator_base<std::remove_cv<T>::type>
, std::iterator<typename std::conditional<std::is_const<T>{}, contiguous_iterator_tag, mutable_contiguous_iterator_tag>::type, T> {
    constexpr contiguous_iterator() noexcept = default;
    template<class U, class = std::enable_if<is_more_cv_qualified<T, U>{}>::type>
    constexpr contiguous_iterator(contiguous_iterator<U> other) noexcept : contiguous_iterator_base<std::remove_cv<T>::type>(other) {}
    constexpr explicit contiguous_iterator(contiguous_iterator_base<std::remove_cv<T>::type> other) noexcept : decltype(other)(other) {}
    constexpr explicit contiguous_iterator(T* p) noexcept { _p = const_cast<decltype(_p)>(p); }
    template<class U>
    constexpr contiguous_iterator<U> rebind() const noexcept { return contiguous_iterator<U>(_p); }
    constexpr T* operator->() const noexcept { return  _p; }
    constexpr T& operator* () const noexcept { return *_p; }
    constexpr T& operator[](std::ptrdiff_t d) const noexcept { return _p[d]; }
    constexpr contiguous_iterator& operator++() noexcept { ++_p; return *this; }
    constexpr contiguous_iterator operator++(int) noexcept { auto r = *this; ++*this; return r; }
    constexpr contiguous_iterator& operator--() noexcept { --_p; return *this; }
    constexpr contiguous_iterator operator--(int) noexcept { auto r = *this; --*this; return r; }
    constexpr contiguous_iterator& operator+=(std::ptrdiff_t d) noexcept { _p += d; return *this; }
    constexpr contiguous_iterator& operator-=(std::ptrdiff_t d) noexcept { _p -= d; return *this; }
    constexpr contiguous_iterator operator+(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) += d; }
    constexpr contiguous_iterator operator-(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) -= d; }
protected:
    using contiguous_iterator_base<std::remove_cv<T>::type>::_p;
};

// smoke test

int main() {
    contiguous_iterator_base<int>{};
    contiguous_iterator<int> a;
    contiguous_iterator<const int> b;
    b = a;
    a = b.rebind<int>();
    //a.rebind<char>(); error
}
added 96 characters in body
Source Link
Deduplicator
  • 19.3k
  • 1
  • 31
  • 65

Following the paradigms of SCARY iteratorsSCARY iterators, there should only be a single iterator-type for contiguous iterators per value-type.
Here my code for that iterator, working with C++11+:

#include <type_traits>
#include <iterator>

template<class T, class U>
struct is_more_cv_qualified : std::integral_constant<bool, std::is_same<T, const volatile U>{}
    || std::is_same<T, const U>{} || std::is_same<T, volatile U>{}>;

struct contiguous_iterator_tag : std::random_access_iterator_tag {};
struct mutable_contiguous_iterator_tag : contiguous_iterator_tag, std::output_iterator_tag {};

template<class T>
struct contiguous_iterator_base {
    constexpr bool operator==(contiguous_iterator_base other) const noexcept { return _p == other.p; }
    constexpr bool operator!=(contiguous_iterator_base other) const noexcept { return _p != other.p; }
    constexpr bool operator<(contiguous_iterator_base other) const noexcept { return _p < other._p; }
    constexpr bool operator>(contiguous_iterator_base other) const noexcept { return _p > other._p; }
    constexpr bool operator<=(contiguous_iterator_base other) const noexcept { return _p <= other._p; }
    constexpr bool operator>=(contiguous_iterator_base other) const noexcept { return _p >= other._p; }
    constexpr std::ptrdiff_t operator-(contiguous_iterator_base other) const noexcept { return _p - other._p; }
protected:
    constexpr contiguous_iterator_base& operator=(const contiguous_iterator_base&) noexcept = default;
    T* _p = nullptr;
};

template<class T>
struct contiguous_iterator : contiguous_iterator_base<std::remove_cv_t<T>>remove_cv<T>::type>
, std::iterator<typename std::conditional<std::is_const<T>{}, contiguous_iterator_tag, mutable_contiguous_iterator_tag>::type, T> {
    constexpr contiguous_iterator() noexcept = default;
    template<class U, class = std::enable_if_t<is_more_cv_qualified<Tenable_if<is_more_cv_qualified<T, U>{}>>>::type>
    constexpr contiguous_iterator(contiguous_iterator<U> other) noexcept : contiguous_iterator_base<std::remove_cv_t<T>>remove_cv<T>::type>(other) {}
    constexpr explicit contiguous_iterator(contiguous_iterator_base<std::remove_cv_t<T>>remove_cv<T>::type> other) noexcept : decltype(other)(other) {}
    constexpr explicit contiguous_iterator(T* p) noexcept { _p = const_cast<decltype(_p)>(p); }
    template<class U>
    constexpr contiguous_iterator<U> rebind() const noexcept { return contiguous_iterator<U>(_p); }
    constexpr T* operator->() noexcept { return  _p; }
    constexpr T& operator* () noexcept { return *_p; }
    constexpr T& operator[](std::ptrdiff_t d) noexcept { return _p[d]; }
    constexpr contiguous_iterator& operator++() noexcept { ++_p; return *this; }
    constexpr contiguous_iterator operator++(int) noexcept { auto r = *this; ++*this; return r; }
    constexpr contiguous_iterator& operator--() noexcept { --_p; return *this; }
    constexpr contiguous_iterator operator--(int) noexcept { auto r = *this; --*this; return r; }
    constexpr contiguous_iterator& operator+=(std::ptrdiff_t d) noexcept { _p += d; return *this; }
    constexpr contiguous_iterator& operator-=(std::ptrdiff_t d) noexcept { _p -= d; return *this; }
    constexpr contiguous_iterator operator+(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) += d; }
    constexpr contiguous_iterator operator-(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) -= d; }
protected:
    using contiguous_iterator_base<std::remove_cv_t<T>>remove_cv<T>::type>::_p;
};

// smoke test

int main() {
    contiguous_iterator_base<int>{};
    contiguous_iterator<int> a;
    contiguous_iterator<const int> b;
    b = a;
    a = b.rebind<int>();
    //a.rebind<char>(); error
}

Following the paradigms of SCARY iterators, there should only be a single iterator-type for contiguous iterators per value-type.
Here my code for that iterator, working with C++11+:

#include <type_traits>
#include <iterator>

template<class T, class U>
struct is_more_cv_qualified : std::integral_constant<bool, std::is_same<T, const volatile U>{}
    || std::is_same<T, const U>{} || std::is_same<T, volatile U>{}>;

struct contiguous_iterator_tag : std::random_access_iterator_tag {};
struct mutable_contiguous_iterator_tag : contiguous_iterator_tag, std::output_iterator_tag {};

template<class T>
struct contiguous_iterator_base {
    constexpr bool operator==(contiguous_iterator_base other) const noexcept { return _p == other.p; }
    constexpr bool operator!=(contiguous_iterator_base other) const noexcept { return _p != other.p; }
    constexpr bool operator<(contiguous_iterator_base other) const noexcept { return _p < other._p; }
    constexpr bool operator>(contiguous_iterator_base other) const noexcept { return _p > other._p; }
    constexpr bool operator<=(contiguous_iterator_base other) const noexcept { return _p <= other._p; }
    constexpr bool operator>=(contiguous_iterator_base other) const noexcept { return _p >= other._p; }
    constexpr std::ptrdiff_t operator-(contiguous_iterator_base other) const noexcept { return _p - other._p; }
protected:
    constexpr contiguous_iterator_base& operator=(const contiguous_iterator_base&) noexcept = default;
    T* _p = nullptr;
};

template<class T>
struct contiguous_iterator : contiguous_iterator_base<std::remove_cv_t<T>>
, std::iterator<typename std::conditional<std::is_const<T>{}, contiguous_iterator_tag, mutable_contiguous_iterator_tag>::type, T> {
    constexpr contiguous_iterator() noexcept = default;
    template<class U, class = std::enable_if_t<is_more_cv_qualified<T, U>{}>>
    constexpr contiguous_iterator(contiguous_iterator<U> other) noexcept : contiguous_iterator_base<std::remove_cv_t<T>>(other) {}
    constexpr explicit contiguous_iterator(contiguous_iterator_base<std::remove_cv_t<T>> other) noexcept : decltype(other)(other) {}
    constexpr explicit contiguous_iterator(T* p) noexcept { _p = const_cast<decltype(_p)>(p); }
    template<class U>
    constexpr contiguous_iterator<U> rebind() const noexcept { return contiguous_iterator<U>(_p); }
    constexpr T* operator->() noexcept { return  _p; }
    constexpr T& operator* () noexcept { return *_p; }
    constexpr T& operator[](std::ptrdiff_t d) noexcept { return _p[d]; }
    constexpr contiguous_iterator& operator++() noexcept { ++_p; return *this; }
    constexpr contiguous_iterator operator++(int) noexcept { auto r = *this; ++*this; return r; }
    constexpr contiguous_iterator& operator--() noexcept { --_p; return *this; }
    constexpr contiguous_iterator operator--(int) noexcept { auto r = *this; --*this; return r; }
    constexpr contiguous_iterator& operator+=(std::ptrdiff_t d) noexcept { _p += d; return *this; }
    constexpr contiguous_iterator& operator-=(std::ptrdiff_t d) noexcept { _p -= d; return *this; }
    constexpr contiguous_iterator operator+(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) += d; }
    constexpr contiguous_iterator operator-(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) -= d; }
protected:
    using contiguous_iterator_base<std::remove_cv_t<T>>::_p;
};

// smoke test

int main() {
    contiguous_iterator_base<int>{};
    contiguous_iterator<int> a;
    contiguous_iterator<const int> b;
    b = a;
    a = b.rebind<int>();
    //a.rebind<char>(); error
}

Following the paradigms of SCARY iterators, there should only be a single iterator-type for contiguous iterators per value-type.
Here my code for that iterator, working with C++11+:

#include <type_traits>
#include <iterator>

template<class T, class U>
struct is_more_cv_qualified : std::integral_constant<bool, std::is_same<T, const volatile U>{}
    || std::is_same<T, const U>{} || std::is_same<T, volatile U>{}>;

struct contiguous_iterator_tag : std::random_access_iterator_tag {};
struct mutable_contiguous_iterator_tag : contiguous_iterator_tag, std::output_iterator_tag {};

template<class T>
struct contiguous_iterator_base {
    constexpr bool operator==(contiguous_iterator_base other) const noexcept { return _p == other.p; }
    constexpr bool operator!=(contiguous_iterator_base other) const noexcept { return _p != other.p; }
    constexpr bool operator<(contiguous_iterator_base other) const noexcept { return _p < other._p; }
    constexpr bool operator>(contiguous_iterator_base other) const noexcept { return _p > other._p; }
    constexpr bool operator<=(contiguous_iterator_base other) const noexcept { return _p <= other._p; }
    constexpr bool operator>=(contiguous_iterator_base other) const noexcept { return _p >= other._p; }
    constexpr std::ptrdiff_t operator-(contiguous_iterator_base other) const noexcept { return _p - other._p; }
protected:
    constexpr contiguous_iterator_base& operator=(const contiguous_iterator_base&) noexcept = default;
    T* _p = nullptr;
};

template<class T>
struct contiguous_iterator : contiguous_iterator_base<std::remove_cv<T>::type>
, std::iterator<typename std::conditional<std::is_const<T>{}, contiguous_iterator_tag, mutable_contiguous_iterator_tag>::type, T> {
    constexpr contiguous_iterator() noexcept = default;
    template<class U, class = std::enable_if<is_more_cv_qualified<T, U>{}>::type>
    constexpr contiguous_iterator(contiguous_iterator<U> other) noexcept : contiguous_iterator_base<std::remove_cv<T>::type>(other) {}
    constexpr explicit contiguous_iterator(contiguous_iterator_base<std::remove_cv<T>::type> other) noexcept : decltype(other)(other) {}
    constexpr explicit contiguous_iterator(T* p) noexcept { _p = const_cast<decltype(_p)>(p); }
    template<class U>
    constexpr contiguous_iterator<U> rebind() const noexcept { return contiguous_iterator<U>(_p); }
    constexpr T* operator->() noexcept { return  _p; }
    constexpr T& operator* () noexcept { return *_p; }
    constexpr T& operator[](std::ptrdiff_t d) noexcept { return _p[d]; }
    constexpr contiguous_iterator& operator++() noexcept { ++_p; return *this; }
    constexpr contiguous_iterator operator++(int) noexcept { auto r = *this; ++*this; return r; }
    constexpr contiguous_iterator& operator--() noexcept { --_p; return *this; }
    constexpr contiguous_iterator operator--(int) noexcept { auto r = *this; --*this; return r; }
    constexpr contiguous_iterator& operator+=(std::ptrdiff_t d) noexcept { _p += d; return *this; }
    constexpr contiguous_iterator& operator-=(std::ptrdiff_t d) noexcept { _p -= d; return *this; }
    constexpr contiguous_iterator operator+(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) += d; }
    constexpr contiguous_iterator operator-(std::ptrdiff_t d) const noexcept { return contiguous_iterator(_p) -= d; }
protected:
    using contiguous_iterator_base<std::remove_cv<T>::type>::_p;
};

// smoke test

int main() {
    contiguous_iterator_base<int>{};
    contiguous_iterator<int> a;
    contiguous_iterator<const int> b;
    b = a;
    a = b.rebind<int>();
    //a.rebind<char>(); error
}
Source Link
Deduplicator
  • 19.3k
  • 1
  • 31
  • 65
Loading