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.
This commit is contained in:
Casey Carter 2017-05-26 15:41:12 -07:00 committed by Neil MacIntosh
parent 1f82596e1d
commit 39902b6ec0

View File

@ -141,36 +141,34 @@ namespace details
using reference = std::conditional_t<IsConst, const element_type_, element_type_>&; using reference = std::conditional_t<IsConst, const element_type_, element_type_>&;
using pointer = std::add_pointer_t<reference>; using pointer = std::add_pointer_t<reference>;
constexpr span_iterator() GSL_NOEXCEPT : span_iterator(nullptr, 0) {} span_iterator() = default;
constexpr span_iterator(const Span* span, typename Span::index_type index) 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())); Expects(span == nullptr || (index_ >= 0 && index <= span_->length()));
} }
friend class span_iterator<Span, true>; friend span_iterator<Span, true>;
constexpr span_iterator(const span_iterator<Span, false>& other) GSL_NOEXCEPT template<bool B, std::enable_if_t<!B && IsConst>* = nullptr>
constexpr span_iterator(const span_iterator<Span, B>& other) GSL_NOEXCEPT
: span_iterator(other.span_, other.index_) : span_iterator(other.span_, other.index_)
{ {
} }
constexpr span_iterator<Span, IsConst>& constexpr reference operator*() const GSL_NOEXCEPT
operator=(const span_iterator<Span, IsConst>&) GSL_NOEXCEPT = default;
constexpr reference operator*() const
{ {
Expects(span_); Expects(span_);
return (*span_)[index_]; return (*span_)[index_];
} }
constexpr pointer operator->() const constexpr pointer operator->() const GSL_NOEXCEPT
{ {
Expects(span_); Expects(span_ && index_ >= 0 && index_ < span_->length());
return &((*span_)[index_]); return span_->data() + index_;
} }
constexpr span_iterator& operator++() constexpr span_iterator& operator++() GSL_NOEXCEPT
{ {
Expects(span_ && index_ >= 0 && index_ < span_->length()); Expects(span_ && index_ >= 0 && index_ < span_->length());
++index_; ++index_;
@ -184,7 +182,7 @@ namespace details
return ret; return ret;
} }
constexpr span_iterator& operator--() constexpr span_iterator& operator--() GSL_NOEXCEPT
{ {
Expects(span_ && index_ > 0 && index_ <= span_->length()); Expects(span_ && index_ > 0 && index_ <= span_->length());
--index_; --index_;
@ -204,7 +202,7 @@ namespace details
return ret += n; 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()); Expects(span_ && (index_ + n) >= 0 && (index_ + n) <= span_->length());
index_ += n; index_ += n;
@ -219,7 +217,7 @@ namespace details
constexpr span_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; } 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_); Expects(span_ == rhs.span_);
return index_ - rhs.index_; return index_ - rhs.index_;
@ -242,7 +240,8 @@ namespace details
return !(lhs == rhs); 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_); Expects(lhs.span_ == rhs.span_);
return lhs.index_ < rhs.index_; return lhs.index_ < rhs.index_;
@ -266,15 +265,9 @@ namespace details
return !(rhs > lhs); return !(rhs > lhs);
} }
void swap(span_iterator& rhs) GSL_NOEXCEPT
{
std::swap(index_, rhs.index_);
std::swap(span_, rhs.span_);
}
protected: protected:
const Span* span_; const Span* span_ = nullptr;
std::ptrdiff_t index_; std::ptrdiff_t index_ = 0;
}; };
template <class Span, bool IsConst> template <class Span, bool IsConst>