diff --git a/include/gsl/span b/include/gsl/span index b828770..7ea1a6c 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -443,15 +443,16 @@ public: template constexpr span last() const { - Expects(Count >= 0 && Count <= size()); + Expects(Count >= 0 && size() - Count >= 0); return {data() + (size() - Count), Count}; } template constexpr span subspan() const { - Expects((Offset == 0 || (Offset > 0 && Offset <= size())) && + Expects((Offset >= 0 && size() - Offset >= 0) && (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size()))); + return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; } @@ -463,18 +464,16 @@ public: constexpr span last(index_type count) const { - Expects(count >= 0 && count <= size()); - return {data() + (size() - count), count}; + return make_subspan(size() - count, dynamic_extent, subspan_selector{}); } constexpr span subspan(index_type offset, index_type count = dynamic_extent) const { - Expects((offset == 0 || (offset > 0 && offset <= size())) && - (count == dynamic_extent || (count >= 0 && offset + count <= size()))); - return {data() + offset, count == dynamic_extent ? size() - offset : count}; + return make_subspan(offset, count, subspan_selector{}); } + // [span.obs], span observers constexpr index_type length() const GSL_NOEXCEPT { return size(); } constexpr index_type size() const GSL_NOEXCEPT { return storage_.size(); } @@ -517,10 +516,13 @@ private: class storage_type : public ExtentType { public: + + // checked parameter is needed to remove unnecessary null check in subspans template - constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) + constexpr storage_type(pointer data, OtherExtentType ext, bool checked = false) : ExtentType(ext), data_(data) { - Expects((!data && ExtentType::size() == 0) || (data && ExtentType::size() >= 0)); + Expects(((checked || !data) && ExtentType::size() == 0) || + ((checked || data) && ExtentType::size() >= 0)); } constexpr pointer data() const GSL_NOEXCEPT { return data_; } @@ -530,8 +532,38 @@ private: }; storage_type> storage_; + + // The rest is needed to remove unnecessary null check in subspans + constexpr span(pointer ptr, index_type count, bool checked) : storage_(ptr, count, checked) {} + + template + class subspan_selector {}; + + template + span make_subspan(index_type offset, + index_type count, + subspan_selector) const GSL_NOEXCEPT + { + span tmp(*this); + return tmp.subspan(offset, count); + } + + span make_subspan(index_type offset, + index_type count, + subspan_selector) const GSL_NOEXCEPT + { + Expects(offset >= 0 && size() - offset >= 0); + if (count == dynamic_extent) + { + return { data() + offset, size() - offset, true }; + } + + Expects(count >= 0 && size() - offset >= count); + return { data() + offset, count, true }; + } }; + // [span.comparison], span comparison operators template inline constexpr bool operator==(const span& l,