diff options
author | Neil MacIntosh <neilmac@microsoft.com> | 2016-08-08 12:06:47 -0700 |
---|---|---|
committer | Neil MacIntosh <neilmac@microsoft.com> | 2016-08-08 12:06:47 -0700 |
commit | 82389aa630a28ec520b115b9bcb770a5ae495860 (patch) | |
tree | 87a232f46e2196dc8057a9942e1feb547325a4d5 | |
parent | 9ab3a2ac3960145c309e3935851ee5e4337c93ee (diff) | |
download | platform_external_Microsoft-GSL-82389aa630a28ec520b115b9bcb770a5ae495860.tar.gz platform_external_Microsoft-GSL-82389aa630a28ec520b115b9bcb770a5ae495860.tar.bz2 platform_external_Microsoft-GSL-82389aa630a28ec520b115b9bcb770a5ae495860.zip |
Fixed up iterator implementation to allow conversion from iterator to
const_iterator.
-rw-r--r-- | include/span.h | 220 | ||||
-rw-r--r-- | tests/span_tests.cpp | 98 |
2 files changed, 121 insertions, 197 deletions
diff --git a/include/span.h b/include/span.h index a5d2823..ca35d8c 100644 --- a/include/span.h +++ b/include/span.h @@ -166,159 +166,29 @@ namespace details { }; - template <class Span> - class const_span_iterator - { - public: - using iterator_category = std::random_access_iterator_tag; - using value_type = typename Span::element_type; - using difference_type = std::ptrdiff_t; - - using const_pointer = std::add_const_t<value_type*>; - using pointer = const_pointer; - - using const_reference = std::add_const_t<value_type&>; - using reference = const_reference; - - constexpr const_span_iterator() : const_span_iterator(nullptr, 0) {} - constexpr const_span_iterator(const Span* span, typename Span::index_type index) - : span_(span), index_(index) - { - Expects(span == nullptr || (index_ >= 0 && index <= span_->length())); - } - - constexpr reference operator*() const - { - Expects(span_); - return (*span_)[index_]; - } - - constexpr pointer operator->() const - { - Expects(span_); - return &((*span_)[index_]); - } - - constexpr const_span_iterator& operator++() noexcept - { - Expects(span_ && index_ >= 0 && index_ < span_->length()); - ++index_; - return *this; - } - - constexpr const_span_iterator operator++(int) noexcept - { - auto ret = *this; - ++(*this); - return ret; - } - - constexpr const_span_iterator& operator--() noexcept - { - Expects(span_ && index_ > 0 && index_ <= span_->length()); - --index_; - return *this; - } - - constexpr const_span_iterator operator--(int) noexcept - { - auto ret = *this; - --(*this); - return ret; - } - - constexpr const_span_iterator operator+(difference_type n) const noexcept - { - auto ret = *this; - return ret += n; - } - - constexpr const_span_iterator& operator+=(difference_type n) noexcept - { - Expects(span_ && (index_ + n) >= 0 && (index_ + n) <= span_->length()); - index_ += n; - return *this; - } - - constexpr const_span_iterator operator-(difference_type n) const noexcept - { - auto ret = *this; - return ret -= n; - } - - constexpr const_span_iterator& operator-=(difference_type n) noexcept - { - return *this += -n; - } - - constexpr difference_type operator-(const const_span_iterator& rhs) const noexcept - { - Expects(span_ == rhs.span_); - return index_ - rhs.index_; - } - - constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); } - - constexpr bool operator==(const const_span_iterator& rhs) const noexcept - { - return span_ == rhs.span_ && index_ == rhs.index_; - } - - constexpr bool operator!=(const const_span_iterator& rhs) const noexcept - { - return !(*this == rhs); - } - - constexpr bool operator<(const const_span_iterator& rhs) const noexcept - { - Expects(span_ == rhs.span_); - return index_ < rhs.index_; - } - - constexpr bool operator<=(const const_span_iterator& rhs) const noexcept - { - return !(rhs < *this); - } - - constexpr bool operator>(const const_span_iterator& rhs) const noexcept - { - return rhs < *this; - } - - constexpr bool operator>=(const const_span_iterator& rhs) const noexcept - { - return !(rhs > *this); - } - - void swap(const_span_iterator& rhs) noexcept - { - std::swap(index_, rhs.index_); - std::swap(span_, rhs.span_); - } - - private: - const Span* span_; - std::ptrdiff_t index_; - }; - - template <class Span> + template <class Span, bool IsConst> class span_iterator { public: using iterator_category = std::random_access_iterator_tag; - using value_type = typename Span::element_type; - using difference_type = std::ptrdiff_t; + using value_type = std::conditional_t<IsConst, std::add_const_t<typename Span::element_type>, typename Span::element_type>; + using difference_type = typename Span::index_type; - using pointer = value_type*; - using reference = value_type&; + using pointer = std::add_pointer_t<value_type>; + using reference = std::add_lvalue_reference_t<value_type>; - constexpr span_iterator() : span_iterator(nullptr, 0) {} + constexpr span_iterator() : span_iterator(nullptr, 0) noexcept {} + constexpr span_iterator(const Span* span, typename Span::index_type index) : span_(span), index_(index) { Expects(span == nullptr || (index_ >= 0 && index <= span_->length())); } + friend class span_iterator<Span, true>; + constexpr span_iterator(const span_iterator<Span, false>& other) noexcept + : span_iterator(other.span_, other.index_) {} + constexpr reference operator*() const { Expects(span_); @@ -378,7 +248,10 @@ namespace details return ret -= n; } - constexpr span_iterator& operator-=(difference_type n) noexcept { return *this += -n; } + constexpr span_iterator& operator-=(difference_type n) noexcept + { + return *this += -n; + } constexpr difference_type operator-(const span_iterator& rhs) const noexcept { @@ -388,32 +261,35 @@ namespace details constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); } - constexpr bool operator==(const span_iterator& rhs) const noexcept + constexpr friend bool operator==(const span_iterator& lhs, const span_iterator& rhs) noexcept { - return span_ == rhs.span_ && index_ == rhs.index_; + return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_; } - constexpr bool operator!=(const span_iterator& rhs) const noexcept + constexpr friend bool operator!=(const span_iterator& lhs, const span_iterator& rhs) noexcept { - return !(*this == rhs); + return !(lhs == rhs); } - constexpr bool operator<(const span_iterator& rhs) const noexcept + constexpr friend bool operator<(const span_iterator& lhs, const span_iterator& rhs) noexcept { - Expects(span_ == rhs.span_); - return index_ < rhs.index_; + Expects(lhs.span_ == rhs.span_); + return lhs.index_ < rhs.index_; } - constexpr bool operator<=(const span_iterator& rhs) const noexcept + constexpr friend bool operator<=(const span_iterator& lhs, const span_iterator& rhs) noexcept { - return !(rhs < *this); + return !(rhs < lhs); } - constexpr bool operator>(const span_iterator& rhs) const noexcept { return rhs < *this; } + constexpr friend bool operator>(const span_iterator& lhs, const span_iterator& rhs) noexcept + { + return rhs < lhs; + } - constexpr bool operator>=(const span_iterator& rhs) const noexcept + constexpr friend bool operator>=(const span_iterator& lhs, const span_iterator& rhs) noexcept { - return !(rhs > *this); + return !(rhs > lhs); } void swap(span_iterator& rhs) noexcept @@ -422,37 +298,23 @@ namespace details std::swap(span_, rhs.span_); } - private: + protected: const Span* span_; std::ptrdiff_t index_; }; - template <typename Span> - constexpr const_span_iterator<Span> - operator+(typename const_span_iterator<Span>::difference_type n, - const const_span_iterator<Span>& rhs) noexcept - { - return rhs + n; - } - - template <typename Span> - constexpr const_span_iterator<Span> - operator-(typename const_span_iterator<Span>::difference_type n, - const const_span_iterator<Span>& rhs) noexcept - { - return rhs - n; - } - - template <typename Span> - constexpr span_iterator<Span> operator+(typename span_iterator<Span>::difference_type n, - const span_iterator<Span>& rhs) noexcept + template <class Span, bool IsConst> + constexpr span_iterator<Span, IsConst> + operator+(typename span_iterator<Span, IsConst>::difference_type n, + const span_iterator<Span, IsConst>& rhs) noexcept { return rhs + n; } - template <typename Span> - constexpr span_iterator<Span> operator-(typename span_iterator<Span>::difference_type n, - const span_iterator<Span>& rhs) noexcept + template <class Span, bool IsConst> + constexpr span_iterator<Span, IsConst> + operator-(typename span_iterator<Span, IsConst>::difference_type n, + const span_iterator<Span, IsConst>& rhs) noexcept { return rhs - n; } @@ -511,8 +373,8 @@ public: using pointer = element_type*; using reference = element_type&; - using iterator = details::span_iterator<span<ElementType, Extent>>; - using const_iterator = details::const_span_iterator<span<ElementType, Extent>>; + using iterator = details::span_iterator<span<ElementType, Extent>, false>; + using const_iterator = details::span_iterator<span<ElementType, Extent>, true>; using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 8c9829d..4058463 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -787,20 +787,90 @@ SUITE(span_tests) } } - TEST(iterator) + TEST(iterator_default_init) { span<int>::iterator it1; span<int>::iterator it2; CHECK(it1 == it2); } - TEST(const_iterator) + TEST(const_iterator_default_init) { span<int>::const_iterator it1; span<int>::const_iterator it2; CHECK(it1 == it2); } + TEST(iterator_conversions) + { + span<int>::iterator badIt; + span<int>::const_iterator badConstIt; + CHECK(badIt == badConstIt); + + int a[] = { 1, 2, 3, 4 }; + span<int> s = a; + + auto it = s.begin(); + auto cit = s.cbegin(); + + CHECK(it == cit); + CHECK(cit == it); + + span<int>::const_iterator cit2 = it; + CHECK(cit2 == cit); + + span<int>::const_iterator cit3 = it + 4; + CHECK(cit3 == s.cend()); + } + + TEST(iterator_comparisons) + { + int a[] = { 1, 2, 3, 4 }; + { + span<int> s = a; + span<int>::iterator it = s.begin(); + auto it2 = it + 1; + span<int>::const_iterator cit = s.cbegin(); + auto cit2 = s.cbegin(); + + CHECK(it == cit); + CHECK(cit == it); + CHECK(it == it); + CHECK(cit == cit); + CHECK(cit == s.begin()); + CHECK(s.begin() == cit); + CHECK(s.cbegin() == cit); + CHECK(it == s.begin()); + CHECK(s.begin() == it); + + CHECK(it != it2); + CHECK(it2 != it); + CHECK(it != s.end()); + CHECK(it2 != s.end()); + CHECK(s.end() != it); + CHECK(it2 != cit); + CHECK(cit != it2); + + CHECK(it < it2); + CHECK(it <= it2); + CHECK(it2 <= s.end()); + CHECK(it < s.end()); + CHECK(it <= cit); + CHECK(cit <= it); + CHECK(cit < it2); + CHECK(cit <= it2); + CHECK(cit < s.end()); + CHECK(cit <= s.end()); + + CHECK(it2 > it); + CHECK(it2 >= it); + CHECK(s.end() > it2); + CHECK(s.end() >= it2); + CHECK(it2 > cit); + CHECK(it2 >= cit); + } + } + TEST(begin_end) { { @@ -867,25 +937,21 @@ SUITE(span_tests) ++it; CHECK(it - first == 1); CHECK(*it == 2); - *it = 22; - CHECK(*it == 22); CHECK(beyond - it == 3); + int last = 0; it = first; CHECK(it == first); while (it != s.cend()) { - *it = 5; + CHECK(*it == last + 1); + + last = *it; ++it; } CHECK(it == beyond); CHECK(it - beyond == 0); - - for (auto& n : s) - { - CHECK(n == 5); - } } } @@ -955,25 +1021,21 @@ SUITE(span_tests) ++it; CHECK(it - first == 1); CHECK(*it == 3); - *it = 22; - CHECK(*it == 22); CHECK(beyond - it == 3); it = first; CHECK(it == first); + int last = 5; while (it != s.crend()) { - *it = 5; + CHECK(*it == last - 1); + last = *it; + ++it; } CHECK(it == beyond); CHECK(it - beyond == 0); - - for (auto& n : s) - { - CHECK(n == 5); - } } } |