Update
June 4th, 2020 – GSL version 3.1.0 has been released. Please see the latest release page for information regarding GSL 3.1.0. For all future updates, please see refer to the release page on GitHub.
GSL 3.0.0 Release
Version 3.0.0 of Microsoft’s implementation of the C++ Core Guidelines Support Library (GSL) is now available for you to download on the releases page. Microsoft’s implementation of gsl::span
has played a pivotal role in the standardization of span for C++20. However, the standard does not provide any runtime checking guarantees for memory bounds safety. The bounds safety provided by gsl::span
has been very successful in preventing security issues in Microsoft products. This release maintains the safety guarantees that we have always offered but modernizes our implementation to align with C++20 span.
What changed in this release?
- New implementations of
gsl::span
andgsl::span_iterator
that align to the C++ 20 standard. - Changes to contract violation behavior.
- Additional CMake support.
- Deprecation of
gsl::multi_span
andgsl::strided_span
.
When should I use gsl::span instead of std::span?
By default, use std::span
 which is shipping in VS2019 16.6 (with additional interface changes in 16.7, see release notes) if you have enabled C++20 mode and do not need runtime bounds checking guarantees. Use gsl::span
 if you need support for a version of C++ lower than C++20 (gsl::span
 supports C++14 and higher) or runtime bounds checking guarantees (all operations performed on gsl::span
 and its iterators have explicit bounds safety checks.) Â
gsl::span
With the standardization of span nearing completion, we decided it was time to align our implementation with the design changes in the standard. The new implementation provides full bounds checking, guaranteeing bounds safety if the underlying data is valid.
General changes
gsl::span
was rewritten to have its interface align to std::span
. The biggest change is that span’s Extent is now unsigned. It is now implemented as std::size_t
whereas previously it was std::ptrdiff_t.
By extension, dynamic_extent
is now defined as static_cast<std::size_t>(-1)
instead of just -1
.
- The field
span::index_type
was removed, superseded byspan::size_type
. - Addition of Class Template Argument Deduction (CTAD) support.
Interface alignment
These are the changes required to align gsl::span
to the interface of std::span
.
Removed functions
span::operator()
span::at
span::cbegin
span::cend
span::crbegin
span::crend
Added functions
span::front
span::back
Renamed functions
span::as_writeable_bytes
was renamed tospan::as_writable_bytes
gsl::span_iterator
General changes
Our implementation of span_iterator
has been completely rewritten to be more range-like. Previously, the implementation consisted of a span pointer and an offset. The new implementation is a set of three pointers: begin, end, and current.
Benefits of our new implementation
The new implementation can perform all of the bounds checks by itself, instead of calling into the span. By relying on pointers to the underlying data, rather than a pointer to the span, the new span_iterator
can outlive the underlying span.
The new <gsl/span_ext> header
The <gsl/span_ext> header was created to support our customers who rely on portions of the old span implementation that no longer exist in the standard definition of span.
Elements moved from <gsl/span> and inserted into <gsl/span_ext>
- span comparison operators
gsl::make_span
- span specialization of
gsl::at
gsl::begin
gsl::rbegin
gsl::crbegin
gsl::end
gsl::rend
gsl::crend
Contract violations
Contract violations are no longer configurable. Contract violations always result in termination, rather than providing a compile-time option to throw or disregard the contract violation. This is subject to change in the future. Some concerns over this decision have been raised and the conversation continues here: CppCoreGuidelines#1561. As a side note, the removal of the throwing behavior required the migration of our test infrastructure from Catch2 to Google Test, whose support of death tests easily enabled testing of contract violation behavior.
CMake improvements
This release now supports find_package
. Once installed, use find_package(Microsoft.GSL CONFIG)
to easily consume the GSL.
Deprecation of multi_span and strided_span
To more closely align Microsoft’s GSL to the C++ Core Guidelines, we decided to deprecate our implementation of gsl::multi_span
and gsl::strided_span
. For the time being, we will continue to provide these headers, but they will not be actively worked on or maintained unless the C++ Core Guidelines identifies a need for them.
Improvement changes causing potential build breaks and mitigationsÂ
Change: The change from signed std::ptrdiff_t
to unsigned std::size_t
in gsl::span
may introduce signed/unsigned mismatches.
Mitigation: Use static_cast
or gsl::narrow_cast
to resolve mismatches.
Change: gsl::multi_span
and gsl::strided_span
have been deprecated.
Mitigation: Pass multi-dimensional arrays as constant references instead of gsl::multi_span
.
Change: Code that makes use of moved span helper functions will generate compiler errors. Examples of these functions include span comparison operators, gsl::make_span
, etc.
Mitigation: Include <gsl/span_ext> instead of <gsl/span> in files where you use these functions.
Change: Throwing contract violation behavior is removed.
Mitigation: Use a terminate handler to log relevant information before termination executes for debugging. Relying on throwing behavior does not guarantee safety.
Upcoming changes
The paper P1976R2 that came out of the WG21 Prague meeting has yet to be implemented in GSL. A minor release will be issued when this is added to GSL.
Feedback
We look forward to hearing your feedback. If you would like to reach us, please use the comments below or email visualcpp@microsoft.com. Visit our page on GitHub if you would like to file issues or contribute to the project.
Update History
4/23/2020 – Released GSL version 3.0.1
6/4/2020 – Released GSL version 3.1.0
“The biggest change is that span’s Extent is now unsigned. ”
Oh my goodness – bliss! Them being signed caused so many obnoxious cases throughout our codebase where we had constantly had to wrap `gsl::narrow_cast<size_t>(someSpan.size())` because every other standard container and corresponding algorithm/loop expected unsigned values (negative values never made sense for a span anyway). Now transitioning from/to `std::span` will be painless.
Dwayne, thank you for your feedback. We are so glad to hear that you can now seamlessly transition from/to the `gsl::span` type.