From 39902b6ec011c9dc980cb11c4596f04366195a0a Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Fri, 26 May 2017 15:41:12 -0700 Subject: [PATCH] span_iterator: converting constructor isn't a copy constructor (#511) Fixes #510. * Constrain the converting constructor to not participate in overload resolution when IsConst is true, so that it is never a copy constructor. * Use Default Member Initializers for span_iterator's data members so that the default constructor can be explicitly defaulted. * Declare all members of span_iterator GSL_NOEXCEPT: they only throw when contract violations throw. * Don't use & in operator-> since evil types may overload it. --- include/gsl/span | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index b344314..2063958 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -141,36 +141,34 @@ namespace details using reference = std::conditional_t&; using pointer = std::add_pointer_t; - constexpr span_iterator() GSL_NOEXCEPT : span_iterator(nullptr, 0) {} + span_iterator() = default; constexpr span_iterator(const Span* span, typename Span::index_type index) - : span_(span), index_(index) + : span_(span), index_(index) GSL_NOEXCEPT { Expects(span == nullptr || (index_ >= 0 && index <= span_->length())); } - friend class span_iterator; - constexpr span_iterator(const span_iterator& other) GSL_NOEXCEPT + friend span_iterator; + template* = nullptr> + constexpr span_iterator(const span_iterator& other) GSL_NOEXCEPT : span_iterator(other.span_, other.index_) { } - constexpr span_iterator& - operator=(const span_iterator&) GSL_NOEXCEPT = default; - - constexpr reference operator*() const + constexpr reference operator*() const GSL_NOEXCEPT { Expects(span_); return (*span_)[index_]; } - constexpr pointer operator->() const + constexpr pointer operator->() const GSL_NOEXCEPT { - Expects(span_); - return &((*span_)[index_]); + Expects(span_ && index_ >= 0 && index_ < span_->length()); + return span_->data() + index_; } - constexpr span_iterator& operator++() + constexpr span_iterator& operator++() GSL_NOEXCEPT { Expects(span_ && index_ >= 0 && index_ < span_->length()); ++index_; @@ -184,7 +182,7 @@ namespace details return ret; } - constexpr span_iterator& operator--() + constexpr span_iterator& operator--() GSL_NOEXCEPT { Expects(span_ && index_ > 0 && index_ <= span_->length()); --index_; @@ -204,7 +202,7 @@ namespace details return ret += n; } - constexpr span_iterator& operator+=(difference_type n) + constexpr span_iterator& operator+=(difference_type n) GSL_NOEXCEPT { Expects(span_ && (index_ + n) >= 0 && (index_ + n) <= span_->length()); index_ += n; @@ -219,7 +217,7 @@ namespace details constexpr span_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; } - constexpr difference_type operator-(const span_iterator& rhs) const + constexpr difference_type operator-(const span_iterator& rhs) const GSL_NOEXCEPT { Expects(span_ == rhs.span_); return index_ - rhs.index_; @@ -242,7 +240,8 @@ namespace details return !(lhs == rhs); } - constexpr friend bool operator<(const span_iterator& lhs, const span_iterator& rhs) + constexpr friend bool operator<(const span_iterator& lhs, + const span_iterator& rhs) GSL_NOEXCEPT { Expects(lhs.span_ == rhs.span_); return lhs.index_ < rhs.index_; @@ -266,15 +265,9 @@ namespace details return !(rhs > lhs); } - void swap(span_iterator& rhs) GSL_NOEXCEPT - { - std::swap(index_, rhs.index_); - std::swap(span_, rhs.span_); - } - protected: - const Span* span_; - std::ptrdiff_t index_; + const Span* span_ = nullptr; + std::ptrdiff_t index_ = 0; }; template