aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAnna Gringauze <annagrin@microsoft.com>2018-05-22 18:07:49 -0700
committerGitHub <noreply@github.com>2018-05-22 18:07:49 -0700
commit51ae678d080c4b9b97419c1ca716b2c464d72741 (patch)
tree7e35cabcd9b0183cdd79768a1408d8ce5344207e /include
parent2be3b00faf46e56845029611a179ea1d3546b309 (diff)
downloadplatform_external_Microsoft-GSL-51ae678d080c4b9b97419c1ca716b2c464d72741.tar.gz
platform_external_Microsoft-GSL-51ae678d080c4b9b97419c1ca716b2c464d72741.tar.bz2
platform_external_Microsoft-GSL-51ae678d080c4b9b97419c1ca716b2c464d72741.zip
Add usage for check-and-unwrap of MS STL iterators (#687)
* Add usage for check-and-unwrap of MS STL iterators This is Billy ONeal's PR #682 with a typo fixed. See corresponding change here: https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_git/msvc/commit/ca77129308c775f422ecef0c01ad460f75c462ad That change officially exposes the STL's range checking machinery, available in MSVC++ "15.8"+ This change augments GSL span::iterator to call into that newly exposed machinery. _Verify_range(cit, cit) Requests that the iterator type check that the parameters form a valid [First, Last) range iterator pair. This replaces _DEBUG_RANGE and supporting machinery. The standard library provides a version for pointers under _IDL != 0; otherwise they are normally provided via hidden friend functions. Note that declaring some of these hidden friends for "wrapper" iterators like move_iterator and reverse_iterator triggers VSO#610735. cit._Verify_offset(difference_type _Off) For random-access iterators, performs any asserts that would be performed by i += _Off; except with possibly a better error message and without moving the iterator. cit._Unwrapped() Returns an "unchecked" or "unwrapped" iterator which has previously been validated. The iterator may have been validated by a call to _Verify_range or _Verify_offset (above), or by seeking a checked iterator to a "high water mark" point. it._Seek_to(cit) / it._Seek_to(return value from _Unwrapped()) Moves the position of the checked iterator it to the position of the unchecked iterator supplied. Generally not intended to perform range checks. * Fixed build break in VS2015 * fixed constexpr build break when using VS2015
Diffstat (limited to 'include')
-rw-r--r--include/gsl/span38
1 files changed, 38 insertions, 0 deletions
diff --git a/include/gsl/span b/include/gsl/span
index f5f1332..dd2d053 100644
--- a/include/gsl/span
+++ b/include/gsl/span
@@ -258,6 +258,44 @@ namespace details
return !(rhs > lhs);
}
+#ifdef _MSC_VER
+ // MSVC++ iterator debugging support; allows STL algorithms in 15.8+
+ // to unwrap span_iterator to a pointer type after a range check in STL
+ // algorithm calls
+ friend constexpr void _Verify_range(span_iterator lhs,
+ span_iterator rhs) noexcept
+ { // test that [lhs, rhs) forms a valid range inside an STL algorithm
+ Expects(lhs.span_ == rhs.span_ // range spans have to match
+ && lhs.index_ <= rhs.index_); // range must not be transposed
+ }
+
+ constexpr void _Verify_offset(const difference_type n) const noexcept
+ { // test that the iterator *this + n is a valid range in an STL
+ // algorithm call
+ Expects((index_ + n) >= 0 && (index_ + n) <= span_->size());
+ }
+
+ constexpr pointer _Unwrapped() const noexcept
+ { // after seeking *this to a high water mark, or using one of the
+ // _Verify_xxx functions above, unwrap this span_iterator to a raw
+ // pointer
+ return span_->data() + index_;
+ }
+
+ // Tell the STL that span_iterator should not be unwrapped if it can't
+ // validate in advance, even in release / optimized builds:
+#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
+ static constexpr const bool _Unwrap_when_unverified = false;
+#else
+ static constexpr bool _Unwrap_when_unverified = false;
+#endif
+ constexpr void _Seek_to(const pointer p) noexcept
+ { // adjust the position of *this to previously verified location p
+ // after _Unwrapped
+ index_ = p - span_->data();
+ }
+#endif
+
protected:
const Span* span_ = nullptr;
std::ptrdiff_t index_ = 0;