diff --git a/include/gsl/span b/include/gsl/span index 622c031..6dd1c1f 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -58,8 +58,6 @@ #endif // _MSC_VER -#define GSL_NOEXCEPT noexcept - namespace gsl { @@ -136,13 +134,13 @@ namespace details span_iterator() = default; - constexpr span_iterator(const Span* span, typename Span::index_type idx) GSL_NOEXCEPT + constexpr span_iterator(const Span* span, typename Span::index_type idx) noexcept : span_(span), index_(idx) {} friend span_iterator; template* = nullptr> - constexpr span_iterator(const span_iterator& other) GSL_NOEXCEPT + constexpr span_iterator(const span_iterator& other) noexcept : span_iterator(other.span_, other.index_) { } @@ -220,37 +218,37 @@ namespace details } constexpr friend bool operator==(span_iterator lhs, - span_iterator rhs) GSL_NOEXCEPT + span_iterator rhs) noexcept { return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_; } constexpr friend bool operator!=(span_iterator lhs, - span_iterator rhs) GSL_NOEXCEPT + span_iterator rhs) noexcept { return !(lhs == rhs); } constexpr friend bool operator<(span_iterator lhs, - span_iterator rhs) GSL_NOEXCEPT + span_iterator rhs) noexcept { return lhs.index_ < rhs.index_; } constexpr friend bool operator<=(span_iterator lhs, - span_iterator rhs) GSL_NOEXCEPT + span_iterator rhs) noexcept { return !(rhs < lhs); } constexpr friend bool operator>(span_iterator lhs, - span_iterator rhs) GSL_NOEXCEPT + span_iterator rhs) noexcept { return rhs < lhs; } constexpr friend bool operator>=(span_iterator lhs, - span_iterator rhs) GSL_NOEXCEPT + span_iterator rhs) noexcept { return !(rhs > lhs); } @@ -284,7 +282,7 @@ namespace details static_assert(Ext >= 0, "A fixed-size span must be >= 0 in size."); - constexpr extent_type() GSL_NOEXCEPT {} + constexpr extent_type() noexcept {} template constexpr extent_type(extent_type ext) @@ -296,7 +294,7 @@ namespace details constexpr extent_type(index_type size) { Expects(size == Ext); } - constexpr index_type size() const GSL_NOEXCEPT { return Ext; } + constexpr index_type size() const noexcept { return Ext; } }; template <> @@ -312,7 +310,7 @@ namespace details explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); } - constexpr index_type size() const GSL_NOEXCEPT { return size_; } + constexpr index_type size() const noexcept { return size_; } private: index_type size_; @@ -355,7 +353,7 @@ public: // "Dependent" is needed to make "std::enable_if_t" SFINAE, // since "std::enable_if_t" is ill-formed when Extent is greater than 0. class = std::enable_if_t<(Dependent || Extent <= 0)>> - constexpr span() GSL_NOEXCEPT : storage_(nullptr, details::extent_type<0>()) + constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) { } @@ -367,19 +365,19 @@ public: } template - constexpr span(element_type (&arr)[N]) GSL_NOEXCEPT - : storage_(&arr[0], details::extent_type()) + constexpr span(element_type (&arr)[N]) noexcept + : storage_(KnownNotNull{&arr[0]}, details::extent_type()) { } template > - constexpr span(std::array& arr) GSL_NOEXCEPT + constexpr span(std::array& arr) noexcept : storage_(&arr[0], details::extent_type()) { } template - constexpr span(const std::array, N>& arr) GSL_NOEXCEPT + constexpr span(const std::array, N>& arr) noexcept : storage_(&arr[0], details::extent_type()) { } @@ -406,7 +404,7 @@ public: { } - constexpr span(const span& other) GSL_NOEXCEPT = default; + constexpr span(const span& other) noexcept = default; template < class OtherElementType, std::ptrdiff_t OtherExtent, @@ -418,8 +416,8 @@ public: { } - ~span() GSL_NOEXCEPT = default; - constexpr span& operator=(const span& other) GSL_NOEXCEPT = default; + ~span() noexcept = default; + constexpr span& operator=(const span& other) noexcept = default; // [span.sub], span subviews template @@ -464,12 +462,12 @@ public: // [span.obs], span observers - constexpr index_type size() const GSL_NOEXCEPT { return storage_.size(); } - constexpr index_type size_bytes() const GSL_NOEXCEPT + constexpr index_type size() const noexcept { return storage_.size(); } + constexpr index_type size_bytes() const noexcept { return size() * narrow_cast(sizeof(element_type)); } - constexpr bool empty() const GSL_NOEXCEPT { return size() == 0; } + constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access constexpr reference operator[](index_type idx) const @@ -480,22 +478,29 @@ public: constexpr reference at(index_type idx) const { return this->operator[](idx); } constexpr reference operator()(index_type idx) const { return this->operator[](idx); } - constexpr pointer data() const GSL_NOEXCEPT { return storage_.data(); } + constexpr pointer data() const noexcept { return storage_.data(); } // [span.iter], span iterator support - constexpr iterator begin() const GSL_NOEXCEPT { return {this, 0}; } - constexpr iterator end() const GSL_NOEXCEPT { return {this, size()}; } + constexpr iterator begin() const noexcept { return {this, 0}; } + constexpr iterator end() const noexcept { return {this, size()}; } - constexpr const_iterator cbegin() const GSL_NOEXCEPT { return {this, 0}; } - constexpr const_iterator cend() const GSL_NOEXCEPT { return {this, size()}; } + constexpr const_iterator cbegin() const noexcept { return {this, 0}; } + constexpr const_iterator cend() const noexcept { return {this, size()}; } - constexpr reverse_iterator rbegin() const GSL_NOEXCEPT { return reverse_iterator{end()}; } - constexpr reverse_iterator rend() const GSL_NOEXCEPT { return reverse_iterator{begin()}; } + constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } + constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } - constexpr const_reverse_iterator crbegin() const GSL_NOEXCEPT { return const_reverse_iterator{cend()}; } - constexpr const_reverse_iterator crend() const GSL_NOEXCEPT { return const_reverse_iterator{cbegin()}; } + constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; } + constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; } private: + + // Needed to remove unnecessary null check in subspans + struct KnownNotNull + { + pointer p; + }; + // this implementation detail class lets us take advantage of the // empty base class optimization to pay for only storage of a single // pointer in the case of fixed-size spans @@ -503,16 +508,23 @@ private: class storage_type : public ExtentType { public: - - // checked parameter is needed to remove unnecessary null check in subspans + // KnownNotNull parameter is needed to remove unnecessary null check + // in subspans and constructors from arrays template - constexpr storage_type(pointer data, OtherExtentType ext, bool checked = false) : ExtentType(ext), data_(data) + constexpr storage_type(KnownNotNull data, OtherExtentType ext) : ExtentType(ext), data_(data.p) { - Expects(((checked || !data) && ExtentType::size() == 0) || - ((checked || data) && ExtentType::size() >= 0)); + Expects(ExtentType::size() >= 0); } - constexpr pointer data() const GSL_NOEXCEPT { return data_; } + + template + constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) + { + Expects(ExtentType::size() >= 0); + Expects(data || ExtentType::size() == 0); + } + + constexpr pointer data() const noexcept { return data_; } private: pointer data_; @@ -520,8 +532,9 @@ 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) {} + // The rest is needed to remove unnecessary null check + // in subspans and constructors from arrays + constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {} template class subspan_selector {}; @@ -542,11 +555,11 @@ private: Expects(offset >= 0 && size() - offset >= 0); if (count == dynamic_extent) { - return { data() + offset, size() - offset, true }; + return { KnownNotNull{ data() + offset }, size() - offset }; } Expects(count >= 0 && size() - offset >= count); - return { data() + offset, count, true }; + return { KnownNotNull{ data() + offset }, count }; } }; @@ -625,7 +638,7 @@ namespace details // [span.objectrep], views of object representation template span::value> -as_bytes(span s) GSL_NOEXCEPT +as_bytes(span s) noexcept { return {reinterpret_cast(s.data()), s.size_bytes()}; } @@ -633,7 +646,7 @@ as_bytes(span s) GSL_NOEXCEPT template ::value>> span::value> -as_writeable_bytes(span s) GSL_NOEXCEPT +as_writeable_bytes(span s) noexcept { return {reinterpret_cast(s.data()), s.size_bytes()}; } @@ -654,7 +667,7 @@ constexpr span make_span(ElementType* firstElem, ElementType* lastE } template -constexpr span make_span(ElementType (&arr)[N]) GSL_NOEXCEPT +constexpr span make_span(ElementType (&arr)[N]) noexcept { return span(arr); } @@ -693,8 +706,6 @@ constexpr ElementType& at(span s, index i) } // namespace gsl -#undef GSL_NOEXCEPT - #ifdef _MSC_VER #if _MSC_VER < 1910 #undef constexpr diff --git a/include/gsl/string_span b/include/gsl/string_span index e4b186f..0bb98d2 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -417,9 +417,8 @@ public: constexpr string_span_type as_string_span() const GSL_NOEXCEPT { auto sz = span_.size(); - return span_.first(sz <= 0 ? 0 : sz - 1); + return { span_.data(), sz > 1 ? sz - 1 : 0 }; } - constexpr string_span_type ensure_z() const GSL_NOEXCEPT { return gsl::ensure_z(span_); } constexpr const_zstring_type assume_z() const GSL_NOEXCEPT { return span_.data(); }