aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2025-10-25 17:50:55 +0200
committerStefan Boberg <[email protected]>2025-10-25 17:50:55 +0200
commit07b37b2cb487fb0cd3587a67c83121777b672dc2 (patch)
tree7fc6d0d4dfce46eb581ce55d3fdb2efe15284382
parentsuppress MSVC 4668 (diff)
downloadzen-07b37b2cb487fb0cd3587a67c83121777b672dc2.tar.xz
zen-07b37b2cb487fb0cd3587a67c83121777b672dc2.zip
in-tree: gsl-lite
-rw-r--r--src/zencore/xmake.lua2
-rw-r--r--src/zenhttp/xmake.lua2
-rw-r--r--src/zennet/xmake.lua4
-rw-r--r--thirdparty/gsl-lite/.editorconfig3
-rw-r--r--thirdparty/gsl-lite/.gitattributes2
-rw-r--r--thirdparty/gsl-lite/.gitignore3
-rw-r--r--thirdparty/gsl-lite/CHANGES.txt727
-rw-r--r--thirdparty/gsl-lite/LICENSE24
-rw-r--r--thirdparty/gsl-lite/README.md338
-rw-r--r--thirdparty/gsl-lite/_config.yml6
-rw-r--r--thirdparty/gsl-lite/_includes/footer.html0
-rw-r--r--thirdparty/gsl-lite/_includes/nav-items.html4
-rw-r--r--thirdparty/gsl-lite/_layouts/home.html64
-rw-r--r--thirdparty/gsl-lite/_layouts/page.html10
-rw-r--r--thirdparty/gsl-lite/_sass/minima/custom-variables.scss7
-rw-r--r--thirdparty/gsl-lite/appveyor.yml51
-rw-r--r--thirdparty/gsl-lite/azure-pipelines.yml205
-rw-r--r--thirdparty/gsl-lite/cmake/CommonPresets.json245
-rw-r--r--thirdparty/gsl-lite/cmake/InstallBasicPackageFiles.cmake684
-rw-r--r--thirdparty/gsl-lite/doc/Reference.md1389
-rw-r--r--thirdparty/gsl-lite/example/01-basic.cpp34
-rw-r--r--thirdparty/gsl-lite/example/02-span.cpp65
-rw-r--r--thirdparty/gsl-lite/example/with-CPM/README.md30
-rw-r--r--thirdparty/gsl-lite/example/with-CPM/cmake/CPM.cmake1291
-rw-r--r--thirdparty/gsl-lite/example/with-CPM/main.cpp22
-rw-r--r--thirdparty/gsl-lite/example/with-Vcpkg/README.md31
-rw-r--r--thirdparty/gsl-lite/example/with-Vcpkg/main.cpp22
-rw-r--r--thirdparty/gsl-lite/example/with-Vcpkg/vcpkg.json6
-rw-r--r--thirdparty/gsl-lite/include/gsl-lite/gsl-lite.hpp6014
-rw-r--r--thirdparty/gsl-lite/include/gsl/gsl-lite.hpp43
-rw-r--r--thirdparty/gsl-lite/src/gsl-lite.natvis26
-rw-r--r--thirdparty/gsl-lite/test/MakeTestTarget.cmake331
-rw-r--r--thirdparty/gsl-lite/test/assert.t.cpp229
-rw-r--r--thirdparty/gsl-lite/test/at.t.cpp163
-rw-r--r--thirdparty/gsl-lite/test/byte.t.cpp216
-rw-r--r--thirdparty/gsl-lite/test/core_check.t.cpp85
-rw-r--r--thirdparty/gsl-lite/test/core_check_lite.t.cpp74
-rw-r--r--thirdparty/gsl-lite/test/cuda/cuda.t.cu176
-rw-r--r--thirdparty/gsl-lite/test/emulation.t.cpp121
-rw-r--r--thirdparty/gsl-lite/test/gsl-lite.t.cpp298
-rw-r--r--thirdparty/gsl-lite/test/gsl-lite.t.hpp149
-rw-r--r--thirdparty/gsl-lite/test/issue.t.cpp140
-rw-r--r--thirdparty/gsl-lite/test/lest_cpp03.hpp1646
-rw-r--r--thirdparty/gsl-lite/test/not_null.t.cpp1956
-rw-r--r--thirdparty/gsl-lite/test/owner.t.cpp67
-rw-r--r--thirdparty/gsl-lite/test/span.t.cpp2199
-rw-r--r--thirdparty/gsl-lite/test/string_span.t.cpp1461
-rw-r--r--thirdparty/gsl-lite/test/util.t.cpp337
-rw-r--r--thirdparty/xmake.lua8
-rw-r--r--xmake.lua1
50 files changed, 21005 insertions, 6 deletions
diff --git a/src/zencore/xmake.lua b/src/zencore/xmake.lua
index db53c93cd..5dcb6ded4 100644
--- a/src/zencore/xmake.lua
+++ b/src/zencore/xmake.lua
@@ -35,6 +35,7 @@ target('zencore')
add_deps("json11")
add_deps("fmt")
add_deps("ryml")
+ add_deps("gsl-lite")
add_packages(
"vcpkg::openssl" -- required for crypto
@@ -42,7 +43,6 @@ target('zencore')
add_packages(
"vcpkg::eastl",
- "vcpkg::gsl-lite",
"lz4",
"xxhash",
{public=true}
diff --git a/src/zenhttp/xmake.lua b/src/zenhttp/xmake.lua
index d89345dac..0109aa2f8 100644
--- a/src/zenhttp/xmake.lua
+++ b/src/zenhttp/xmake.lua
@@ -8,11 +8,11 @@ target('zenhttp')
add_files("servers/httpsys.cpp", {unity_ignored=true})
add_includedirs("include", {public=true})
add_deps("zencore", "zentelemetry", "transport-sdk", "asio", "cpr")
+ add_deps("gsl-lite")
add_packages(
"vcpkg::curl", -- required by cpr
"vcpkg::openssl", -- required by curl
"vcpkg::zlib", -- required by curl
- "vcpkg::gsl-lite",
"http_parser"
)
add_options("httpsys")
diff --git a/src/zennet/xmake.lua b/src/zennet/xmake.lua
index b44878acc..b31c799cc 100644
--- a/src/zennet/xmake.lua
+++ b/src/zennet/xmake.lua
@@ -7,6 +7,4 @@ target('zennet')
add_files("**.cpp")
add_includedirs("include", {public=true})
add_deps("zencore", "zenutil", "asio")
- add_packages(
- "vcpkg::gsl-lite"
- )
+ add_deps("gsl-lite")
diff --git a/thirdparty/gsl-lite/.editorconfig b/thirdparty/gsl-lite/.editorconfig
new file mode 100644
index 000000000..d1169ef88
--- /dev/null
+++ b/thirdparty/gsl-lite/.editorconfig
@@ -0,0 +1,3 @@
+[*]
+indent_style = space
+indent_size = 4 \ No newline at end of file
diff --git a/thirdparty/gsl-lite/.gitattributes b/thirdparty/gsl-lite/.gitattributes
new file mode 100644
index 000000000..689b10950
--- /dev/null
+++ b/thirdparty/gsl-lite/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/thirdparty/gsl-lite/.gitignore b/thirdparty/gsl-lite/.gitignore
new file mode 100644
index 000000000..b3b901f7c
--- /dev/null
+++ b/thirdparty/gsl-lite/.gitignore
@@ -0,0 +1,3 @@
+out/
+build*/
+.vs/
diff --git a/thirdparty/gsl-lite/CHANGES.txt b/thirdparty/gsl-lite/CHANGES.txt
new file mode 100644
index 000000000..917195d1e
--- /dev/null
+++ b/thirdparty/gsl-lite/CHANGES.txt
@@ -0,0 +1,727 @@
+Changes in gsl-lite
+===================
+
+version 1.0.1 2025-05-19
+
+Fixes:
+- Add `span<>` constructor overloads for `span<>::iterator` arguments.
+ This improves backward compatibility, since our iterator used to be a pointer in v0.*, which made
+ `span{ otherSpan.begin(), 0 }` work because we have constructor overloads that accept pointers.
+- Add missing alias templates for polyfills.
+
+
+version 1.0.0 2025-05-19
+
+Breaking changes:
+- gsl-lite now lives in the single header file `<gsl-lite/gsl-lite.hpp>`, and all its symbols reside in namespace `gsl_lite`.
+ By default, gsl-lite no longer defines a namespace `gsl` or the unprefixed `Expects()` and `Ensures()` macros for
+ precondition and postcondition checking.
+ This change enables coexistence with Microsoft GSL or other GSL implementations. (#194)
+ To minimize the impact of the breaking changes, gsl-lite introduces an optional GSL compatibility mode controlled by the
+ new configuration switch `gsl_FEATURE_GSL_COMPATIBILITY_MODE`, which is is disabled by default and can be enabled by
+ defining `gsl_FEATURE_GSL_COMPATIBILITY_MODE=1`. This should not be used in public header files of libraries which use
+ gsl-lite because it precludes the use of Microsoft GSL in the same translation unit.
+ The legacy header file `<gsl/gsl-lite.hpp>` now forwards to `<gsl-lite/gsl-lite.hpp>` and implicitly enables the GSL
+ compatibility mode. When the legacy header is included, it emits a warning message which urges to either migrate to header
+ `<gsl-lite/gsl-lite.hpp>`, namespace `gsl_lite`, and the prefixed contract checking macros `gsl_Expects()` and
+ `gsl_Ensures()`, or to explicitly request GSL compatibility by defining `gsl_FEATURE_GSL_COMPATIBILITY_MODE=1`.
+ Please refer to the migration guide in the gsl-lite documentation for guidance on how to adapt your code.
+
+Other changes:
+- `span<>` now implements static extents. This was achieved by adapting the `span<>` implementation from Microsoft GSL,
+ back-porting it to support C++98 and older compilers. (#153)
+- gsl-lite v1 has different defaults for the numerous configuration options and switches:
+ - `gsl_FEATURE_STRING_SPAN`:
+ Version-1 default: `gsl_FEATURE_STRING_SPAN=0`
+ Version-0 default: `gsl_FEATURE_STRING_SPAN=1`
+ Reason: string spans are no longer part of the GSL specification.
+ - `gsl_FEATURE_BYTE`:
+ Version-1 default: `gsl_FEATURE_BYTE=0`
+ Version-0 default: `gsl_FEATURE_BYTE=1`
+ Reason: `byte` has been superseded by `std::byte` in C++17.
+ - `gsl_CONFIG_DEPRECATE_TO_LEVEL`:
+ Version-1 default: `gsl_CONFIG_DEPRECATE_TO_LEVEL=9`
+ Version-0 default: `gsl_CONFIG_DEPRECATE_TO_LEVEL=0`
+ - `gsl_CONFIG_INDEX_TYPE`:
+ Version-1 default: `std::ptrdiff_t`:
+ Version-0 default: `gsl_CONFIG_SPAN_INDEX_TYPE` (defaults to `std::size_t`)
+ Reason: the GSL specifies `gsl::index` to be a signed type.
+ - `gsl_CONFIG_ALLOWS_SPAN_COMPARISON`:
+ Version-1 default: `gsl_CONFIG_ALLOWS_SPAN_COMPARISON=0`
+ Version-0 default: `gsl_CONFIG_ALLOWS_SPAN_COMPARISON=1`
+ Reason: C++20 `std::span<>` does not support comparison because semantics (deep vs. shallow) are unclear.
+ - `gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR`:
+ Version-1 default: `gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR=1`
+ Version-0 default: `gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR=0`
+ Reason: see https://github.com/Microsoft/GSL/issues/395.
+ (Note that `not_null<>` in Microsoft GSL has an implicit constructor, cf. https://github.com/Microsoft/GSL/issues/699).)
+ - `gsl_CONFIG_TRANSPARENT_NOT_NULL`:
+ Version-1 default: `gsl_CONFIG_TRANSPARENT_NOT_NULL=1`
+ Version-0 default: `gsl_CONFIG_TRANSPARENT_NOT_NULL=0`
+ Reason: enables conformant behavior for `not_null<>::get()`.
+ - `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION`:
+ Version-1 default: `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=1`
+ Version-0 default: `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=0`
+ Reason: enables conformant behavior for `narrow<>()` (cf. #52).
+ - default runtime contract violation handling:
+ Version-1 default: `gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS`
+ Version-0 default: `gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES`
+ Reason: the mode enabled by `gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS` is consistent with the behavior of the `assert()` macro
+ while retaining runtime contract checks even if `NDEBUG` is defined.
+- `narrow<>()` and `narrow_failfast<>()` now support non-totally-ordered types such as `std::complex<>`, borrowing from
+ https://github.com/microsoft/GSL/pull/986. (#309)
+
+- gsl-lite now emits a warning if a configuration option alters the binary interface, leading to possible ODR violations.
+ The warning can be explicitly overridden by defining `gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI`.
+
+- For MSVC on Windows, gsl-lite now uses `#pragma detect_mismatch()` to diagnose ABI incompatibilities at link time.
+
+
+Fixes:
+- In C++98 mode, the faulty definition of the internal function macro `gsl_STATIC_ASSERT_()` was corrected, fixing an unwanted
+ predicate inversion for some internal compile-time checks.
+- Contract check macros now always expand to an expression or a statement, which avoids compiler warnings.
+
+
+Deprecations and removals:
+- Deprecated unsafe `span<>` member function `as_span<>()`.
+- Removed `Owner()` and `implicit` macros, which already were disabled by default.
+- Removed `finally()`, `on_error()`, and `on_return()` implementation for C++98.
+- Removed many deprecated functions:
+ - `as_writeable_bytes()`
+ - `basic_string_span<>` member function `operator()` for indexing
+ - `span<>` constructor overloads and `make_span()` overloads accepting reference arguments, `unique_ptr<>`, or `shared_ptr<>` arguments
+ - `span<>` member functions `at()` and `operator()` for indexing
+ - `span<>` member functions `length()`, `length_bytes()`, `as_bytes()`, `as_writeable_bytes()`
+- Removed the non-templated functions `finally()`, `on_return()`, and `on_error()` for C++98.
+
+
+version 0.43.0 2025-05-05
+
+Additions:
+- `not_null<>` now supports function pointers and nullable function objects such as `std::function<>` and (for C++11 and
+ newer) defines a conditionally enabled forwarding `operator()` to permit function-call syntax (#353, thanks to @n0F4x)
+- `not_null<>` now supports implicit construction from non-nullable arguments such as function objects and functions (#353)
+- Add `is_nullable<>` trait (#353, thanks to @BenFrantzDale)
+- Add tentative C++26 detection macro `gsl_CPP26_OR_GREATER`, `CONSTEXPR_26` language feature, and `gsl_constexpr26`
+ keyword macro
+- For C++20 and newer, define `operator<=>` for `not_null<>` in C++20
+- For C++20 and newer, Add `gsl_NO_UNIQUE_ADDRESS` which uses MSVC's ABI-breaking `[[msvc::no_unique_address]]` if
+ necessary
+
+Changes:
+- Add feature macro `gsl_FEATURE_STRING_SPAN`, defaulting to 0 for version-1 defaults, to control the availability of
+ string spans, which are no longer part of the GSL specification and have been deprecated for a while
+- Add feature macro `gsl_FEATURE_BYTE`, defaulting to 0 for version-1 defaults, to control the availability of `byte`,
+ which has been superseded by `std::byte` in C++17
+- If `gsl_FEATURE_STRING_SPAN=0`, we now avoid pulling in standard library header files `<ios>` and `<string>`
+- In version-1 mode, default to `gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS` rather than `gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES`,
+ which is more convenient in practice
+- `gsl_FEATURE_WITH_CONTAINER_TO_STD` now defaults to 0 with version-1 defaults (#353)
+- Remove unsupported CUDA toolkits and older GCC versions no longer available through Azure Pipelines (#353)
+
+Fixes:
+- Add `[[maybe_unused]]` annotations to macro-generated function definitions to avoid Clang warnings about unused functions
+ in anonymous namespaces
+
+version 0.42.0 2024-11-01
+
+Additions:
+- Define `gsl_MAYBE_UNUSED_MEMBER` for `[[maybe_unused]]` annotations on members
+ (https://github.com/gsl-lite/gsl-lite/commit/34ba5141492a88912e2055e08cd1bdd6714431c5)
+- Support `not_null<void*>` (#341, thanks to @BenFrantzDale)
+- Support `not_null<>` for `unique_ptr<void, D>` and `shared_ptr<void>` (#349, thanks to @BenFrantzDale)
+
+Changes:
+- For modern (≥v1) defaults, `finally()`, `on_return()`, and `on_error()` are now implemented without virtual function calls (#342)
+- Deprecate `finally()`, `on_return()`, and `on_error()` for pre-C++11 (#342)
+- `narrow_failfast<>()` now uses `gsl_Assert()` rather than `gsl_Expects()` to express the contract check (#351)
+- `std::hash<gsl_lite::byte>` now forwards to `std::hash<unsigned char>` (#343)
+- Add Continuous Integration for GCC 13, Clang 17 to 19, and for NVCC 12.6; remove CI for GCC 10 on macOS and for
+ Apple Clang 12.0.5 and earlier (#351)
+
+Fixes:
+- `std::terminate()` cannot be called from CUDA device code, but the call may go undetected due to a NVCC issue;
+ for `!gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )`, `narrow<>()` now makes sure that the program is terminated by
+ issuing a trap instruction if `std::terminate()` is not available (#351, thanks to @pauleonix for helping track this down)
+- `narrow<>()` no longer responds to `gsl_CONFIG_CONTRACT_VIOLATION_THROWS` because it does not do contract checking;
+ therefore, it now plainly fails to compile if `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION` is set to 1 even though
+ exceptions are unavailable (e.g. in device code) (#351)
+- Fix issues in test suite (#338, thanks to @musicinmybrain)
+
+version 0.41.0 2023-04-12
+
+Additions:
+- Add tentative C++23 detection macro `gsl_CPP23_OR_GREATER`, `CONSTEXPR_23` language feature, and `gsl_constexpr23`
+ keyword macro (#329)
+- Add `gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS` config switch for suppressing the compile-time syntax
+ validation of contract check expressions (#330)
+
+Changes:
+- Deprecate `string_span` and `zstring_span` and prepare for removal (#335)
+- Continuous Integration now also tests GCC 12, Clang 14 thru 16, and NVCC 11.8 and 12.1
+- Remove Continuous Integration for GCC 6 and earlier, Clang 5 and earlier, Apple Clang 11.0.0 and earlier, and
+ CUDA 10.2 and earlier (#333, #334)
+
+Fixes:
+- Use NVCC's `__builtin_assume()` for `gsl_ASSUME_()` in device code (#324, thanks to @codecircuit)
+- Fix `not_null_ic<>` copy construction (#326, thanks to @runer112)
+- Respect libc++ configuration option to disable `wchar_t` (#331, thanks to @burnpanck)
+- Suppress "-Wweak-vtables" warning for Clang (#332, thanks to @mrahn)
+- Suppress "-Wuseless-cast" warning for GCC (#332, thanks to @wirew0rm)
+
+version 0.40.0 2021-11-05
+
+Additions:
+- Add debug-mode contract checking macros `gsl_ExpectsDebug()`, `gsl_EnsuresDebug()`, `gsl_AssertDebug()` which are sensitive
+ to the `NDEBUG` macro, and thus similar to `assert()` (#316)
+- Add dedicated contract check configuration macros for device code: `gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT`/`ON`/`OFF`,
+ `gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS`/`TRAPS`/`CALLS_HANDLER`, and
+ `gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME`/`ELIDE` (#317)
+- Add `gsl::is_valid()` for explicitly detecting the moved-from state of a `gsl::not_null<>` object (#318)
+- Add device code detection macro `gsl_DEVICE_CODE` (evaluates to 1 when compiling CUDA device code, 0 when compiling host code)
+
+Changes:
+- Continuous Integration now also tests Clang 13 and updates CUDA version to 11.5
+- Improve documentation for contract checking macros and configuration macros
+
+Fixes:
+- Check for `gsl::` target rather than nonexistent `gsl-lite::` target in Config.cmake (#315, thanks to @Ram-Z)
+
+version 0.39.0 2021-09-30
+
+Additions:
+- Add `gsl::make_unique<T>()` and `gsl::make_shared<T>()` which resemble the eponymous functions from `std` but return
+ `gsl::not_null<std::unique_ptr<T>>` and `gsl::not_null<std::shared_ptr<T>>` (#312)
+- Add basic support for NVHPC compiler (#308, thanks to @olupton)
+
+Changes:
+- Continuous Integration now also tests GCC 11, Clang 12, and AppleClang 12.0.5 and 13, and updates CUDA version to 11.4 (#314)
+- Remove C++98 polyfills `std98::equal()`, `std98::lexicographical_compare()` from public interface (#313)
+
+Fixes:
+- `gsl::not_null<std::shared_ptr<T>>` now correctly converts to `std::weak_ptr<T>` (#311, thanks to @stohrendorf)
+
+version 0.38.1 2021-04-22
+
+Additions:
+- Add feature detection macro `gsl_HAVE( C99_PREPROCESSOR )`
+- Add `gsl_CONSTRAINT()` which can be used to impose concept requirements on template type parameters in a backward-compatible manner:
+ `template< gsl_CONSTRAINT(Concept) T >` expands to `template< Concept T >` for C++20 and to `template< typename T >` otherwise
+- Add C++20 polyfill `std20::endian()` (#305)
+- Restore Continuous Integration testing for NVCC 10.2
+- Add basic CUDA runtime tests to test suite (#307)
+
+Changes:
+- Continuous Integration now also tests "RelWithDebInfo" configuration for select compilers and platforms
+
+Fixes:
+- Fix regression in precondition/postcondition/assertion checks for CUDA (cf. #302, thanks to @Spielix)
+- Add workaround for GCC bug to test suite (cf. #303, thanks to @sanjayankur31)
+- Fix endianness issues in test suite (cf. #304, thanks to @sanjayankur31)
+- Improve `constexpr` support for `span<>`; add `constexpr` tests (#306)
+
+version 0.38.0 2021-03-31
+
+Additions:
+- Add macros `gsl_Assert()`, `gsl_AssertAudit()` to express checks which are neither pre- nor postconditions (#294)
+- Add fail-fast operation `gsl_FailFast()` which is guaranteed to terminate normal execution in some way
+ (exception, `std::terminate()`, or trap instruction) (#294)
+- Add configuration option `gsl_CONFIG_CONTRACT_VIOLATION_TRAPS` which makes `gsl_Expects()`/`gsl_Ensures()`/`gsl_Assert()` (and
+ the `Audit` variants if audit mode is enabled) and `gsl_FailFast()` execute a trap instruction in case of a contract violation
+- Add configuration option `gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS` which implements `gsl_Expects()`/`gsl_Ensures()`/`gsl_Assert()`
+ (and the `Audit` variants if audit mode is enabled) in terms of the `assert()` macro from the standard library. This has the
+ benefits that both legacy assertions and contract checks can be globally suppressed with a single macro (`NDEBUG`), and that
+ `assert()` prints an informative error message which contains the contract check expression.
+- Add `as_nullable()` function (#251, thanks to @petamas)
+- Add compiler detection macro for NVCC (#294)
+- Add compiler detection macro and tentative support (no CI) for ARMCC (#293; thanks to @woodsking2)
+- Add conditional `std::hash<>` specialization for `not_null<>` (#297; thanks to @mbs-c)
+- Track language and library versions separately; new macros `gsl_STDLIB_CPPxx_OR_GREATER` indicate availability of the standard library
+- Add feature detection macros `gsl_HAVE( HASH )`, `gsl_HAVE( MOVE_FORWARD )`, `gsl_HAVE( OVERRIDE_FINAL )`
+- Add `size_type` to `span<>` and `basic_string_span<>`
+- Add Continuous Integration testing for NVCC 11.0-11.2 (CUDA14, CUDA17), Clang 10-11, GCC 10, Apple Clang 12.0.0
+- Add Continuous Integration testing for Clang with libstdc++
+- Add Valgrind "memcheck" run to Continuous Integration
+- Add testing for more configuration scenarios, e.g. building with exceptions disabled and using different ways of precondition
+ violation handling
+
+Changes:
+- Remove dependency on standard library headers <algorithm> and <iterator> (#290, #295; thanks to @mpusz)
+- Use of `gsl_HAVE()`, `gsl_CONFIG()`, `gsl_FEATURE()` with unknown arguments now causes compilation errors (#272)
+- `narrow<>()` now issues a `static_assert()` that refers to `narrow_failfast<>()` if exceptions are unavailable (#269)
+- With version-1 defaults, `not_null<>` now has a specialization for raw pointers which avoids unnecessary contract checks (#300)
+- The contract expression is now part of the exception message in `gsl_CONFIG_CONTRACT_VIOLATION_THROWS` mode
+- `narrowing_error` now produces a less unhelpful exception message ("narrowing_error")
+- `gsl_noexcept` now falls back to `throw()` if `noexcept` is unavailable
+- Most symbols are now accessible through both `namespace gsl` and `namespace gsl_lite` to ease migration
+- `not_null_ic<>` is now also visible in `namespace gsl_lite` (#280; thanks to @woodsking2)
+- `nullptr_t` comparison operators for `not_null<>` are now explicitly deleted
+- More uses of `gsl_NODISCARD` throughout the library
+- For NVCC ≥11.3, make use of new `__builtin_unreachable()` intrinsic in `gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME` mode
+
+Fixes:
+- Many bugfixes (#249, #250, #255, #256, #262, #263, #268, #270, #271, #286, #287, #292; thanks to @fodinabor, @KazDragon,
+ @martinmoene, @Maximus5, @Pesa, @petamas, @travnick)
+
+version 0.37.0 2020-05-13
+
+Additions:
+- Add configuration option `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION`
+- Add configuration option `gsl_CONFIG_ALLOWS_SPAN_COMPARISON`
+- Add `narrow_failfast<>()`, a fast-fail variant of `narrow<>()` (#52)
+- Add `front()` and `back()` to `span<>` and `basic_string_span<>` (#241, thanks to @ned14)
+
+Changes:
+- Rename `as_writeable_bytes()` -> `as_writable_bytes()` to follow C++20 in spelling; the old name is still provided for compatibility
+- Rename `gsl_DEPRECATED()` -> `gsl_DEPRECATED_MSG()`, add `gsl_DEPRECATED`
+- Add more `gsl_DEPRECATED()` annotations
+- Deprecate `span<>::at()`, `basic_string_span<>::at()`, and call indexing
+- Minor documentation improvements
+- Unify internal SFINAE macros to `gsl_ENABLE_IF_()` (#238; thanks to @martinmoene)
+- Add more comprehensive tests for `narrow<>()` and `narrow_failfast<>()`
+
+Fixes:
+- Fix spurious static assertion for pre-/postcondition check arguments explicitly convertible to bool if `gsl_CONFIG_CONTRACT_CHECKING_OFF` is defined
+- Fix hard failure in `span<>` constrained constructor (#242, thanks to @orangeturtle739)
+- Make `gsl::detail::is_compatible_container<>` a proper type trait
+
+
+version 0.36.0 2020-01-24
+
+The repository now moved to a dedicated GitHub organization: https://github.com/gsl-lite/gsl-lite
+
+gsl-lite is now mostly maintained by @mbeutel (#175).
+
+Additions:
+- Describe versioning semantics in Readme
+- Add audit-level contract checks `gsl_ExpectsAudit()` and `gsl_EnsuresAudit()` (#172)
+- Add `basic_zstring_span<>` and `zstring_span` (#136, #154, thanks to @chan-lee)
+- Add support for user-defined contract violation handler `fail_fast_assert_handler()`
+- Add macros `gsl_NORETURN`, `gsl_NODISCARD`, `gsl_DEPRECATED()`, `gsl_constexpr17`, `gsl_constexpr20`
+- Add C++11 polyfills in `gsl::std11`: `remove_reference<>`
+- Add C++17 polyfills in `gsl::std17`: `conjunction<>`, `disjunction<>`, `negation<>`, `void_t<>`
+- Add C++20 polyfills in `gsl::std20`: `identity`, `type_identity<>`, `ssize()` (#144, #180), `remove_cvref<>`
+- Add configuration macro `gsl_CONFIG_TRANSPARENT_NOT_NULL` (#185)
+- Add configuration macro `gsl_CONFIG_INDEX_TYPE` which controls the type of `gsl::index` independently of `gsl::span<>::index_type` (#169)
+- Add language feature macro `gsl_HAVE_EXCEPTIONS`
+- Add macros `gsl_DEFINE_ENUM_BITMASK_OPERATORS()` and `gsl_DEFINE_ENUM_RELATIONAL_OPERATORS()`
+- Add header <gsl-lite/gsl-lite.hpp> and namespace `gsl_lite` to pave the way for future coexistence with M-GSL (#221, #222)
+- Add Continuous Integration for more versions of GCC (4.7 through 9), Clang (3.5 through 9), AppleClang (7.3 through 11), and MSVC (2010 through 2019)
+- Run tests with AddressSanitizer and UndefinedBehaviorSanitizer in CI (GCC 9, Clang 9)
+- Add Continuous Integration for NVCC 10.2 (with GCC 7, 8 on Linux, MSVC 2019 on Windows) to test CUDA support
+
+Changes:
+- `not_null<>` now properly supports smart pointers (#184, #197, huge thanks to @petamas)
+- Restructure contract checking configuration macros such that checking policy (off, on, audit), violation handling (throws, terminates, calls handler) and unenforced contract handling (assume, elide) can be configured independently (cf. https://github.com/martinmoene/gsl-lite/#contract-violation-response-macros)
+- `gsl_noexcept` no longer depends on contract violation settings (cf. https://github.com/martinmoene/gsl-lite/commit/0c296a9c986ac070997610fc7cf86e9c517558bf)
+- `gsl_FEATURE_IMPLICIT_MACRO` now defaults to 0 (#156, thanks to @tadeu)
+- AppleClang is now considered a separate compiler (use `gsl_COMPILER_APPLECLANG_VERSION` for checking)
+- CMake installs arch-independent by default
+- CMake doesn't install M-GSL compatibility headers by default
+- gsl-lite now compiles warning-free with MSVC at warning level 4
+- Many small improvements (thanks to @AraHaan, @codecircuit, @elnull, @ilyalesokhin-starkware, @ngrodzitski, @petamas, @stohrendorf, @theodelrieu)
+
+
+version 0.34.0 2019-03-21
+
+Additions:
+- Add macro gsl_REQUIRES_T() (nonstd lite issue 18)
+
+Changes
+- Change the CMake package folder name to gsl-lite (it was gsl)
+- Add a usage description for the Conda package manager to the Readme.
+- Update lest test framework to v1.35.1.
+
+
+version 0.33.0 2019-03-08
+
+Additions:
+- Add script/create-cov-rpt.py to create OpenCppCoverage report (nonstd-lite project issue 29)
+- Add script/create-vcpkg.py (nonstd-lite-project issue 28)
+- Add script/upload-conan.py (nonstd-lite-project issue 26)
+- Add conanfile.py, edit it from script/update-version.py (nonstd-lite-project issue 26)
+- Add CMake installation and config-file packaging; Let tests and example use gsl-lite interface library
+- Add "LANGUAGES CXX" to CMake project
+- Add GNUC -Wsign-conversion warning to CMake configuration
+- Add AppleClang to CMake configuration
+- Add OSX to Travis configuration
+- Add TOC entry for Standard selection macro (#128, thanks to @egarrulo)
+- Add span::ssize(), ssize(span), size(span) (#144)
+- Add test/tc-cl.bat
+
+Changes:
+- Rename "Guideline support library" to "Guidelines -" (#134)
+- Align Appveyor configuration (plan 9, nonstd-lite-project issue 14)
+- Align CMakefiles.txt (plan 8, nonstd-lite-project issue 13)
+- Align test scripts (nonstd-lite-project issue 12)
+- Align badges in readme (nonstd-lite-project issue 3)
+- Obviate need for -DNOMINMAX with MSVC (nonstd-lite issue 16)
+- Prevent and suppress warnings from clang
+- Let ctest produce output on failure
+- Update lest test framework to v1.35.0.
+
+Fixes:
+- Fix CMake install command (expected-lite issue 25, thanks to @rmorozov)
+- Fix clashing CMake cached variable, use 'gsl' for namespace and package folder (thanks to @rmorozov)
+- Fix template argument in not_null<> comparison operators (#143, thanks @stohrendorf)
+- Fix macro gsl_IN_STD (#142, thanks to @Flamefire)
+- Fix possible int overflow in nonstd::span::subspan() range (issue #138, thanks to @fefe17)
+- Fix link to P0122 (#130, thanks to @alexeyr)
+- Fix for misleading __cplusplus of GCC 4.7.0 and earlier (#127, thanks to @egarrulo)
+- Fix final_action_return() and final_action_error() during stack unwinding (#126, thanks to @patstew)
+- Fix unused parameter if Expects elided via new macro gsl_EXPECTS_UNUSED_PARAM (#123, #124, thanks to @kugelrund)
+
+version 0.32.0 2018-05-12
+
+- Review not_null (issue #122).
+- Add not_null_ic with implicit constructor, allowing copy-initialization.
+- Enable making not_null constructor explicit via gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR, default 0 (breaking, issue #46).
+- Enable not_null get() return by const & via gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF (via M-GSL PR 651 @xaxxon, PR 675 @ericLemanissier).
+- Change constraint on not_null construction from is_convertible to is_constructible (via M-GSL PR 650, @xaxxon).
+- Change to take not_null constructor argument by const & when rvalue references are not available.
+- Add not_null non-is-default rvalue reference copy-constructor, copy-assignment.
+- Remove not_null converting assignment operator.
+- Rename to gsl_HAVE_EXPLICIT.
+- Adapt several compile-time tests for not_null with explicit constructor.
+- Fix GNUC C++98 compilation by making RefCounted conversion function const in not_null.t.cpp.
+
+version 0.31.0 2018-05-10
+
+- Change span towards proposal p0122r7 (issue #118).
+- Add gsl_lite_MAJOR, gsl_lite_MINOR, gsl_lite_PATCH, script/update-version.py.
+- Add configuration selector gsl_CONFIG_DEPRECATE_TO_LEVEL.
+- Add feature selector gsl_FEATURE_WITH_CONTAINER_TO_STD.
+- Add feature selector gsl_FEATURE_MAKE_SPAN_TO_STD.
+- Add feature selector gsl_FEATURE_BYTE_SPAN_TO_STD.
+- Add macros gsl_FEATURE(), gsl_CONFIG(), gsl_HAVE().
+- Add macro gsl_ADDRESSOF(x).
+- Add span::value_type.
+- Add details::can_construct_span_from<>.
+- Add convertible constraint to span C-array constructor.
+- Add class template argument deduction guides for span.
+- Add make_span( with_container_t, ...) creator functions.
+- Add byte_span() creator functions.
+- Use C++11 constexpr where possible.
+- Parenthesize macro arguments.
+- Omit macros min(), max() via -DNOMINMAX.
+- Update t-all.bat for various configuration and feature selections.
+
+version 0.30.0 2018-05-06
+
+- Add support for DJGPP cross compiler is introduced (PR #107, thanks to Tom� Zeman, @zemasoft).
+- Add Readme.md to example/cmake-pkg.
+- Update lest test framework to v1.33.1.
+- Allow strict aliasing with Clang and GNUC for gsl::byte (issue #114).
+- Enable differentiating between MSVC 14.0 (VS 2015) and 14.1 (VS 2017), also report clang version.
+- Remove the space after ':' in FILE: LINE in reported locations (issue #112).
+- Avoid MSVC level 4 warning C4127: conditional expression is constant (issue #115, thanks to @kpeace)
+- Add a constructor to allow rvalue to const lvalue conversion (issue #113, PR #117, thanks to @theodelrieu )
+- Enable owner alias template for VC12 (Issue #111, thanks to @sg-james)
+- Fix omission of #include <algorithm>
+- Fix clang compilation by specifying C++ standard
+- Fix gsl-lite version in section "As CMake package"
+- Fix type in a test of span has been correced (PR #105, thanks to Tom� Zeman, @zemasoft)
+
+version 0.29.0 2018-03-03
+
+- Added CMake package, thanks to @FlorianWolters (PR #100, #103).
+- Added CMake option GSL_LITE_OPT_BUILD_TESTS to ./CMakeLists.txt (default off).
+- Added CMake option GSL_LITE_OPT_BUILD_EXAMPLESto ./CMakeLists.txt (default off).
+- Added scipt/install-gsl-pkg.py
+- Added script use-gsl-pkg.py as part of an example that uses the package.
+- Added script/update-version.py to updated gsl-lite's version number in relevant files.
+- Added type `gsl::index` for container indices, subscripts and sizes.
+- Fixed padding of the output stream operator of class `string_span` to pad to the right side.
+- Deprecated span::length() and span::length_bytes() (issue #99).
+- Deprecated constructors span(shared_ptr<element_type> const & ptr) and span(unique_ptr<element_type> const & ptr)` (issue #98).
+- Added documentation section 'Deprecation'.
+- Expanded documentation section 'Installation and use'.
+- Updated documentation section 'Reported to work with'.
+
+version 0.28.0 2018-01-01
+
+- Expand Travis and Appveyor CI compiler matrices and use CMake configuration.
+- Fix to use CMAKE_CXX_COMPILER_VERSION in CMake configuration.
+- Add targets for various -std flags for MSVC to CMake configuration.
+- Add Core Guidelines checking, limited to GSL Lite.
+- Add test to compare empty to non-empty string span.
+- Suppress test to compare empty string spans.
+- Update Wandbox link for release 0.28.0.
+- Update Wandbox link for release 0.27.0.
+
+version 0.27.0 2017-12-30
+
+- Change extension of GSL Lite header file to .hpp with backwards compatibility via headers gsl.h and gsl/gsl-lite.h. See issue #94 (thanks to @AraHaan).
+- Suppress several warnings from Microsoft's CppCoreCheck. See pull request #95 (thanks to @AraHaan).
+
+version 0.26.0 2017-12-09
+
+- Rename final_act to final_action per issue #89.
+- Make clang-tidy cppcoreguidelines checks pass per PR #91 (thanks to @poconbhui).
+- Fix nullptr to gsl_nullptr in not_nul::get() per PR #90 (thanks to @poconbhui).
+- Fix -Wshadow warning per PR #84 (thanks to @MikeLankamp).
+- Add conan installation instructions and badge (thanks to @agauniyal).
+- Add CMake install target per issue #85.
+
+version 0.25.0 2017-10-22
+
+- Restrict owner<T> to pointers if possible, per issue #80.
+- Introduce gsl_is_delete, per issue #81.
+- Add deleted operators for not_null<>, per issue #82.
+- Add more comparison operators for not_null<>, per issue #83.
+- Use = default for not_null copy assignment/construction if available.
+- Take parameter in not_null assignment by value as in ctor.
+
+version 0.24.0 2017-07-10
+
+- Add try it online badge.
+- Implement to_byte(), to_integer() for C++17 per issue #75 (thanks to David Mugnai, @cinghiale).
+
+version 0.23.0 2017-06-29
+
+- Enable use of option -Wundef per issue #74.
+- Update lest to version 1.30.1.
+- Check macro via #ifdef if possibly undefined (support -Wundef).
+- Fix check for make_unique().
+- Fix CMake compiler selection.
+- Make struct definition nonlocal for C++98, C++03.
+- Add not_null<> tests for member access and dereferencing.
+- Add dereference operator to not_null<> per issue #73.
+- Add compiler version information.
+- Add constexpr to not_null<>.
+- Report gsl_CPP11_OR_GREATER etc.
+
+version 0.22.0 2017-04-27
+
+- Add operator<< for string_span (thanks to Magnus Bergsten, @Sillamacka).
+- Fix conversion and sign-conversion warnings (thanks to Magnus Bergsten, @Sillamacka).
+- Fix memory leak, which prevents tests to pass with address sanitizing (thanks to @Vladimir Rapatskiy).
+- Fix order of add_compile_options() and its targets in CMakeLists.txt.
+- Replace fail_fast's base with std::logic_error as per issue #69.
+- Update lest_cpp03.hpp to version 1.29.1 (Fix above conversion and sign-conversion warnings).
+
+version 0.21.0 2016-11-28
+
+- Add as_bytes() for basic_string_span<> (thanks to Magnus Bergsten, @Sillamacka).
+- Fix: remove call to hash<std::size_t>(), undefined with Xcode on Mac OS X (issue #63, thanks to Dave Tallman).
+- Fix: remove static from enum in integral_constant (thanks to Dave Tallman).
+- Change t[g]-all.bat to test variations of C++ std/span index type/contract violation response.
+
+version 0.20.0 2016-11-18
+
+- Remove used_length(), same as length()
+- Rename bytes(), used_bytes() to size_bytes(), length_bytes()
+- Make final_act<T> and final_act_return<T> useable with VC11/VS2012 (PR #61, thanks to @lm1458777)
+- Fix fail_fast_assert() for gcc < 6 for no-throw/std::terminate() case (comment, thanks to @xsacha)
+- Fix =default with gsl_noexcept for gcc < 6 for basic_string_span (PR #58, thanks to @xsacha)
+
+version 0.19.0 2016-11-17
+
+- Rename as_span() creator functions to make_span() (issue #49).
+- Add make_span() for gsl::shared_ptr, gsl::unique_ptr.
+- Add section Algorithms to feature table.
+- Remove maybe_null from feature table (M-GSL PR 123, 124, 126).
+
+version 0.18.0 2016-11-11
+
+- Remove span::size_type, deprecated since 0.12.0.
+- Add gsl_CONFIG_SPAN_INDEX_TYPE configuration macro; default size_t.
+- Add span constructor for std::array<> const &.
+- Add span constructor for std::unique_ptr, std::shared_ptr.
+- Make span's unconstrained constructor disabled at default.
+ This enables construction from unique_ptr and shared_ptr.
+- Prevent conversion warning [-Wconversion]
+- Prevent old-style casts warning [-Wold-style-cast]
+- Replace arr with &arr[0], not automatic decay (several).
+- Update lest_cpp03.hpp to version 1.27.2
+- Fix noexcept with default ctors for GNUC < 4.9.0 (adapted PR #58, thanks to Dmitry Banschikov, @ubique).
+
+version 0.17.2 2016-11-10
+
+- Use &arr[0], not automatic decay
+- Workaround GNUC 5 throw constexpr bug
+- Workaround for GNUC 5.2.0 failing two tests
+- Use order: gsl_api inline gsl_constexpr type f() gsl_noexcept
+
+version 0.17.1 2016-11-09
+
+- Fixes thanks to Magnus Bergsten, @Sillamacka:
+- Marked several functions as constexpr.
+- Fix: make gsl::fail_fast_assert() constexpr allowing Expects() from constexpr functions.
+- Fix: prevent pointer decay to let remove_z() invoke wrong overload.
+- Fix: remove span used in string_length(), it has two bound problems.
+
+version 0.17.0 2016-11-09
+
+- Add free-standing as_bytes() and as_writable_bytes() as in M-GSL (PR #55, thanks to Dmitry Banschikov, @ubique).
+- Member methods as_bytes() and as_writable_bytes() have been deprecated.
+
+version 0.16.1 2016-11-09
+
+- Fix macro used with string_span comparison.
+
+version 0.16.0 2016-11-09
+
+- Allow comparison with types that are convertible to string_span (issue #53, thanks to Magnus Bergsten, @Sillamacka).
+
+version 0.15.0 2016-11-09
+
+- Add basic_string_span (issue #53, thanks to Magnus Bergsten, @Sillamacka).
+
+version 0.14.0 2016-11-03
+
+- narrow() now uses std::terminate(), unless gsl_CONFIG_CONTRACT_VIOLATION_THROWS (issue #50, thanks to @Sp3EdeR)
+- narrow_cast<>() now forwards its argument if possible (issue #44).
+
+version 0.13.0 2016-10-09
+
+- Add on_return() and on_error() as experimental feature (gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD).
+
+version 0.12.0 2016-10-08
+
+- Fix test compilation with GCC 4.8.4.
+- Remove span::value_type deprecated since version 0.9.0 (use element_type).
+- Deprecate span::size_type (issue #42).
+- Make span's stream output for tests more container-like.
+- Make operations on byte C++11 constexpr except for op=() variants.
+- Rename �Guidelines support library" to "Guideline -" (issue #39).
+- Add tests for C++11 constexpr-ness.
+- Add copy algorithm for span (issue #36).
+- Add GSL version by Vicente J. Botet Escriba to Readme.
+
+version 0.11.0 2016-09-04
+
+- Add missing byte comparisons (non-enum class case).
+- Add missing gsl_noexcept to byte equality operator.
+
+version 0.10.1 2016-09-02
+
+- Use struct with unsigned char for byte with pre-C++17 (issue #34).
+
+version 0.10.0 2016-08-31
+
+- Remove operator bool() per issue #33.
+- Remove deprecated gsl_CONFIG_THROWS_FOR_TESTING.
+- Remove parentheses and allow lest to decompose span comparison expressions.
+- Allow comparison of spans with a different element type or const-volatile-ness.
+- Add gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON for span comparison configuration.
+
+version 0.9.1 2016-08-25
+
+- Move conditional inclusion of cstdint out of namespace gsl.
+
+version 0.9.0 2016-08-23
+
+- Provide gsl/gsl header for compatibility with M-GSL.
+- Add index_type to span while keeping size_type.
+- Add gsl_noexcept to iterator creators begin() etc.
+- Add at(std::initializer_list<T>, index).
+- Add at(span<T>, index).
+- Add call operator to span for element access as per p0122r3.
+- Add test: empty spans compare equal as per p0122r3.
+- Use span's size_type.
+- Move at() to section utilities.
+- Move comparison functions outside span.
+- Deprecate span::value_type, use span::element_type per M-GSL, p0122r3.
+- Remove non-const index operator, at().
+
+version 0.8.0 2016-08-20
+
+- Add operations for byte type.
+
+version 0.7.5 2016-08-08
+
+- Fix to create empty subspan, enabling slicing off data until span is empty (PR #26, thanks to Janusz Chorko).
+
+version 0.7.4 2016-07-09
+
+- Revert "Remove boundary check from operator[]()" of v0.7.3.
+
+version 0.7.3 2016-07-08
+
+- Removed boundary check from operator[]()
+- Changed indexing to return non-const reference and make it STL compliant (issue #23, thanks to @marton78)
+- Made converting constructors public (issue #22, thanks to @marton78).
+
+version 0.7.2 2016-07-06
+
+- Fixed as_span() for const arguments (thanks to Dave Tallman).
+
+version 0.7.1 2016-07-01
+
+- Fixed with_container_t to be literal type (thanks to Dave Tallman).
+
+version 0.7.0 2016-06-30
+
+- Added tagged construction from a container to span.
+- Replaced gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR with gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR
+
+version 0.6.1 2016-06-29
+
+- Fixed library for the removal of _HAS_CPP0X in VS2015 Update 3 (Issue #21, thanks to @exjam)
+- Added tests tagged [.stdlangauge], [.stdlibrary] to inspect various gsl_HAVE_... macros.
+- Added tag [.stdc++] to test to inspect __cplusplus.
+- Updated lest test framework to version 1.27.0.
+
+version 0.6.0 2016-06-25
+
+- Renamed Final_act to final_act to follow standard library conventions.
+- Fixed final_act to also work without copy-elision optimization, issue #19 (thanks to Marco Arena).
+
+version 0.5.0 2016-06-24
+
+- Added compatibility with MS GSL symbolic names for contract violation response control.
+- Added contract violation response control as suggested in N4415, Simple Contracts for C++.
+
+version 0.4.1 2016-06-23
+
+- Added gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR for pre-C++11 (default: 1).
+- Avoided std::distance() to support CUDA.
+- Avoided shadowing according to the too-strict option -Wshadow of gcc before 4.8 (thanks to Dave Tallman).
+- Removed comparisons of unsigned with zero.
+- Fixed ensure_z() without length (thanks to Dave Tallman).
+
+version 0.4.0 2016-05-28
+
+- Added support for CUDA compilation.
+
+version 0.3.2 2016-05-27
+
+- Fixed compilation error in narrow() for VC11 (VS2012).
+
+version 0.3.1 2016-05-25
+
+- Added test for construction of a span from another span of a compatible type.
+- Changed view to span in specification.
+
+version 0.3.0 2016-05-24
+
+- Added first(), last() and subspan().
+- Improved example 02-span.cpp (thanks to Dave Tallman).
+
+version 0.2.2 2016-05-23
+
+- Fixed missing return in not_null copy-assignment (thanks to PVS-Studio).
+
+version 0.2.1 2016-05-23
+
+- Added several tests.
+- Added definition of gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG.
+- Prevented using default function template argument in span for pre-VS2013 (VC12).
+- Fixed compile error with clang targeting MSVC, PR #17 (Thanks to @ned14).
+- Fixed data access of empty container, PR #16 (Thanks to @realzhtw).
+
+version 0.2.0 2016-02-02
+
+- Removed constructor span( U (&arr)[N], size_type size ), not part of M-GSL and in favour of:
+- Changed constructor to span( pointer data, size_type size ), removing & from pointer & data (Thanks to @realzhtw).
+- Added construction from an l-value for C++11 onwards.
+
+version 0.1.0 2016-02-02
+
+- Added move-construction and move-assignment to span<>.
+
+version 0.0 2015-09-25
+
+- Initial release.
diff --git a/thirdparty/gsl-lite/LICENSE b/thirdparty/gsl-lite/LICENSE
new file mode 100644
index 000000000..941611dea
--- /dev/null
+++ b/thirdparty/gsl-lite/LICENSE
@@ -0,0 +1,24 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2019 Martin Moene
+Copyright (c) 2019-2025 Moritz Beutel
+Copyright (c) 2015-2018, 2025 Microsoft Corporation. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/thirdparty/gsl-lite/README.md b/thirdparty/gsl-lite/README.md
new file mode 100644
index 000000000..4f178d36e
--- /dev/null
+++ b/thirdparty/gsl-lite/README.md
@@ -0,0 +1,338 @@
+# *gsl-lite*
+
+
+| metadata | build | packages | try online |
+| -------- | ------ | -------- | ---------- |
+| [![Language](https://badgen.net/badge/C++/98,11+/blue)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) <br> [![License](https://badgen.net/github/license/gsl-lite/gsl-lite)](https://opensource.org/license/MIT) <br> [![Version](https://badgen.net/github/release/gsl-lite/gsl-lite)](https://github.com/gsl-lite/gsl-lite/releases) | [![Azure Pipelines build status](https://dev.azure.com/gsl-lite/gsl-lite/_apis/build/status/gsl-lite.gsl-lite?branchName=master)](https://dev.azure.com/gsl-lite/gsl-lite/_build/latest?definitionId=1&branchName=master) <br> [![AppVeyor build status](https://ci.appveyor.com/api/projects/status/1v6eqy68m8g7tm06?svg=true)](https://ci.appveyor.com/project/gsl-lite/gsl-lite) | [![Vcpkg](https://badgen.net/badge/latest/on%20Vcpkg/blue)](https://vcpkg.io/en/package/gsl-lite) <br> [![single header](https://badgen.net/badge/latest/single%20header/blue)](https://raw.githubusercontent.com/gsl-lite/gsl-lite/master/include/gsl-lite/gsl-lite.hpp) | [![Try it on Compiler Explorer](https://badgen.net/badge/on/Compiler%20Explorer/blue)](https://gcc.godbolt.org/z/8jqq6P1G5) <br> [![Try it on Wandbox](https://badgen.net/badge/on/Wandbox/blue)](https://wandbox.org/permlink/ZTwg9XJ9IEd4SptE) |
+
+
+***gsl-lite*** is a portable, single-file, header-only library for defensive programming based on the [C++ Core Guidelines Support Library](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-gsl) specification.
+
+
+## Contents
+
+- [Example usage](#example-usage)
+- [In a nutshell](#in-a-nutshell)
+- [License](#license)
+- [Dependencies](#dependencies)
+- [Installation and use](#installation-and-use)
+- [Why *gsl-lite*?](#why-gsl-lite)
+- [Features](#features)
+- [Reference documentation](doc/Reference.md)
+- [Migration guide](#migration-guide)
+- [Using *gsl-lite* in libraries](#using-gsl-lite-in-libraries)
+- [Reported to work with](#reported-to-work-with)
+- [Version semantics](#version-semantics)
+- [Contributing](#contributing)
+
+
+## Example usage
+
+```c++
+#include <memory>
+#include <utility>
+#include <numeric>
+
+#include <gsl-lite/gsl-lite.hpp>
+
+
+namespace my_lib {
+
+ // Define this in your own namespace.
+ namespace gsl = ::gsl_lite;
+
+ // `span<T[, Extent]>`: contiguous range with bounds checks
+ double mean( gsl::span<double const> values )
+ {
+ // `gsl_Expects( cond )`: precondition check
+ gsl_Expects( !values.empty() );
+
+ double sum = std::accumulate( values.begin(), values.end(), 0. );
+
+ // `narrow_failfast<T>( u )`: checked numeric cast
+ double num = gsl::narrow_failfast<double>( std::ssize( values ) );
+
+ return sum / num;
+ }
+
+ class Resource
+ {
+ ...
+ public:
+ Resource( std::size_t size );
+ };
+
+ // Type-encoded precondition with `not_null<P>`
+ void consumeResource( gsl::not_null<std::unique_ptr<Resource>> resource );
+
+ // Type-encoded postcondition with `not_null<P>`
+ gsl::not_null<std::unique_ptr<Resource>> acquireResource( std::size_t size )
+ {
+ // A flavor of `make_unique<T>()` which returns `not_null<std::unique_ptr<T>>`
+ return gsl::make_unique<Resource>( size );
+ }
+
+} // namespace my_lib
+```
+
+
+## In a nutshell
+
+*gsl-lite* strives to implement the [Guidelines Support Library specification](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-gsl) of the C++ Core Guidelines
+maintained by the [Standard C++ Foundation](https://isocpp.org/).
+The library is originally based on [Microsoft GSL](https://github.com/microsoft/gsl) and was adapted for C++98, C++03. It also works when compiled as C++11, C++14, C++17, C++20, or C++23.
+
+*gsl-lite* does not interfere with Microsoft GSL since both libraries live in different namespaces (`gsl_lite` vs. `gsl`).
+
+*gsl-lite* recognizes when it is compiled for the CUDA platform and decorates some functions with `__host__` and `__device__` accordingly.
+
+
+## License
+
+*gsl-lite* uses the [MIT](LICENSE) license.
+
+
+## Dependencies
+
+*gsl-lite* has no dependencies other than the [C++ standard library](http://en.cppreference.com/w/cpp/header).
+
+
+## Installation and use
+
+The recommended way to consume *gsl-lite* in your CMake project is to use `find_package()` to locate the package `gsl-lite`
+and `target_link_libraries()` to link to the imported target `gsl-lite::gsl-lite`:
+
+```cmake
+cmake_minimum_required( VERSION 3.20 FATAL_ERROR )
+
+project( my-program LANGUAGES CXX )
+
+find_package( gsl-lite 1.0 REQUIRED )
+
+add_executable( my-program main.cpp )
+target_compile_features( my-program PRIVATE cxx_std_17 )
+target_link_libraries( my-program PRIVATE gsl-lite::gsl-lite )
+```
+
+*gsl-lite* is available via [Vcpkg](https://vcpkg.io/en/package/gsl-lite), [Conan](https://conan.io/center/recipes/gsl-lite),
+and possibly other package managers. It may also be obtained with [CPM](https://github.com/cpm-cmake/CPM.cmake):
+```cmake
+CPMAddPackage( NAME gsl-lite VERSION 1.0.1 GITHUB_REPOSITORY gsl-lite/gsl-lite )
+```
+See the directories [example/with-CPM](https://github.com/gsl-lite/gsl-lite/tree/master/example/with-CPM) and
+[example/with-Vcpkg](https://github.com/gsl-lite/gsl-lite/tree/master/example/with-Vcpkg) for example projects
+that use CPM and Vcpkg, respectively, to obtain *gsl-lite*.
+
+Once the build system is set up, include the `<gsl-lite/gsl-lite.hpp>` header file to use *gsl-lite*:
+
+```c++
+// main.cpp
+
+#include <iostream>
+
+#include <gsl-lite/gsl-lite.hpp>
+
+void printCmdArgs( gsl_lite::span<gsl_lite::zstring const> cmdArgs )
+{
+ gsl_Expects( !cmdArgs.empty() );
+
+ auto argsWithoutExeName = cmdArgs.subspan( 1 );
+ for ( auto arg : argsWithoutExeName )
+ {
+ std::cout << arg << "\n";
+ }
+}
+
+int main( int argc, char* argv[] )
+{
+ auto numArgs = gsl_lite::narrow_failfast<std::size_t>( argc );
+ auto cmdArgs = gsl_lite::span( argv, numArgs );
+ printCmdArgs( cmdArgs );
+}
+```
+
+
+## Why *gsl-lite*?
+
+*gsl-lite* is different from [Microsoft GSL](https://github.com/microsoft/gsl), the default implementation of the
+[C++ Core Guidelines support library (GSL)](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines), in the following ways:
+
+- *gsl-lite* maintains support for older versions of C++ (C++98, C++03, C++11) and older compilers.
+ (see: [Reported to work with](#reported-to-work-with))
+- *gsl-lite* supports [CUDA](https://developer.nvidia.com/cuda-toolkit), and many of its features can be used in CUDA kernel code.
+- [Contract and assertion checks](doc/Reference.md#contract-and-assertion-checks) are more fine-grained, and runtime enforcement is
+ [configurable](doc/Reference.md#contract-checking-configuration-macros).
+- In *gsl-lite*, `not_null<P>` retains the copyability and movability of `P` and therefore may have a [*moved-from state*](doc/Reference.md#nullability-and-the-moved-from-state),
+ which Microsoft GSL [expressly disallows](https://github.com/microsoft/GSL/issues/1022#issuecomment-1022713632).
+ As a consequence, `not_null<std::unique_ptr<T>>` is movable in *gsl-lite* but not in Microsoft GSL.
+- *gsl-lite* defines [feature testing macros](doc/Reference.md#feature-checking-macros) and [polyfills](doc/Reference.md#polyfills) useful for targeting multiple versions of C++.
+- *gsl-lite* comes as a single-header library.
+
+
+## Features
+
+See the [reference documentation](doc/Reference.md) for a detailed explanation of the features provided by *gsl-lite*, and
+Section&nbsp;[GSL: Guidelines support library](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-gsl) of the C++ Core Guidelines
+for the specification of the Guidelines support library.
+
+
+Feature \\ library | GSL spec | MS GSL | *gsl&#8209;lite* | Notes |
+------------------------------------------------------------------------|:-----------:|:-------------:|:-------------------:|:-------|
+[**Views:**](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslview-views) | &nbsp; | &nbsp; | &nbsp; | &nbsp; |
+[`owner<>`](doc/Reference.md#ownerp-c11-and-higher) | ✓ | ✓ | ✓¹¹ | Annotate a raw pointer that carries ownership |
+[`not_null<>`](doc/Reference.md#not_nullp) | ✓ | ✓ | ✓ | Annotate a (smart) pointer that must not be `nullptr`; enforces non-nullability at runtime<br>(cf. `strict_not_null<>` in Microsoft GSL) |
+[`not_null_ic<>`](doc/Reference.md#not_null_icp) | - | ✓ | ✓ | Like `not_null<>` but allows implicit construction from nullable pointers<br>(cf. `not_null<>` in Microsoft GSL) |
+[`make_unique<>()`](doc/Reference.md#not_nullp) | - | - | ✓¹¹ | Like [`std::make_unique<T>()`](https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) but returns `not_null<std::unique_ptr<T>>` |
+[`make_shared<>()`](doc/Reference.md#not_nullp) | - | - | ✓¹¹ | Like [`std::make_shared<T>()`](https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared) but returns `not_null<std::shared_ptr<T>>` |
+[`span<>`](doc/Reference.md#safe-contiguous-ranges) | ✓ | ✓ | ✓ | Like [`std::span<>`](https://en.cppreference.com/w/cpp/container/span) but with bounds-checking |
+[`zstring`<br>`czstring`](doc/Reference.md#string-type-aliases) | ✓ | ✓ | ✓ | Aliases for `char *` and `char const *` to be used for 0-terminated strings (C-style strings) |
+[`wzstring`<br>`wczstring`](doc/Reference.md#string-type-aliases) | - | ✓ | ✓ | Aliases for `wchar_t *` and `wchar_t const *` to be used for 0-terminated strings (C-style strings) |
+[**Assertions:**](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslassert-assertions) | &nbsp; | &nbsp; | &nbsp; | &nbsp;|
+[`Expects()`](doc/Reference.md#contract-and-assertion-checks) | ✓ | ✓ | (✓) | Checks precondition at runtime<br>(only defined in [GSL compatibility mode](doc/Reference.md#gsl_feature_gsl_compatibility_mode0)) |
+[`Ensures()`](doc/Reference.md#contract-and-assertion-checks) | ✓ | ✓ | (✓) | Checks precondition at runtime<br>(only defined in [GSL compatibility mode](doc/Reference.md#gsl_feature_gsl_compatibility_mode0)) |
+[`gsl_Expects()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks precondition at runtime |
+[`gsl_ExpectsDebug()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks precondition at runtime<br>unless [`NDEBUG`](https://en.cppreference.com/w/cpp/error/assert) is defined |
+[`gsl_ExpectsAudit()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks precondition at runtime<br>if [audit mode](doc/Reference.md#runtime-enforcement) is enabled |
+[`gsl_Ensures()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks postcondition at runtime |
+[`gsl_EnsuresDebug()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks postcondition at runtime<br>unless [`NDEBUG`](https://en.cppreference.com/w/cpp/error/assert) is defined |
+[`gsl_EnsuresAudit()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks postcondition at runtime<br>if [audit mode](doc/Reference.md#runtime-enforcement) is enabled |
+[`gsl_Assert()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks invariant at runtime |
+[`gsl_AssertDebug()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks invariant at runtime<br>unless [`NDEBUG`](https://en.cppreference.com/w/cpp/error/assert) is defined |
+[`gsl_AssertAudit()`](doc/Reference.md#contract-and-assertion-checks) | - | - | ✓ | Checks invariant at runtime<br>if [audit mode](doc/Reference.md#runtime-enforcement) is enabled |
+[**Utilities:**](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslutil-utilities) | &nbsp; | &nbsp; | &nbsp; | &nbsp; |
+[`finally()`](doc/Reference.md#ad-hoc-resource-management-c11-and-higher) | ✓ | ✓ | ✓¹¹ | Returns an object that executes a given action in its destructor; use for ad hoc resource cleanup |
+[`on_return()`](doc/Reference.md#ad-hoc-resource-management-c11-and-higher) | - | - | (✓¹¹) | Creates an object that executes a given action in its destructor if no exception occurred<br>([opt-in](doc/Reference.md#gsl_feature_experimental_return_guard0) feature) |
+[`on_error()`](doc/Reference.md#ad-hoc-resource-management-c11-and-higher) | - | - | (✓¹¹) | Creates an object that executes a given action in its destructor if an exception was thrown<br>([opt-in](doc/Reference.md#gsl_feature_experimental_return_guard0) feature) |
+[`at()`](doc/Reference.md#bounds-checked-element-access) | ✓ | ✓ | ✓ | Bounds-checked element access for C-style arrays and containers with random access |
+[`index`](doc/Reference.md#integer-type-aliases) | ✓ | ✓ | ✓ | Signed integer type for indexes and subscripts |
+[`dim`](doc/Reference.md#integer-type-aliases) | - | - | ✓ | Signed integer type for sizes |
+[`stride`](doc/Reference.md#integer-type-aliases) | - | - | ✓ | Signed integer type for index strides |
+[`diff`](doc/Reference.md#integer-type-aliases) | - | - | ✓ | Signed integer type for index differences |
+[`narrow_cast<>()`](doc/Reference.md#narrow_castt-u-) | ✓ | ✓ | ✓ | Narrowing cast which tolerates lossy conversions; equivalent to `static_cast<>()` |
+[`narrow<>()`](doc/Reference.md#narrowt-u-) | ✓ | ✓ | ✓ | Checked narrowing cast; throws `narrowing_error` if cast is lossy |
+[`narrow_failfast<>()`](doc/Reference.md#narrow_failfastt-u-) | - | - | ✓ | Checked narrowing cast; fails assertion check if cast is lossy |
+
+¹¹: C++11 or newer required
+
+
+## Migration guide
+
+Starting with v1.0, *gsl-lite* lives in the single header file `<gsl-lite/gsl-lite.hpp>`, and all its symbols reside in namespace
+`gsl_lite`. By default, *gsl-lite* no longer defines a namespace `gsl` or the unprefixed `Expects()` and `Ensures()` macros for
+precondition and postcondition checking.
+
+This change enables coexistence with [Microsoft GSL](https://github.com/microsoft/GSL) ([#194](https://github.com/gsl-lite/gsl-lite/issues/194)).
+
+### Adapting your code
+
+If you are migrating from *gsl-lite* v0.\*, adapt your code by referencing namespace `gsl_lite` rather than namespace `gsl`, and by
+using the prefixed macros `gsl_Expects()` and `gsl_Ensures()` rather than the unprefixed macros `Expects()` and `Ensures()` for
+precondition and postcondition checking.
+
+Note that *gsl-lite* v1 also changed the defaults for many of *gsl-lite*'s configuration options. See the
+[v1.0.0 release notes](https://github.com/gsl-lite/gsl-lite/releases/tag/v1.0.0) for a comprehensive list of changes.
+This should not affect you if you had already opted in to version-1 defaults by setting `gsl_CONFIG_DEFAULTS_VERSION=1`
+or by linking to the `gsl::gsl-lite-v1` target in CMake.
+
+To reduce the pervasiveness of required changes, it can be useful to define a namespace alias inside your own namespace:
+
+```c++
+// my-lib.hpp
+
+#include <gsl-lite/gsl-lite.hpp> // instead of <gsl/gsl-lite.hpp>
+
+namespace my_lib {
+
+ namespace gsl = ::gsl_lite; // convenience alias
+
+ inline double median( gsl::span<double const> elements )
+ {
+ gsl_Expects( !elements.empty() ); // instead of Expects()
+ ...
+ }
+
+} // namespace my_lib
+```
+
+### Using the GSL compatibility mode
+
+To minimize the impact of the breaking changes, *gsl-lite* introduces an optional *GSL compatibility mode* controlled by the
+new configuration switch [`gsl_FEATURE_GSL_COMPATIBILITY_MODE`](doc/Reference.md#feature-selection-macros), which is is disabled
+by default and can be enabled by defining `gsl_FEATURE_GSL_COMPATIBILITY_MODE=1`.
+
+If the GSL compatibility mode is enabled, *gsl-lite* additionally makes the following global definitions:
+```c++
+namespace gsl = ::gsl_lite;
+#define Expects( x ) gsl_Expects( x )
+#define Ensures( x ) gsl_Ensures( x )
+```
+
+The GSL compatibility mode precludes the use of *gsl-lite* and Microsoft GSL in the same translation unit. Therefore, **do not use
+the GSL compatibility mode when using *gsl-lite* in a public header file of a library.** (See notes on
+[using *gsl-lite* in libraries](#using-gsl-lite-in-libraries) below.)
+
+The GSL compatibility mode causes no link-time interference between *gsl-lite* and as Microsoft GSL. Both libraries may be used in
+the same project as long as no translation unit includes both at the same time.
+
+The legacy header file `<gsl/gsl-lite.hpp>` now forwards to `<gsl-lite/gsl-lite.hpp>` and implicitly enables the GSL compatibility mode.
+When the legacy header is included, it emits a warning message that urges to either migrate to header `<gsl-lite/gsl-lite.hpp>`,
+namespace `gsl_lite` and the prefixed contract checking macros `gsl_Expects()` and `gsl_Ensures()`, or to explicitly request GSL
+compatibility by defining `gsl_FEATURE_GSL_COMPATIBILITY_MODE=1`.
+
+
+## Using *gsl-lite* in libraries
+
+Many features of *gsl-lite* are very useful for defining library interfaces, for instance spans, contract checks, or `not_null<>`.
+
+*gsl-lite* can coexist with Microsoft GSL. However, the GSL compatibility mode of *gsl-lite* may cause interference with Microsoft GSL.
+Also, *gsl-lite* is customizable through a large number of configuration options and switches. These configuration macros may affect the API and
+ABI of *gsl-lite* in ways that renders it incompatible with other code. How *gsl-lite* is configured should be the prerogative of the consumer,
+not the author, of a library.
+
+Therefore, when using *gsl-lite* in a library, please mind the following suggestions:
+
+- Do not define, or rely on, any of *gsl-lite*'s configuration options or switches when using *gsl-lite* in a library.
+- In particular, do not enable the GSL compatibility mode.
+- Do not use the legacy header file `<gsl/gsl-lite.hpp>`, which implicitly enables the GSL compatibility mode; use the header `<gsl-lite/gsl-lite.hpp>` instead.
+- Use namespace `gsl_lite` rather than namespace `gsl`; if desired, define a `namespace gsl = ::gsl_lite;` alias in your own namespace.
+- Use the prefixed contract checking macros `gsl_Expects()` and `gsl_Ensures()` rather than the unprefixed macros `Expects()` and `Ensures()`.
+
+
+## Reported to work with
+
+The table below mentions the compiler versions and platforms *gsl-lite* is reported to work with.
+
+Compiler | OS | Platforms | Versions | CI |
+--------------------:|:----------------|-----------|------------------:|----|
+GCC | Linux | x64 | 4.7 and newer | [9, 10, 11, 12, 13, 14](https://dev.azure.com/gsl-lite/gsl-lite/_build?definitionId=1) |
+GCC (MinGW) | Windows | x86, x64 | 4.8.4 and newer | |
+GCC (DJGPP) | DOSBox, FreeDOS | x86 | 7.2 | |
+GCC | MacOS | x64 | 6 and newer | [11, 12, 13, 14](https://dev.azure.com/gsl-lite/gsl-lite/_build?definitionId=1) |
+Clang | Linux | x64 | 3.5 and newer | [11, 12, 13, 14, 15, 16, 17, 18, 19](https://dev.azure.com/gsl-lite/gsl-lite/_build?definitionId=1) |
+Clang with libstdc++ | Linux | x64 | 11 and newer | [19](https://dev.azure.com/gsl-lite/gsl-lite/_build?definitionId=1) |
+Clang | Windows | x64 | version shipped with VS | VS [2019, 2022](https://dev.azure.com/gsl-lite/gsl-lite/_build?definitionId=1) |
+MSVC (Visual Studio) | Windows | x86, x64 | VS 2010 and newer | VS [2010, 2012, 2013, 2015, 2017](https://ci.appveyor.com/project/gsl-lite/gsl-lite), [2019, 2022](https://dev.azure.com/gsl-lite/gsl-lite/_build?definitionId=1) |
+AppleClang (Xcode) | MacOS | x64 | 7.3 and newer | [14, 15, 16](https://dev.azure.com/gsl-lite/gsl-lite/_build?definitionId=1) |
+NVCC (CUDA Toolkit) | Linux, Windows | x64 | 10.2 and newer | [12.8](https://dev.azure.com/gsl-lite/gsl-lite/_build?definitionId=1) |
+ARMCC | | ARM | 5 and newer | |
+
+
+## Version semantics
+
+*gsl-lite* follows [Semantic Versioning](https://semver.org/) guidelines. We maintain [API](https://en.wikipedia.org/wiki/Application_programming_interface) and
+[ABI](https://en.wikipedia.org/wiki/Application_binary_interface) compatibility and avoid breaking changes in minor and patch releases.
+
+Development of *gsl-lite* happens in the `master` branch. Versioning semantics apply only to tagged releases: there is no stability guarantee between individual
+commits in the `master` branch, that is, anything added since the last tagged release may be renamed, removed, or have the semantics changed without further notice.
+
+A minor-version release will be compatible (in both ABI and API) with the previous minor-version release. Thus, once a change is released, it becomes part of the API.
+
+Some of the [configuration options](doc/Reference.md#configuration-options-and-switches) may affect the API and ABI of *gsl-lite*.
+
+
+## Contributing
+
+Contributions to *gsl-lite* through [pull requests](https://github.com/gsl-lite/gsl-lite/pulls) or [issues](https://github.com/gsl-lite/gsl-lite/issues) are welcome.
+
+*gsl-lite* comes with a test suite that uses an included, slightly modified copy of the [*lest* test framework](https://github.com/martinmoene/lest).
+To build *gsl-lite*'s test suite, enable the CMake build option `GSL_LITE_OPT_BUILD_TESTS` when configuring the project.
diff --git a/thirdparty/gsl-lite/_config.yml b/thirdparty/gsl-lite/_config.yml
new file mode 100644
index 000000000..e0147566c
--- /dev/null
+++ b/thirdparty/gsl-lite/_config.yml
@@ -0,0 +1,6 @@
+description: ISO C++ Core Guidelines Library implementation for C++98, C++11, and later
+remote_theme: jekyll/minima@0b7ca6b
+plugins:
+ - jekyll-remote-theme
+minima:
+ skin: auto
diff --git a/thirdparty/gsl-lite/_includes/footer.html b/thirdparty/gsl-lite/_includes/footer.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/thirdparty/gsl-lite/_includes/footer.html
diff --git a/thirdparty/gsl-lite/_includes/nav-items.html b/thirdparty/gsl-lite/_includes/nav-items.html
new file mode 100644
index 000000000..30ee89f8f
--- /dev/null
+++ b/thirdparty/gsl-lite/_includes/nav-items.html
@@ -0,0 +1,4 @@
+<div class="nav-items">
+ <a class="nav-item" href="https://gsl-lite.github.io/gsl-lite/doc/Reference.html">Reference documentation</a>
+ <a class="nav-item" href="https://github.com/gsl-lite/gsl-lite">GitHub repository</a>
+</div>
diff --git a/thirdparty/gsl-lite/_layouts/home.html b/thirdparty/gsl-lite/_layouts/home.html
new file mode 100644
index 000000000..c65a9b020
--- /dev/null
+++ b/thirdparty/gsl-lite/_layouts/home.html
@@ -0,0 +1,64 @@
+---
+layout: base
+---
+
+<div class="home">
+
+ {{ content }}
+
+
+ {% if site.paginate %}
+ {% assign posts = paginator.posts %}
+ {% else %}
+ {% assign posts = site.posts %}
+ {% endif %}
+
+
+ {%- if posts.size > 0 -%}
+ {%- if page.list_title -%}
+ <h2 class="post-list-heading">{{ page.list_title }}</h2>
+ {%- endif -%}
+ <ul class="post-list">
+ {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
+ {%- for post in posts -%}
+ <li>
+ <span class="post-meta">{{ post.date | date: date_format }}</span>
+ <h3>
+ <a class="post-link" href="{{ post.url | relative_url }}">
+ {{ post.title | escape }}
+ </a>
+ </h3>
+ {%- if site.minima.show_excerpts -%}
+ {{ post.excerpt }}
+ {%- endif -%}
+ </li>
+ {%- endfor -%}
+ </ul>
+
+ {% if site.paginate %}
+ <div class="pager">
+ <ul class="pagination">
+ {%- if paginator.previous_page %}
+ <li>
+ <a href="{{ paginator.previous_page_path | relative_url }}" class="previous-page" title="Go to Page {{ paginator.previous_page }}">
+ {{ paginator.previous_page }}
+ </a>
+ </li>
+ {%- else %}
+ <li><div class="pager-edge">•</div></li>
+ {%- endif %}
+ <li><div class="current-page">{{ paginator.page }}</div></li>
+ {%- if paginator.next_page %}
+ <li>
+ <a href="{{ paginator.next_page_path | relative_url }}" class="next-page" title="Go to Page {{ paginator.next_page }}">
+ {{ paginator.next_page }}
+ </a>
+ </li>
+ {%- else %}
+ <li><div class="pager-edge">•</div></li>
+ {%- endif %}
+ </ul>
+ </div>
+ {%- endif %}
+ {%- endif -%}
+</div>
diff --git a/thirdparty/gsl-lite/_layouts/page.html b/thirdparty/gsl-lite/_layouts/page.html
new file mode 100644
index 000000000..43851a089
--- /dev/null
+++ b/thirdparty/gsl-lite/_layouts/page.html
@@ -0,0 +1,10 @@
+---
+layout: base
+---
+<article class="post">
+
+ <div class="post-content">
+ {{ content }}
+ </div>
+
+</article>
diff --git a/thirdparty/gsl-lite/_sass/minima/custom-variables.scss b/thirdparty/gsl-lite/_sass/minima/custom-variables.scss
new file mode 100644
index 000000000..387f596b2
--- /dev/null
+++ b/thirdparty/gsl-lite/_sass/minima/custom-variables.scss
@@ -0,0 +1,7 @@
+$content-width: 900px;
+
+$on-palm: 600px;
+$on-laptop: 900px;
+
+$on-medium: $on-palm;
+$on-large: $on-laptop;
diff --git a/thirdparty/gsl-lite/appveyor.yml b/thirdparty/gsl-lite/appveyor.yml
new file mode 100644
index 000000000..109802dd7
--- /dev/null
+++ b/thirdparty/gsl-lite/appveyor.yml
@@ -0,0 +1,51 @@
+version: "{branch} #{build}"
+
+shallow_clone: true
+
+image:
+ #- Visual Studio 2019
+ - Visual Studio 2017
+ - Visual Studio 2015
+
+environment:
+ matrix:
+ # VS 2019 and newer are tested with Azure Pipelines
+ #- generator: "Visual Studio 16 2019"
+ - generator: "Visual Studio 15 2017"
+ - generator: "Visual Studio 14 2015"
+ - generator: "Visual Studio 12 2013"
+ - generator: "Visual Studio 11 2012"
+ - generator: "Visual Studio 10 2010"
+
+configuration:
+ - Debug
+ #- Release
+
+platform:
+ - Win32
+ - x64
+
+matrix:
+ fast_finish: false
+ exclude:
+ - image: Visual Studio 2017
+ generator: "Visual Studio 12 2013"
+ - image: Visual Studio 2017
+ generator: "Visual Studio 11 2012"
+ - image: Visual Studio 2017
+ generator: "Visual Studio 10 2010"
+ - image: Visual Studio 2015
+ generator: "Visual Studio 15 2017"
+ - image: Visual Studio 2015
+ generator: "Visual Studio 14 2015"
+
+before_build:
+ - mkdir build && cd build
+ - cmake -A %platform% -G "%generator%" -DGSL_LITE_OPT_BUILD_TESTS=ON -DGSL_LITE_OPT_BUILD_EXAMPLES=ON ..
+
+build_script:
+ #- cmake --build . --config %configuration% -- -verbosity:normal
+ - cmake --build . --config %configuration% -- -verbosity:minimal
+
+test_script:
+ - ctest --output-on-failure -C %configuration%
diff --git a/thirdparty/gsl-lite/azure-pipelines.yml b/thirdparty/gsl-lite/azure-pipelines.yml
new file mode 100644
index 000000000..5fd28243d
--- /dev/null
+++ b/thirdparty/gsl-lite/azure-pipelines.yml
@@ -0,0 +1,205 @@
+
+variables:
+ System.Debug: true
+
+trigger:
+- master
+- mr/*
+
+pr:
+- master
+
+resources:
+ repositories:
+ - repository: CImakeshift
+ type: github
+ name: mbeutel/CImakeshift
+ endpoint: gsl-lite
+
+jobs:
+- template: azure-pipelines/cmake.yml@CImakeshift
+ parameters:
+ cache: False
+ cmakeBuildConfigurations: [Debug]
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_TESTS=ON -DGSL_LITE_OPT_BUILD_EXAMPLES=ON'
+ cmakeTestArgs: '--exclude-regex cuda' # do not run CUDA tests
+
+ targets:
+
+ # put a set of representative (and slow) jobs first
+
+ - os: Linux
+ cxxCompiler: GCC
+ cxxCompilerVersions: [14]
+ cmakeBuildConfigurations: [Debug, RelWithDebInfo]
+ platforms: [x64]
+ tag: 'memcheck'
+ postSetupSteps:
+ - bash: |
+ sudo apt install valgrind
+ # suppress AVX/AVX2 paths because there are apparent false positives in glibc's AVX2-optimized memcmp routines
+ # (cf. https://sourceware.org/bugzilla/show_bug.cgi?id=22954, https://bugs.kde.org/show_bug.cgi?id=397083)
+ echo "##vso[task.setvariable variable=GLIBC_TUNABLES]glibc.cpu.hwcaps=-AVX2_Usable,-AVX_Usable,-AVX_Fast_Unaligned_Load"
+ displayName: 'Install Valgrind'
+ # Make Valgrind return a non-zero exit code when errors occur in order to make the job fail.
+ # Also, enforce DWARF version 4 because Valgrind cannot read DWARF version 5 yet (cf. https://bugs.kde.org/show_bug.cgi?id=452758).
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_TESTS=ON -DCMAKE_CXX_FLAGS="-gdwarf-4" -DMEMORYCHECK_COMMAND_OPTIONS="--error-exitcode=1 --leak-check=full"'
+ cmakeBuildArgs: '<cmakeBuildArgs> --target gsl-lite-v1-cpp20.t'
+ cmakeTestArgs: '<cmakeTestArgs> --test-action memcheck --tests-regex gsl-lite-v1-cpp20'
+
+ - os: Linux
+ cxxCompiler: GCC
+ cxxCompilerVersions: [14]
+ cmakeBuildConfigurations: [Debug, RelWithDebInfo]
+ cudaCompiler: NVCC
+ cudaCompilerVersions: [12_8]
+ platforms: [x64]
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_CUDA_TESTS=ON'
+
+ # CImakeshift doesn't currently support Clang-CUDA.
+ #- os: Linux
+ # cxxCompiler: Clang
+ # cxxCompilerVersions: [13]
+ # cmakeBuildConfigurations: [Debug, RelWithDebInfo]
+ # cudaCompiler: Clang
+ # cudaCompilerVersions: [13]
+ # platforms: [x64]
+ # cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_CUDA_TESTS=ON'
+
+ - os: Linux
+ cxxCompiler: Clang
+ cxxCompilerVersions: [19]
+ cmakeBuildConfigurations: [Debug, RelWithDebInfo]
+ platforms: [x64]
+ tag: 'memcheck'
+ postSetupSteps:
+ - bash: |
+ sudo apt install valgrind
+ # suppress AVX/AVX2 paths because there are apparent false positives in glibc's AVX2-optimized memcmp routines
+ # (cf. https://sourceware.org/bugzilla/show_bug.cgi?id=22954, https://bugs.kde.org/show_bug.cgi?id=397083)
+ echo "##vso[task.setvariable variable=GLIBC_TUNABLES]glibc.cpu.hwcaps=-AVX2_Usable,-AVX_Usable,-AVX_Fast_Unaligned_Load"
+ displayName: 'Install Valgrind'
+ # Make Valgrind return a non-zero exit code when errors occur in order to make the job fail.
+ # Also, enforce DWARF version 4 because Valgrind cannot read DWARF version 5 yet (cf. https://bugs.kde.org/show_bug.cgi?id=452758).
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_TESTS=ON -DCMAKE_CXX_FLAGS="-gdwarf-4" -DMEMORYCHECK_COMMAND_OPTIONS="--error-exitcode=1 --leak-check=full"'
+ cmakeBuildArgs: '<cmakeBuildArgs> --target gsl-lite-v0-cpp20.t gsl-lite-v1-cpp20.t'
+ cmakeTestArgs: '<cmakeTestArgs> --test-action memcheck --tests-regex gsl-lite-v[0-1]-cpp20'
+
+ - os: Windows
+ cxxCompiler: MSVC
+ cxxCompilerVersions: [VS2022]
+ cmakeGenerator: 'MSBuild' # required for CppCoreCheck
+ cmakeBuildConfigurations: [Debug, RelWithDebInfo]
+ platforms: [x86, x64]
+ cmakeConfigArgs: '<cmakeConfigArgs> -DGSL_LITE_OPT_BUILD_STATIC_ANALYSIS_DEMOS=ON'
+ cmakeBuildArgs: '<cmakeBuildArgs> --target gsl-lite-v1-cpplatest.t gsl-lite-v1-cpplatest-CppCoreCheck'
+ cmakeTestArgs: '<cmakeTestArgs> --tests-regex gsl-lite-v1-cpplatest'
+
+ - os: Windows
+ cxxCompiler: Clang
+ cxxCompilerVersions: [VS2019, VS2022]
+ cmakeBuildConfigurations: [Debug, RelWithDebInfo]
+ platforms: [x86, x64]
+ cmakeBuildArgs: '<cmakeBuildArgs> --target gsl-lite-v1-cpplatest.t'
+ cmakeTestArgs: '<cmakeTestArgs> --tests-regex gsl-lite-v1-cpplatest'
+
+ - os: Windows
+ cxxCompiler: MSVC
+ cxxCompilerVersions: [VS2022]
+ cudaCompiler: NVCC
+ cudaCompilerVersions: [12_8]
+ cmakeBuildConfigurations: [Debug, RelWithDebInfo]
+ platforms: [x64]
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_CUDA_TESTS=ON'
+
+ - os: MacOS
+ cxxCompiler: AppleClang
+ cxxCompilerVersions: [16]
+ cmakeBuildConfigurations: [Debug, RelWithDebInfo]
+ platforms: [x64]
+ cmakeBuildArgs: '<cmakeBuildArgs> --target gsl-lite-v1-cpp17.t'
+ cmakeTestArgs: '<cmakeTestArgs> --tests-regex gsl-lite-v1-cpp17'
+
+ # GCC 4.7, 4.8, 4.9, 5, and 6 are tested with Travis
+ #- os: Linux
+ # cxxCompiler: GCC
+ # cxxCompilerVersions: [5]
+ # platforms: [x64]
+
+ - os: Linux
+ cxxCompiler: GCC
+ cxxCompilerVersions: [9, 10, 11, 12, 13]
+ platforms: [x64]
+
+ - os: Linux
+ cxxCompiler: GCC
+ cxxCompilerVersions: [14]
+ cxxStandardLibraryDebugMode: true
+ cxxSanitizers: [AddressSanitizer, UndefinedBehaviorSanitizer]
+ platforms: [x64]
+ tag: 'sanitize'
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_TESTS=ON'
+ cmakeBuildArgs: '<cmakeBuildArgs> --target gsl-lite-v0-cpp17.t gsl-lite-v1-cpp17.t'
+ cmakeTestArgs: '<cmakeTestArgs> --tests-regex gsl-lite-v[0-1]-cpp17'
+
+ # Clang 3.5, 3.6, 3.7, 3.8, and 3.9, 4, and 5 are tested with Travis
+ #- os: Linux
+ # cxxCompiler: Clang
+ # cxxCompilerVersions: [4]
+ # platforms: [x64]
+
+ - os: Linux
+ cxxCompiler: Clang
+ cxxCompilerVersions: [11, 12, 13, 14, 15, 16, 17, 18]
+ platforms: [x64]
+
+ - os: Linux
+ cxxCompiler: Clang
+ cxxCompilerVersions: [19]
+ cxxStandardLibraryDebugMode: true
+ cxxSanitizers: [AddressSanitizer, UndefinedBehaviorSanitizer, ImplicitIntegerArithmeticValueChange]
+ platforms: [x64]
+ tag: 'sanitize'
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_TESTS=ON'
+ cmakeBuildArgs: '<cmakeBuildArgs> --target gsl-lite-v0-cpp17.t gsl-lite-v1-cpp17.t'
+ cmakeTestArgs: '<cmakeTestArgs> --tests-regex gsl-lite-v[0-1]-cpp17'
+
+ - os: Linux
+ cxxCompiler: Clang
+ cxxCompilerVersions: [19]
+ cxxStandardLibrary: libstdc++
+ platforms: [x64]
+ tag: 'libstdc++'
+
+ - os: Linux
+ cxxCompiler: GCC
+ cxxCompilerVersions: [11]
+ cudaCompiler: NVCC
+ cudaCompilerVersions: [12_6]
+ platforms: [x64]
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_CUDA_TESTS=ON'
+
+ # VS 2010, 2012, 2013, 2015, and 2017 are tested with AppVeyor
+
+ - os: Windows
+ cxxCompiler: MSVC
+ cxxCompilerVersions: [VS2019]
+ cudaCompiler: NVCC
+ cudaCompilerVersions: [11_8, 12_1]
+ platforms: [x64]
+ cmakeConfigArgs: '-DGSL_LITE_OPT_BUILD_CUDA_TESTS=ON'
+
+ - os: Windows
+ cxxCompiler: MSVC
+ cxxCompilerVersions: [VS2019, VS2022]
+ platforms: [x86, x64]
+
+ - os: MacOS
+ cxxCompiler: GCC
+ cxxCompilerVersions: [11, 12, 13, 14]
+ platforms: [x64]
+
+ - os: MacOS
+ cxxCompiler: AppleClang
+ cxxCompilerVersions: [14, 15, 16]
+ platforms: [x64]
diff --git a/thirdparty/gsl-lite/cmake/CommonPresets.json b/thirdparty/gsl-lite/cmake/CommonPresets.json
new file mode 100644
index 000000000..9e3c5314a
--- /dev/null
+++ b/thirdparty/gsl-lite/cmake/CommonPresets.json
@@ -0,0 +1,245 @@
+{
+ // Collection of generally useful CMake configuration presets.
+ // Version 0.1.0β
+ // The contents of this file are in the public domain.
+ // (Moritz Beutel, 2025)
+ "version": 7,
+ "configurePresets": [
+ {
+ "name": "use Vcpkg",
+ "hidden": true,
+ "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
+ },
+
+ {
+ "name": "compiler presets",
+ "hidden": true,
+ "environment": {
+ "_CFLAGS": "$penv{CFLAGS} $env{_PRESET_CFLAGS} $env{_USE_PRESET_ASAN} $env{_USE_PRESET_UBSAN} $env{_USE_PRESET_TSAN} $env{_USE_PRESET_STDLIB}",
+ "_CXXFLAGS": "$penv{CXXFLAGS} $env{_PRESET_CXXFLAGS} $env{_USE_PRESET_ASAN} $env{_USE_PRESET_UBSAN} $env{_USE_PRESET_TSAN} $env{_USE_PRESET_STDLIB} $env{_USE_PRESET_DEBUGCHECKS}",
+ "_CUDAFLAGS": "$penv{CUDAFLAGS} $env{_PRESET_CUDAFLAGS} $env{_CUDA_USE_PRESET_STDLIB} $env{_USE_PRESET_DEBUGCHECKS}",
+ "CFLAGS": "$env{_CFLAGS}",
+ "CXXFLAGS": "$env{_CXXFLAGS}",
+ "CUDAFLAGS": "$env{_CUDAFLAGS}",
+ "MY_COMPILE_OPTIONS": "$env{_USE_PRESET_WARN};$env{_USE_PRESET_WARNERR}"
+ }
+ },
+
+ {
+ // "CI" covers AppVeyor, GitHub Actions, GitLab CI, Travis CI, and possibly others.
+ "name": "CI",
+ "hidden": true,
+ "condition": {
+ "type": "notEquals",
+ "lhs": "$env{CI}$env{CIRCLECI}$env{TF_BUILD}",
+ "rhs": ""
+ }
+ },
+
+ {
+ // For MSVC, enable UTF-8 source file encoding, the highest warning level, and some additional warnings:
+ // W44062: enumerator 'identifier' in a switch of enum 'enumeration' is not handled
+ // W44242: 'identifier': conversion from 'type1' to 'type2', possible loss of data
+ // W44254: 'operator': conversion from 'type1' to 'type2', possible loss of data
+ // W44265: 'class': class has virtual functions, but destructor is not virtual
+ "name": "MSVC presets",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_PRESET_CFLAGS": "/utf-8",
+ "_PRESET_CXXFLAGS": "/utf-8",
+ "_PRESET_CUDAFLAGS": "-Xcompiler=/utf-8",
+ "_PRESET_WARN": "$<$<COMPILE_LANGUAGE:C,CXX>:/permissive-;/W4;/w44062;/w44242;/w44254;/w44265>$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/permissive-,/W4,/w44062,/w44242,/w44254,/w44265>",
+ "_PRESET_WARNERR": "$<$<COMPILE_LANGUAGE:C,CXX>:/WX>$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/WX>",
+ "_PRESET_ASAN": "/fsanitize=address",
+ "_PRESET_UBSAN": "/fsanitize=undefined", // not currently supported
+ "_PRESET_TSAN": "/fsanitize=thread", // not currently supported
+ "_PRESET_DEBUGCHECKS": "/D_ITERATOR_DEBUG_LEVEL=1"
+ },
+ "condition": {
+ "type": "equals",
+ "lhs": "${hostSystemName}",
+ "rhs": "Windows"
+ }
+ },
+ {
+ // For clang-cl, use the same general presets as for MSVC with some minor changes.
+ "name": "clang-cl presets",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_PRESET_CFLAGS": "/utf-8",
+ "_PRESET_CXXFLAGS": "/utf-8",
+ "_PRESET_CUDAFLAGS": "-Xcompiler=/utf-8",
+ "_PRESET_WARN": "$<$<COMPILE_LANGUAGE:C,CXX>:/permissive-;/W4;/w44062;/w44242;/w44254;/w44265>$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/permissive-,/W4,/w44062,/w44242,/w44254,/w44265>",
+ "_PRESET_WARNERR": "$<$<COMPILE_LANGUAGE:C,CXX>:/WX>$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/WX>",
+ "_PRESET_ASAN": "/fsanitize=address",
+ "_PRESET_UBSAN": "-fsanitize=undefined -fsanitize-trap=undefined -fsanitize=implicit-integer-arithmetic-value-change",
+ "_PRESET_TSAN": "-fsanitize=thread", // not currently supported
+ "_PRESET_DEBUGCHECKS": "/D_ITERATOR_DEBUG_LEVEL=1"
+ },
+ "condition": {
+ "type": "equals",
+ "lhs": "${hostSystemName}",
+ "rhs": "Windows"
+ }
+ },
+ {
+ // For GCC, enable the highest warning level and pedantic mode.
+ "name": "GCC presets",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_PRESET_CFLAGS": "",
+ "_PRESET_CXXFLAGS": "",
+ "_PRESET_CUDAFLAGS": "",
+ "_PRESET_WARN": "$<$<COMPILE_LANGUAGE:C,CXX>:-Wall;-Wextra;-pedantic>$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=-Wall,-Wextra,-pedantic>",
+ "_PRESET_WARNERR": "$<$<COMPILE_LANGUAGE:C,CXX>:-Werror>", // avoid -Werror for CUDA host compilers for now
+ "_PRESET_ASAN": "-fsanitize=address -fno-omit-frame-pointer",
+ "_PRESET_UBSAN": "-fsanitize=undefined -fno-omit-frame-pointer -fsanitize-undefined-trap-on-error",
+ "_PRESET_TSAN": "-fsanitize=thread",
+ "_PRESET_DEBUGCHECKS": "-D_GLIBCXX_DEBUG"
+ }
+ },
+ {
+ // For Clang, enable the highest warning level and pedantic mode.
+ "name": "Clang presets",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_PRESET_CFLAGS": "",
+ "_PRESET_CXXFLAGS": "",
+ "_PRESET_CUDAFLAGS": "",
+ "_PRESET_WARN": "$<$<COMPILE_LANGUAGE:C,CXX>:-Wall;-Wextra;-pedantic>$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=-Wall,-Wextra,-pedantic>",
+ "_PRESET_WARNERR": "$<$<COMPILE_LANGUAGE:C,CXX>:-Werror>", // avoid -Werror for CUDA host compilers for now
+ "_PRESET_ASAN": "-fsanitize=address -fno-omit-frame-pointer",
+ "_PRESET_UBSAN": "-fsanitize=undefined -fno-omit-frame-pointer -fsanitize-trap=undefined -fsanitize=implicit-integer-arithmetic-value-change",
+ "_PRESET_TSAN": "-fsanitize=thread",
+ // cf. https://libcxx.llvm.org/Hardening.html
+ "_PRESET_DEBUGCHECKS": "-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG"
+ }
+ },
+
+ {
+ "name": "ASan",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_USE_PRESET_ASAN": "$env{_PRESET_ASAN}"
+ }
+ },
+ {
+ "name": "UBSan",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_USE_PRESET_UBSAN": "$env{_PRESET_UBSAN}"
+ }
+ },
+ {
+ "name": "TSan",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_USE_PRESET_TSAN": "$env{_PRESET_TSAN}"
+ }
+ },
+ {
+ "name": "library debug checks",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_USE_PRESET_DEBUGCHECKS": "$env{_PRESET_DEBUGCHECKS} $env{_PRESET_DEBUGCHECKS2}"
+ }
+ },
+ {
+ "name": "high warning level",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_USE_PRESET_WARN": "$env{_PRESET_WARN}"
+ }
+ },
+ {
+ "name": "warnings as errors",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_USE_PRESET_WARNERR": "$env{_PRESET_WARNERR}"
+ }
+ },
+
+ {
+ "name": "libstdc++ for Clang",
+ "hidden": true,
+ "inherits": "compiler presets",
+ "environment": {
+ "_USE_PRESET_STDLIB": "-stdlib=libstdc++",
+ "_CUDA_USE_PRESET_STDLIB": "-Xcompiler=-stdlib=libstdc++",
+ "_PRESET_DEBUGCHECKS2": "-D_GLIBCXX_DEBUG"
+ }
+ },
+
+ {
+ "name": "force MSVC",
+ "hidden": true,
+ "inherits": "MSVC presets",
+ "environment": {
+ "CC": "cl",
+ "CXX": "cl"
+ },
+ "condition": {
+ "type": "equals",
+ "lhs": "${hostSystemName}",
+ "rhs": "Windows"
+ }
+ },
+ {
+ "name": "force clang-cl",
+ "hidden": true,
+ "inherits": "clang-cl presets",
+ "environment": {
+ "CC": "clang-cl",
+ "CXX": "clang-cl"
+ },
+ "condition": {
+ "type": "equals",
+ "lhs": "${hostSystemName}",
+ "rhs": "Windows"
+ }
+ },
+ {
+ "name": "force GCC",
+ "hidden": true,
+ "inherits": "GCC presets",
+ "environment": {
+ "CC": "gcc",
+ "CXX": "g++"
+ }
+ },
+ {
+ "name": "force Clang",
+ "hidden": true,
+ "inherits": "Clang presets",
+ "environment": {
+ "CC": "clang",
+ "CXX": "clang++"
+ }
+ }
+ ],
+ "buildPresets": [
+ ],
+ "testPresets": [
+ {
+ "name": "defaults",
+ "hidden": true,
+ "output": {
+ "outputOnFailure": true
+ },
+ "execution": {
+ "noTestsAction": "error",
+ "stopOnFailure": true
+ }
+ }
+ ]
+}
diff --git a/thirdparty/gsl-lite/cmake/InstallBasicPackageFiles.cmake b/thirdparty/gsl-lite/cmake/InstallBasicPackageFiles.cmake
new file mode 100644
index 000000000..077b95d5f
--- /dev/null
+++ b/thirdparty/gsl-lite/cmake/InstallBasicPackageFiles.cmake
@@ -0,0 +1,684 @@
+# SPDX-FileCopyrightText: 2012-2021 Istituto Italiano di Tecnologia (IIT)
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+InstallBasicPackageFiles
+------------------------
+
+A helper module to make your package easier to be found by other
+projects.
+
+
+.. command:: install_basic_package_files
+
+Create and install a basic version of cmake config files for your
+project::
+
+ install_basic_package_files(<Name>
+ COMPATIBILITY <compatibility>
+ [VERSION <version>]
+ [ARCH_INDEPENDENT]
+ [NO_EXPORT | EXPORT <export>] # (default = "EXPORT <Name>")
+ [NO_SET_AND_CHECK_MACRO]
+ [NO_CHECK_REQUIRED_COMPONENTS_MACRO]
+ [VARS_PREFIX <prefix>] # (default = "<Name>")
+ [EXPORT_DESTINATION <destination>]
+ [INSTALL_DESTINATION <destination>]
+ [NAMESPACE <namespace>] # (default = "<Name>::")
+ [EXTRA_PATH_VARS_SUFFIX path1 [path2 ...]]
+ [CONFIG_TEMPLATE <file>]
+ [UPPERCASE_FILENAMES | LOWERCASE_FILENAMES]
+ [DEPENDENCIES <dependency1> "<dependency2> [...]" ...]
+ [PRIVATE_DEPENDENCIES <dependency1> "<dependency2> [...]" ...]
+ [INCLUDE_FILE <file> | INCLUDE_CONTENT <content>]
+ [COMPONENT <component>] # (default = "<Name>")
+ )
+
+Depending on ``UPPERCASE_FILENAMES`` and ``LOWERCASE_FILENAMES``, this
+function generates 3 files:
+
+ - ``<Name>ConfigVersion.cmake`` or ``<name>-config-version.cmake``
+ - ``<Name>Config.cmake`` or ``<name>-config.cmake``
+ - ``<Name>Targets.cmake`` or ``<name>-targets.cmake``
+
+If neither ``UPPERCASE_FILENAMES`` nor ``LOWERCASE_FILENAMES`` is
+set, a file ``<Name>Config.cmake.in`` or
+``<name>-config.cmake.in`` is searched, and the convention
+is chosed according to the file found. If no file was found, the
+uppercase convention is used.
+
+The ``DEPENDENCIES`` argument can be used to set a list of dependencies
+that will be searched using the :cmake:command:`find_dependency` command
+from the :module:`CMakeFindDependencyMacro` module.
+Dependencies can be followed by any of the possible
+:cmake:command:`find_dependency` argument.
+In this case, all the arguments must be specified within double quotes (e.g.
+``"<dependency> 1.0.0 EXACT"``, or ``"<dependency> CONFIG"``).
+The ``PRIVATE_DEPENDENCIES`` argument is similar to ``DEPENDENCIES``, but
+these dependencies are included only when :variable:`BUILD_SHARED_LIBS` is
+``OFF``.
+If a libraries is declared ``STATIC``, ``OBJECT`` or ``INTERFACE``, and they
+link to some dependency, these should be added using the ``DEPENDENCIES``
+argument, since the ``PRIVATE_DEPENDENCIES`` argument would work only when
+:variable:`BUILD_SHARED_LIBS` is disabled.
+
+When using a custom template file, the ``@PACKAGE_DEPENDENCIES@``
+string is replaced with the code checking for the dependencies
+specified by these two argument.
+
+If the ``ARCH_INDEPENDENT`` option is enabled, the installed package version
+will be considered compatible even if it was built for a different
+architecture than the requested architecture.
+
+Each file is generated twice, one for the build directory and one for
+the installation directory. The ``INSTALL_DESTINATION`` argument can be
+passed to install the files in a location different from the default
+one (``${CMAKE_INSTALL_DATADIR}/cmake/${Name}`` if the ``ARCH_INDEPENDENT``
+option is enabled, ``${CMAKE_INSTALL_LIBDIR}/cmake/${Name}`` otherwise).
+The ``EXPORT_DESTINATION`` argument can be passed to
+generate the files in the build tree in a location different from the default
+one (``CMAKE_BINARY_DIR``). If this is a relative path, it is
+considered relative to the ``CMAKE_CURRENT_BINARY_DIR`` directory.
+
+The build directory is exported to the CMake user package registry if the
+build option ``CMAKE_EXPORT_PACKAGE_REGISTRY`` is set.
+
+The ``<Name>ConfigVersion.cmake`` file is generated using
+:cmake:command:`write_basic_package_version_file`. The ``VERSION``,
+``COMPATIBILITY``, and ``ARCH_INDEPENDENT``arguments are passed to this
+function.
+
+``VERSION`` shall be in the form ``<major>[.<minor>[.<patch>[.<tweak>]]]]``.
+If no ``VERSION`` is given, the ``PROJECT_VERSION`` variable is used.
+If this hasn’t been set, it errors out. The ``VERSION`` argument is also used
+to replace the ``@PACKAGE_VERSION@`` string in the configuration file.
+
+``COMPATIBILITY`` shall be any of the options accepted by the
+:cmake:command:`write_basic_package_version_file` command
+(``AnyNewerVersion``, ``SameMajorVersion``, ``SameMinorVersion`` [CMake 3.11],
+or ``ExactVersion``).
+These options are explained in :cmake:command:`write_basic_package_version_file`
+command documentation.
+If your project has more elaborate version matching rules, you will need to
+write your own custom ConfigVersion.cmake file instead of using this macro.
+
+The ``<Name>Config.cmake`` file is generated using
+:cmake:command:`configure_package_config_file`. The
+``NO_SET_AND_CHECK_MACRO``, ``NO_CHECK_REQUIRED_COMPONENTS_MACRO``, and
+arguments are passed to this function.
+
+By default :command:`install_basic_package_files` also generates the two helper
+macros ``set_and_check()`` and ``check_required_components()`` into the
+``<Name>Config.cmake`` file. ``set_and_check()`` should be used instead of the
+normal :cmake:command:`set()` command for setting directories and file locations.
+Additionally to setting the variable it also checks that the referenced file
+or directory actually exists and fails with a ``FATAL_ERROR`` otherwise.
+This makes sure that the created ``<Name>Config.cmake`` file does not contain
+wrong references.
+When using the ``NO_SET_AND_CHECK_MACRO, this macro is not generated into the
+``<Name>Config.cmake`` file.
+
+By default, :command:`install_basic_package_files` append a call to
+``check_required_components(<Name>)`` in ``<Name>Config.cmake`` file if the
+package supports components. This macro checks whether all requested,
+non-optional components have been found, and if this is not the case, sets the
+``<Name>_FOUND`` variable to ``FALSE``, so that the package is considered to
+be not found. It does that by testing the ``<Name>_<Component>_FOUND``
+variables for all requested required components. When using the
+``NO_CHECK_REQUIRED_COMPONENTS_MACRO`` option, this macro is not generated
+into the ``<Name>Config.cmake`` file.
+
+Finally, the files in the build and install directory are exactly the same.
+
+See the documentation of :module:`CMakePackageConfigHelpers` module for
+further information and references therein.
+
+If the ``CONFIG_TEMPLATE`` argument is passed, the specified file
+is used as template for generating the configuration file, otherwise
+this module expects to find a ``<Name>Config.cmake.in`` or
+``<name>-config.cmake.in`` file either in current source directory.
+If the file does not exist, a very basic file is created.
+
+A set of variables are checked and passed to
+:cmake:command:`configure_package_config_file` as ``PATH_VARS``. For each of the
+``SUFFIX`` considered, if one of the variables::
+
+ <VARS_PREFIX>_(BUILD|INSTALL)_<SUFFIX>
+ (BUILD|INSTALL)_<VARS_PREFIX>_<SUFFIX>
+
+is defined, the ``<VARS_PREFIX>_<SUFFIX>`` variable will be defined
+before configuring the package. In order to use that variable in the
+config file, you have to add a line::
+
+ set_and_check(<VARS_PREFIX>_<SUFFIX> \"@PACKAGE_<VARS_PREFIX>_<SUFFIX>@\")
+
+if the path must exist or just::
+
+ set(<VARS_PREFIX>_<SUFFIX> \"@PACKAGE_<VARS_PREFIX>_<SUFFIX>@\")
+
+if the path could be missing.
+
+These variable will have different values whether you are using the
+package from the build tree or from the install directory. Also these
+files will contain only relative paths, meaning that you can move the
+whole installation and the CMake files will still work.
+
+Default ``PATH_VARS`` suffixes are::
+
+ BINDIR BIN_DIR
+ SBINDIR SBIN_DIR
+ LIBEXECDIR LIBEXEC_DIR
+ SYSCONFDIR SYSCONF_DIR
+ SHAREDSTATEDIR SHAREDSTATE_DIR
+ LOCALSTATEDIR LOCALSTATE_DIR
+ LIBDIR LIB_DIR
+ INCLUDEDIR INCLUDE_DIR
+ OLDINCLUDEDIR OLDINCLUDE_DIR
+ DATAROOTDIR DATAROOT_DIR
+ DATADIR DATA_DIR
+ INFODIR INFO_DIR
+ LOCALEDIR LOCALE_DIR
+ MANDIR MAN_DIR
+ DOCDIR DOC_DIR
+
+more suffixes can be added using the ``EXTRA_PATH_VARS_SUFFIX``
+argument.
+
+
+The ``<Name>Targets.cmake`` is generated using :cmake:command:`export(EXPORT)`
+in the build tree and :cmake:command:`install(EXPORT)` in the installation
+directory. The targets are exported using the value for the ``NAMESPACE``
+argument as namespace.
+The export can be passed using the ``EXPORT`` argument. If no export is
+used (e.g. for a CMake script library), pass ``NO_EXPORT``.
+
+If the ``INCLUDE_FILE`` argument is passed, the content of the specified file
+(which might contain ``@variables@``) is appended to the generated
+``<Name>Config.cmake`` file.
+If the ``INCLUDE_CONTENT`` argument is passed, the specified content
+(which might contain ``@variables@``) is appended to the generated
+``<Name>Config.cmake`` file.
+When a ``CONFIG_TEMPLATE`` is passed, or a ``<Name>ConfigVersion.cmake.in`` or
+a ``<name>-config-version.cmake.in file is available, these 2 arguments are
+used to replace the ``@INCLUDED_CONTENT@`` string in this file.
+This allows one to inject custom code to this file, useful e.g. to set
+additional variables which are loaded by downstream projects.
+
+Note that content specified with ``INCLUDE_FILE`` or ``INCLUDE_CONTENT``
+cannot reference any of the ``PATH_VARS`` because this content is not
+expanded by :cmake:command:`configure_package_config_file`.
+
+If the ``COMPONENT`` argument is passed, it is forwarded to the
+:cmake:command:`install` commands, otherwise ``<Name>`` is used.
+#]=======================================================================]
+
+
+if(COMMAND install_basic_package_files)
+ return()
+endif()
+
+
+include(GNUInstallDirs)
+include(CMakePackageConfigHelpers)
+include(CMakeParseArguments)
+
+
+function(INSTALL_BASIC_PACKAGE_FILES _Name)
+
+ set(_options ARCH_INDEPENDENT
+ NO_EXPORT
+ NO_SET_AND_CHECK_MACRO
+ NO_CHECK_REQUIRED_COMPONENTS_MACRO
+ UPPERCASE_FILENAMES
+ LOWERCASE_FILENAMES
+ NO_COMPATIBILITY_VARS # Deprecated
+ ENABLE_COMPATIBILITY_VARS) # Deprecated
+ set(_oneValueArgs VERSION
+ COMPATIBILITY
+ EXPORT
+ FIRST_TARGET # Deprecated
+ TARGETS_PROPERTY # Deprecated
+ VARS_PREFIX
+ EXPORT_DESTINATION
+ INSTALL_DESTINATION
+ DESTINATION # Deprecated
+ NAMESPACE
+ CONFIG_TEMPLATE
+ INCLUDE_FILE
+ INCLUDE_CONTENT
+ COMPONENT)
+ set(_multiValueArgs EXTRA_PATH_VARS_SUFFIX
+ TARGETS # Deprecated
+ TARGETS_PROPERTIES # Deprecated
+ DEPENDENCIES
+ PRIVATE_DEPENDENCIES)
+ cmake_parse_arguments(_IBPF "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" "${ARGN}")
+
+ if(NOT DEFINED _IBPF_VARS_PREFIX)
+ set(_IBPF_VARS_PREFIX ${_Name})
+ endif()
+
+ if(NOT DEFINED _IBPF_VERSION)
+ if(NOT DEFINED PROJECT_VERSION)
+ message(FATAL_ERROR "VERSION argument is required (PROJECT_VERSION is not defined)")
+ endif()
+ set(_IBPF_VERSION ${PROJECT_VERSION})
+ endif()
+
+ if(NOT DEFINED _IBPF_COMPATIBILITY)
+ message(FATAL_ERROR "COMPATIBILITY argument is required")
+ endif()
+
+ unset(_arch_independent)
+ if(_IBPF_ARCH_INDEPENDENT)
+ set(_arch_independent ARCH_INDEPENDENT)
+ endif()
+
+ if(_IBPF_UPPERCASE_FILENAMES AND _IBPF_LOWERCASE_FILENAMES)
+ message(FATAL_ERROR "UPPERCASE_FILENAMES and LOWERCASE_FILENAMES arguments cannot be used together")
+ endif()
+
+ if(DEFINED _IBPF_INCLUDE_FILE AND DEFINED _IBPF_INCLUDE_CONTENT)
+ message(FATAL_ERROR "INCLUDE_FILE and INCLUDE_CONTENT arguments cannot be used together")
+ endif()
+
+ # Prepare install and export commands
+ unset(_targets)
+ set(_install_cmd EXPORT ${_Name})
+ set(_export_cmd EXPORT ${_Name})
+
+ if(DEFINED _IBPF_EXPORT)
+ if(_IBPF_NO_EXPORT OR DEFINED _IBPF_TARGETS OR DEFINED _IBPF_TARGETS_PROPERTIES OR DEFINED _IBPF_TARGETS_PROPERTIES)
+ message(FATAL_ERROR "EXPORT cannot be used with NO_EXPORT, TARGETS, TARGETS_PROPERTY, or TARGETS_PROPERTIES")
+ endif()
+
+ set(_export_cmd EXPORT ${_IBPF_EXPORT})
+ set(_install_cmd EXPORT ${_IBPF_EXPORT})
+
+ elseif(_IBPF_NO_EXPORT)
+ if(DEFINED _IBPF_TARGETS OR DEFINED _IBPF_TARGETS_PROPERTIES OR DEFINED _IBPF_TARGETS_PROPERTIES)
+ message(FATAL_ERROR "NO_EXPORT cannot be used with TARGETS, TARGETS_PROPERTY, or TARGETS_PROPERTIES")
+ endif()
+
+ elseif(DEFINED _IBPF_TARGETS)
+ message(DEPRECATION "TARGETS is deprecated. Use EXPORT instead")
+
+ if(DEFINED _IBPF_TARGETS_PROPERTY OR DEFINED _IBPF_TARGETS_PROPERTIES)
+ message(FATAL_ERROR "TARGETS cannot be used with TARGETS_PROPERTY or TARGETS_PROPERTIES")
+ endif()
+
+ set(_targets ${_IBPF_TARGETS})
+ set(_export_cmd TARGETS ${_IBPF_TARGETS})
+
+ elseif(DEFINED _IBPF_TARGETS_PROPERTY)
+ message(DEPRECATION "TARGETS_PROPERTY is deprecated. Use EXPORT instead")
+
+ if(DEFINED _IBPF_TARGETS_PROPERTIES)
+ message(FATAL_ERROR "TARGETS_PROPERTIES cannot be used with TARGETS_PROPERTIES")
+ endif()
+
+ get_property(_targets GLOBAL PROPERTY ${_IBPF_TARGETS_PROPERTY})
+ set(_export_cmd TARGETS ${_targets})
+
+ elseif(DEFINED _IBPF_TARGETS_PROPERTIES)
+ message(DEPRECATION "TARGETS_PROPERTIES is deprecated. Use EXPORT instead")
+
+ set(_targets "") # Defined but empty
+ foreach(_prop ${_IBPF_TARGETS_PROPERTIES})
+ get_property(_prop_val GLOBAL PROPERTY ${_prop})
+ list(APPEND _targets ${_prop_val})
+ endforeach()
+ set(_export_cmd TARGETS ${_targets})
+
+ endif()
+
+ # Path for installed cmake files
+ if(DEFINED _IBPF_DESTINATION)
+ message(DEPRECATION "DESTINATION is deprecated. Use INSTALL_DESTINATION instead")
+ if(NOT DEFINED _IBPF_INSTALL_DESTINATION)
+ set(_IBPF_INSTALL_DESTINATION ${_IBPF_DESTINATION})
+ endif()
+ endif()
+
+ # If not set by the user, choose an adequate destination
+ if(NOT DEFINED _IBPF_INSTALL_DESTINATION)
+ if(_IBPF_ARCH_INDEPENDENT)
+ set(_IBPF_INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/${_Name})
+ else()
+ set(_IBPF_INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${_Name})
+ endif()
+ endif()
+
+ # FIRST_TARGET is no longer used
+ if(DEFINED _IBPF_FIRST_TARGET)
+ message(DEPRECATION "FIRST_TARGET is deprecated.")
+ endif()
+
+ # NO_COMPATIBILITY_VARS and ENABLE_COMPATIBILITY_VARS cannot be used together
+ if(_IBPF_NO_COMPATIBILITY_VARS AND _ENABLE_COMPATIBILITY_VARS)
+ message(FATAL_ERROR "NO_COMPATIBILITY_VARS and ENABLE_COMPATIBILITY_VARS cannot be used together")
+ endif()
+ # NO_COMPATIBILITY_VARS is deprecated
+ if(_IBPF_NO_COMPATIBILITY_VARS)
+ message(DEPRECATION "NO_COMPATIBILITY_VARS is deprecated.")
+ endif()
+ # ENABLE_COMPATIBILITY_VARS is deprecated
+ if(_IBPF_ENABLE_COMPATIBILITY_VARS)
+ message(DEPRECATION "ENABLE_COMPATIBILITY_VARS is deprecated.")
+ endif()
+ # ENABLE_COMPATIBILITY_VARS does not work with EXPORT
+ if(NOT DEFINED _targets AND _IBPF_ENABLE_COMPATIBILITY_VARS)
+ message(FATAL_ERROR "ENABLE_COMPATIBILITY_VARS does not work with EXPORT")
+ endif()
+ # ENABLE_COMPATIBILITY_VARS can be enabled for projects still using targets
+ if(DEFINED _targets AND NOT _IBPF_NO_COMPATIBILITY_VARS AND NOT _IBPF_ENABLE_COMPATIBILITY_VARS)
+ message(DEPRECATION "Compatibility variables are no longer generated. Use ENABLE_COMPATIBILITY_VARS to re-enable them (deprecated) or define them using either INCLUDE_FILE or INCLUDE_CONTENT (recommended).")
+ endif()
+
+ if(NOT DEFINED _IBPF_EXPORT_DESTINATION)
+ set(_IBPF_EXPORT_DESTINATION "${CMAKE_BINARY_DIR}")
+ elseif(NOT IS_ABSOLUTE "${_IBPF_EXPORT_DESTINATION}")
+ set(_IBPF_EXPORT_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${_IBPF_EXPORT_DESTINATION}")
+ endif()
+
+ if(NOT DEFINED _IBPF_NAMESPACE)
+ set(_IBPF_NAMESPACE "${_Name}::")
+ endif()
+
+ if(NOT DEFINED _IBPF_COMPONENT)
+ set(_IBPF_COMPONENT "${_Name}")
+ endif()
+
+ if(_IBPF_NO_SET_AND_CHECK_MACRO)
+ list(APPEND configure_package_config_file_extra_args NO_SET_AND_CHECK_MACRO)
+ endif()
+
+ if(_IBPF_NO_CHECK_REQUIRED_COMPONENTS_MACRO)
+ list(APPEND configure_package_config_file_extra_args NO_CHECK_REQUIRED_COMPONENTS_MACRO)
+ endif()
+
+
+
+ # Set input file for config, and ensure that _IBPF_UPPERCASE_FILENAMES
+ # and _IBPF_LOWERCASE_FILENAMES are set correctly
+ unset(_config_cmake_in)
+ set(_generate_file 0)
+ if(DEFINED _IBPF_CONFIG_TEMPLATE)
+ if(NOT EXISTS "${_IBPF_CONFIG_TEMPLATE}")
+ message(FATAL_ERROR "Config template file \"${_IBPF_CONFIG_TEMPLATE}\" not found")
+ endif()
+ set(_config_cmake_in "${_IBPF_CONFIG_TEMPLATE}")
+ if(NOT _IBPF_UPPERCASE_FILENAMES AND NOT _IBPF_LOWERCASE_FILENAMES)
+ if("${_IBPF_CONFIG_TEMPLATE}" MATCHES "${_Name}Config.cmake.in")
+ set(_IBPF_UPPERCASE_FILENAMES 1)
+ elseif("${_IBPF_CONFIG_TEMPLATE}" MATCHES "${_name}-config.cmake.in")
+ set(_IBPF_LOWERCASE_FILENAMES 1)
+ else()
+ set(_IBPF_UPPERCASE_FILENAMES 1)
+ endif()
+ endif()
+ else()
+ string(TOLOWER "${_Name}" _name)
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_Name}Config.cmake.in")
+ set(_config_cmake_in "${CMAKE_CURRENT_SOURCE_DIR}/${_Name}Config.cmake.in")
+ if(NOT _IBPF_UPPERCASE_FILENAMES AND NOT _IBPF_LOWERCASE_FILENAMES)
+ set(_IBPF_UPPERCASE_FILENAMES 1)
+ endif()
+ elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_name}-config.cmake.in")
+ set(_config_cmake_in "${CMAKE_CURRENT_SOURCE_DIR}/${_name}-config.cmake.in")
+ if(NOT _IBPF_UPPERCASE_FILENAMES AND NOT _IBPF_LOWERCASE_FILENAMES)
+ set(_IBPF_LOWERCASE_FILENAMES 1)
+ endif()
+ else()
+ set(_generate_file 1)
+ if(_IBPF_LOWERCASE_FILENAMES)
+ set(_config_cmake_in "${CMAKE_CURRENT_BINARY_DIR}/${_name}-config.cmake.in")
+ else()
+ set(_config_cmake_in "${CMAKE_CURRENT_BINARY_DIR}/${_Name}Config.cmake.in")
+ set(_IBPF_UPPERCASE_FILENAMES 1)
+ endif()
+ endif()
+ endif()
+
+ # Set input file containing user variables
+ if(DEFINED _IBPF_INCLUDE_FILE)
+ if(NOT IS_ABSOLUTE "${_IBPF_INCLUDE_FILE}")
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_IBPF_INCLUDE_FILE}")
+ set(_IBPF_INCLUDE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${_IBPF_INCLUDE_FILE}")
+ endif()
+ endif()
+ if(NOT EXISTS "${_IBPF_INCLUDE_FILE}")
+ message(FATAL_ERROR "File \"${_IBPF_INCLUDE_FILE}\" not found")
+ endif()
+ file(READ ${_IBPF_INCLUDE_FILE} _IBPF_INCLUDE_CONTENT)
+ endif()
+
+ if(DEFINED _IBPF_INCLUDE_CONTENT)
+ string(CONFIGURE ${_IBPF_INCLUDE_CONTENT}
+ _IBPF_INCLUDE_CONTENT
+ @ONLY)
+ set(INCLUDED_CONTENT
+"#### Expanded from INCLUDE_FILE/INCLUDE_CONTENT by install_basic_package_files() ####
+
+${_IBPF_INCLUDE_CONTENT}
+
+#####################################################################################
+")
+ endif()
+
+ # Backwards compatibility
+ if(NOT _generate_file AND DEFINED _IBPF_INCLUDE_FILE)
+ file(READ ${_config_cmake_in} _config_cmake_in_content)
+ if("${_config_cmake_in_content}" MATCHES "@INCLUDED_FILE_CONTENT@")
+ message(DEPRECATION "The @INCLUDED_FILE_CONTENT@ variable is deprecated in favour of @INCLUDED_CONTENT@")
+ set(INCLUDED_FILE_CONTENT "${INCLUDED_CONTENT}")
+ endif()
+ endif()
+
+ # Select output file names
+ if(_IBPF_UPPERCASE_FILENAMES)
+ set(_config_filename ${_Name}Config.cmake)
+ set(_version_filename ${_Name}ConfigVersion.cmake)
+ set(_targets_filename ${_Name}Targets.cmake)
+ elseif(_IBPF_LOWERCASE_FILENAMES)
+ set(_config_filename ${_name}-config.cmake)
+ set(_version_filename ${_name}-config-version.cmake)
+ set(_targets_filename ${_name}-targets.cmake)
+ endif()
+
+
+ # If the template config file does not exist, write a basic one
+ if(_generate_file)
+ # Generate the compatibility code
+ unset(_compatibility_vars)
+ if(_IBPF_ENABLE_COMPATIBILITY_VARS)
+ unset(_get_include_dir_code)
+ unset(_set_include_dir_code)
+ unset(_target_list)
+ foreach(_target ${_targets})
+ list(APPEND _target_list ${_IBPF_NAMESPACE}${_target})
+ endforeach()
+ if(DEFINED ${_IBPF_VARS_PREFIX}_BUILD_INCLUDEDIR OR
+ DEFINED BUILD_${_IBPF_VARS_PREFIX}_INCLUDEDIR OR
+ DEFINED ${_IBPF_VARS_PREFIX}_INSTALL_INCLUDEDIR OR
+ DEFINED INSTALL_${_IBPF_VARS_PREFIX}_INCLUDEDIR)
+ list(APPEND _include_dir_list "\"\@PACKAGE_${_IBPF_VARS_PREFIX}_INCLUDEDIR\@\"")
+ elseif(DEFINED ${_IBPF_VARS_PREFIX}_BUILD_INCLUDE_DIR OR
+ DEFINED BUILD_${_IBPF_VARS_PREFIX}_INCLUDE_DIR OR
+ DEFINED ${_IBPF_VARS_PREFIX}_INSTALL_INCLUDE_DIR OR
+ DEFINED INSTALL_${_IBPF_VARS_PREFIX}_INCLUDE_DIR)
+ list(APPEND _include_dir_list "\"\@PACKAGE_${_IBPF_VARS_PREFIX}_INCLUDE_DIR\@\"")
+ else()
+ unset(_include_dir_list)
+ foreach(_target ${_targets})
+ list(APPEND _include_dir_list "\$<TARGET_PROPERTY:${_IBPF_NAMESPACE}${_target},INTERFACE_INCLUDE_DIRECTORIES>")
+ endforeach()
+ string(REPLACE ";" " " _include_dir_list "${_include_dir_list}")
+ string(REPLACE ";" " " _target_list "${_target_list}")
+ set(_set_include_dir "")
+ endif()
+ set(_compatibility_vars
+"# Compatibility\nset(${_Name}_LIBRARIES ${_target_list})
+set(${_Name}_INCLUDE_DIRS ${_include_dir_list})
+if(NOT \"\${${_Name}_INCLUDE_DIRS}\" STREQUAL \"\")
+ list(REMOVE_DUPLICATES ${_Name}_INCLUDE_DIRS)
+endif()
+")
+ endif()
+
+ if(_IBPF_NO_EXPORT)
+ set(_include_targets_cmd "")
+ else()
+ set(_include_targets_cmd "include(\"\${CMAKE_CURRENT_LIST_DIR}/${_targets_filename}\")")
+ endif()
+
+ # Write the file
+ file(WRITE "${_config_cmake_in}"
+"set(${_IBPF_VARS_PREFIX}_VERSION \@PACKAGE_VERSION\@)
+
+\@PACKAGE_INIT\@
+
+\@PACKAGE_DEPENDENCIES\@
+
+${_include_targets_cmd}
+
+${_compatibility_vars}
+
+\@INCLUDED_CONTENT\@
+")
+ endif()
+
+ # Make relative paths absolute (needed later on) and append the
+ # defined variables to _(build|install)_path_vars_suffix
+ foreach(p BINDIR BIN_DIR
+ SBINDIR SBIN_DIR
+ LIBEXECDIR LIBEXEC_DIR
+ SYSCONFDIR SYSCONF_DIR
+ SHAREDSTATEDIR SHAREDSTATE_DIR
+ LOCALSTATEDIR LOCALSTATE_DIR
+ LIBDIR LIB_DIR
+ INCLUDEDIR INCLUDE_DIR
+ OLDINCLUDEDIR OLDINCLUDE_DIR
+ DATAROOTDIR DATAROOT_DIR
+ DATADIR DATA_DIR
+ INFODIR INFO_DIR
+ LOCALEDIR LOCALE_DIR
+ MANDIR MAN_DIR
+ DOCDIR DOC_DIR
+ ${_IBPF_EXTRA_PATH_VARS_SUFFIX})
+ if(DEFINED ${_IBPF_VARS_PREFIX}_BUILD_${p})
+ list(APPEND _build_path_vars_suffix ${p})
+ list(APPEND _build_path_vars "${_IBPF_VARS_PREFIX}_${p}")
+ endif()
+ if(DEFINED BUILD_${_IBPF_VARS_PREFIX}_${p})
+ list(APPEND _build_path_vars_suffix ${p})
+ list(APPEND _build_path_vars "${_IBPF_VARS_PREFIX}_${p}")
+ endif()
+ if(DEFINED ${_IBPF_VARS_PREFIX}_INSTALL_${p})
+ list(APPEND _install_path_vars_suffix ${p})
+ list(APPEND _install_path_vars "${_IBPF_VARS_PREFIX}_${p}")
+ endif()
+ if(DEFINED INSTALL_${_IBPF_VARS_PREFIX}_${p})
+ list(APPEND _install_path_vars_suffix ${p})
+ list(APPEND _install_path_vars "${_IBPF_VARS_PREFIX}_${p}")
+ endif()
+ endforeach()
+
+
+ # <Name>ConfigVersion.cmake file (same for build tree and intall)
+ write_basic_package_version_file("${_IBPF_EXPORT_DESTINATION}/${_version_filename}"
+ VERSION ${_IBPF_VERSION}
+ COMPATIBILITY ${_IBPF_COMPATIBILITY}
+ ${_arch_independent})
+ install(FILES "${_IBPF_EXPORT_DESTINATION}/${_version_filename}"
+ DESTINATION ${_IBPF_INSTALL_DESTINATION}
+ COMPONENT ${_IBPF_COMPONENT})
+
+
+ # Prepare PACKAGE_DEPENDENCIES variable
+ set(_need_private_deps 0)
+ if(NOT BUILD_SHARED_LIBS)
+ set(_need_private_deps 1)
+ endif()
+
+ unset(PACKAGE_DEPENDENCIES)
+ if(DEFINED _IBPF_DEPENDENCIES OR (DEFINED _IBPF_PRIVATE_DEPENDENCIES AND _need_private_deps))
+ set(PACKAGE_DEPENDENCIES "#### Expanded from @PACKAGE_DEPENDENCIES@ by install_basic_package_files() ####\n\ninclude(CMakeFindDependencyMacro)\n")
+
+ foreach(_dep ${_IBPF_DEPENDENCIES})
+ string(APPEND PACKAGE_DEPENDENCIES "find_dependency(${_dep})\n")
+ endforeach()
+
+ if(_need_private_deps)
+ foreach(_dep ${_IBPF_PRIVATE_DEPENDENCIES})
+ string(APPEND PACKAGE_DEPENDENCIES "find_dependency(${_dep})\n")
+ endforeach()
+ endif()
+
+ string(APPEND PACKAGE_DEPENDENCIES "\n###############################################################################\n")
+ endif()
+
+ # Prepare PACKAGE_VERSION variable
+ set(PACKAGE_VERSION ${_IBPF_VERSION})
+
+ # <Name>Config.cmake (build tree)
+ foreach(p ${_build_path_vars_suffix})
+ if(DEFINED ${_IBPF_VARS_PREFIX}_BUILD_${p})
+ set(${_IBPF_VARS_PREFIX}_${p} "${${_IBPF_VARS_PREFIX}_BUILD_${p}}")
+ elseif(DEFINED BUILD_${_IBPF_VARS_PREFIX}_${p})
+ set(${_IBPF_VARS_PREFIX}_${p} "${BUILD_${_IBPF_VARS_PREFIX}_${p}}")
+ endif()
+ endforeach()
+ configure_package_config_file("${_config_cmake_in}"
+ "${_IBPF_EXPORT_DESTINATION}/${_config_filename}"
+ INSTALL_DESTINATION ${_IBPF_EXPORT_DESTINATION}
+ PATH_VARS ${_build_path_vars}
+ ${configure_package_config_file_extra_args}
+ INSTALL_PREFIX ${CMAKE_BINARY_DIR})
+
+ # <Name>Config.cmake (installed)
+ foreach(p ${_install_path_vars_suffix})
+ if(DEFINED ${_IBPF_VARS_PREFIX}_INSTALL_${p})
+ set(${_IBPF_VARS_PREFIX}_${p} "${${_IBPF_VARS_PREFIX}_INSTALL_${p}}")
+ elseif(DEFINED INSTALL_${_IBPF_VARS_PREFIX}_${p})
+ set(${_IBPF_VARS_PREFIX}_${p} "${INSTALL_${_IBPF_VARS_PREFIX}_${p}}")
+ endif()
+ endforeach()
+ configure_package_config_file("${_config_cmake_in}"
+ "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_config_filename}.install"
+ INSTALL_DESTINATION ${_IBPF_INSTALL_DESTINATION}
+ PATH_VARS ${_install_path_vars}
+ ${configure_package_config_file_extra_args})
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_config_filename}.install"
+ DESTINATION ${_IBPF_INSTALL_DESTINATION}
+ RENAME ${_config_filename}
+ COMPONENT ${_IBPF_COMPONENT})
+
+
+ # <Name>Targets.cmake (build tree)
+ if(NOT _IBPF_NO_EXPORT)
+ export(${_export_cmd}
+ NAMESPACE ${_IBPF_NAMESPACE}
+ FILE "${_IBPF_EXPORT_DESTINATION}/${_targets_filename}")
+ endif()
+
+ # Export build directory if CMAKE_EXPORT_PACKAGE_REGISTRY is set.
+ # CMake >= 3.15 already checks for CMAKE_EXPORT_PACKAGE_REGISTRY in `export(PACKAGE)` (cf.
+ # cf. https://cmake.org/cmake/help/latest/policy/CMP0090.html), and we effectively back-port
+ # this behavior to earlier versions.
+ # Note that even never CMake versions may apply old policy behaviors if the consuming project
+ # requires a lower version of CMake (e.g. `cmake_minimum_required(VERSION 3.14)`), so the
+ # check for `CMAKE_EXPORT_PACKAGE_REGISTRY` is necessary for CMake >= 3.15 as well.
+ if(CMAKE_EXPORT_PACKAGE_REGISTRY)
+ export(PACKAGE ${_Name})
+ endif()
+
+ # <Name>Targets.cmake (installed)
+ if(NOT _IBPF_NO_EXPORT)
+ install(${_install_cmd}
+ NAMESPACE ${_IBPF_NAMESPACE}
+ DESTINATION ${_IBPF_INSTALL_DESTINATION}
+ FILE "${_targets_filename}"
+ COMPONENT ${_IBPF_COMPONENT})
+ endif()
+endfunction()
diff --git a/thirdparty/gsl-lite/doc/Reference.md b/thirdparty/gsl-lite/doc/Reference.md
new file mode 100644
index 000000000..f182e9783
--- /dev/null
+++ b/thirdparty/gsl-lite/doc/Reference.md
@@ -0,0 +1,1389 @@
+# Reference documentation
+
+## Contents
+
+- [Contract and assertion checks](#contract-and-assertion-checks): `gsl_Expects( pred )`, `gsl_Ensures( pred )`, `gsl_Assert( pred )`, and more
+- [Pointer annotations](#pointer-annotations): `owner<P>`, `not_null<P>`, and `not_null_ic<P>`
+- [Numeric type conversions](#numeric-type-conversions): `narrow<T>( u )`, `narrow_failfast<T>( u )`, and `narrow_cast<T>( u )`
+- [Safe contiguous ranges](#safe-contiguous-ranges): `span<T, Extent>`
+- [Bounds-checked element access](#bounds-checked-element-access): `at( container, index )`
+- [Integer type aliases](#integer-type-aliases): `index`, `dim`, `stride`, `diff`
+- [String type aliases](#string-type-aliases): `zstring`, `czstring`, `wzstring`, `cwzstring`
+- [Ad hoc resource management (C++11 and higher)](#ad-hoc-resource-management-c11-and-higher): `finally( action )`, `on_return( action )`, and `on_error( action )`
+- [Feature checking macros](#feature-checking-macros)
+- [Polyfills](#polyfills)
+- [Configuration options and switches](#configuration-options-and-switches)
+- [Configuration changes, deprecated and removed features](#configuration-changes-deprecated-and-removed-features)
+
+
+## Contract and assertion checks
+
+(Core Guidelines reference: [GSL.assert: Assertions](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-assertions))
+
+There are several macros for expressing preconditions, postconditions, and invariants:
+
+- `gsl_FailFast()` to indicate unreachable code
+- `gsl_Expects( cond )` for simple preconditions
+- `gsl_Ensures( cond )` for simple postconditions
+- `gsl_Assert( cond )` for simple assertions
+- `gsl_ExpectsDebug( cond )` for debug-mode preconditions
+- `gsl_EnsuresDebug( cond )` for debug-mode postconditions
+- `gsl_AssertDebug( cond )` for debug-mode assertions
+- `gsl_ExpectsAudit( cond )` for preconditions that are expensive or include potentially opaque function calls
+- `gsl_EnsuresAudit( cond )` for postconditions that are expensive or include potentially opaque function calls
+- `gsl_AssertAudit( cond )` for assertions that are expensive or include potentially opaque function calls
+
+**Example:**
+```c++
+template< class RandomIt >
+auto median( RandomIt first, RandomIt last )
+{
+ gsl_Expects( first != last );
+
+ // Verifying that a range of elements is sorted is an expensive operation that changes the
+ // computational complexity of the function `median()` from 𝒪(1) to 𝒪(n). Therefore, we
+ // express it as an audit-level contract check.
+ gsl_ExpectsAudit( std::is_sorted( first, last ) );
+
+ auto count = last - first;
+ return count % 2 != 0
+ ? first[ count / 2 ]
+ : std::midpoint( first[ count / 2 ], first[ count / 2 + 1 ] );
+}
+```
+
+The behavior of the different flavors of pre-/postcondition checks and assertions depends on a number of [configuration macros](#contract-checking-configuration-macros):
+
+- The macros **`gsl_Expects()`**, **`gsl_Ensures()`**, and **`gsl_Assert()`** are compiled to runtime checks unless contract
+ checking is disabled with the `gsl_CONFIG_CONTRACT_CHECKING_OFF` configuration macro.
+
+- Contract checks expressed with **`gsl_ExpectsAudit()`**, **`gsl_EnsuresAudit()`**, and **`gsl_AssertAudit()`** are discarded by
+ default. In order to have them checked at runtime, the `gsl_CONFIG_CONTRACT_CHECKING_AUDIT` configuration macro must be defined.
+
+- The macros **`gsl_ExpectsDebug()`**, **`gsl_EnsuresDebug()`**, and **`gsl_AssertDebug()`** are compiled to runtime checks unless
+ contract checking is disabled by defining `gsl_CONFIG_CONTRACT_CHECKING_OFF` or assertions are disabled by defining `NDEBUG`.
+ They can be used in place of the [`assert()`](https://en.cppreference.com/w/cpp/error/assert) macro from the C standard library.
+ (Note that defining `gsl_CONFIG_CONTRACT_CHECKING_AUDIT` also enables checking of the `gsl_*Debug()` macros regardless of
+ whether `NDEBUG` is defined.)
+
+- The **`gsl_Expects*()`**, **`gsl_Ensures*()`**, **`gsl_Assert*()`** categories of checks can be disabled individually with the
+ `gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF`, `gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF`, or `gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF`
+ configuration macros.
+
+- **`gsl_FailFast()`** is similar to `gsl_Assert( false )` but is guaranteed to interrupt the current path of execution even
+ if contract checking is disabled with configuration macros. It is useful in places which should not be reachable during program
+ execution. For example:
+ ```c++
+ enum class Color : int { red, green, blue };
+ std::string colorToString( Color color )
+ {
+ switch (color)
+ {
+ case Color::red: return "red";
+ case Color::green: return "green";
+ case Color::blue: return "blue";
+ }
+ gsl_FailFast();
+ }
+ ```
+ The C++ language permits casting any representable integer value to an enum. Therefore, `colorToString(Color(0xFF00FF))`
+ is legal C++, but not actually supported by this `colorToString()` implementation. `gsl_FailFast()` is employed here to ensure
+ that passing unsupported values to `colorToString()` will be detected at runtime.
+
+ `gsl_FailFast()` behaves as if annotated by the [`[[noreturn]]`](https://en.cppreference.com/w/cpp/language/attributes/noreturn)
+ attribute. A C++11 compiler will therefore not emit a warning about a missing return statement in `colorToString()`.
+ <!--(Unrelated note: the `switch` statement above deliberately elides the `default:` clause. Because the switch statement is wrapped
+ in a dedicated function, we can use `return` instead of `break` to conclude the `case` clauses, and hence the default handler
+ can simply go after the `switch` statement. The benefit of avoiding the `default:` clause is that most compilers will understand
+ that the `switch` statement is supposed to handle all defined enumeration values and thus issue a warning if the programmer adds
+ a new enumeration value (say, `Color::yellow`) but forgets to amend the `switch` statement.)-->
+
+
+## Pointer annotations
+
+- [`owner<P>` (C++11 and higher)](#ownerp-c11-and-higher)
+- [`not_null<P>`](#not_nullp)
+ - [Motivation](#motivation)
+ - [Reference](#reference)
+ - [Nullability and the moved-from state](#nullability-and-the-moved-from-state)
+- [`not_null_ic<P>`](#not_null_icp)
+
+(Core Guidelines reference: [GSL.view: Views](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslview-views))
+
+*gsl-lite* defines the three pointer type annotations `owner<P>`, `not_null<P>`, and `not_null_ic<P>` which let the user signify additional intent:
+
+- `owner<P>` indicates that a raw pointer `P` carries ownership of the object it points to, and is thus responsible for managing its lifetime.
+- `not_null<P>` and `not_null_ic<P>` indicate that a pointer `P` must not be `nullptr`.
+
+### `owner<P>` (C++11 and higher)
+
+`gsl_lite::owner<P>` is a type alias that solely serves the purpose of expressing intent:
+```c++
+template< class P >
+requires ( std::is_pointer_v<P> )
+using owner = P;
+```
+(*Note:* The actual definition uses a SFINAE constraint to support C\+\+11 to C\+\+17).
+
+As far as the type system and the runtime behavior is concerned, `owner<P>` is exactly equivalent to `P`. However, the annotation conveys
+intent to a reader, and static analysis tools may use the annotation to impose semantic checks based on the assumption of ownership.
+
+If possible, a smart pointer with automatic lifetime management such as [`std::unique_ptr<>`](https://en.cppreference.com/w/cpp/memory/unique_ptr)
+or [`std::shared_ptr<>`](https://en.cppreference.com/w/cpp/memory/shared_ptr) should be used instead. The purpose of `owner<>` is annotation of
+raw pointers which cannot currently be replaced with a smart pointer.
+
+
+### `not_null<P>`
+
+`gsl_lite::not_null<P>` is a class template that wraps a pointer type `P` while enforcing non-nullability.
+
+`not_null<P>` has no default constructor, and its unary constructors use [`gsl_Expects()`](#contract-and-assertion-checks) to check
+that their argument is not `nullptr`. Therefore, when attempting to construct a `not_null<P>` from a null pointer, a runtime contract violation is triggered:
+```c++
+using gsl_lite::not_null;
+
+int i = 42;
+int * pi = &i;
+int * pn = nullptr;
+
+ // compile error: no default constructor
+//not_null<int *> n;
+
+ // compile error: no implicit conversion
+//not_null<int *> npi = pi;
+
+ // explicit conversion: runtime null check
+not_null<int *> npi = not_null( pi );
+
+ // compile error: no implicit conversion
+//not_null<int *> nn = nullptr;
+
+ // compile error: no explicit conversion
+//not_null<int *> nn = not_null( nullptr );
+
+ // explicit conversion: runtime null check ⇒ runtime contract violation
+not_null<int *> npn = not_null( pn );
+```
+
+#### Motivation
+
+<!--C++ knows two kinds of indirections: pointers and references. A pointer can refer to a special value known as `nullptr`,
+which indicates it does not point to any object, and can be subsequently reassigned. In contrast, references must always
+refer to a valid object, and they can be assigned only once, as part of their initialization.-->
+
+When defining function signatures, it is customary to use pointers and references to indicate whether an object
+reference is required or optional:
+```c++
+void lock( Mutex & m ); // requires a valid object reference
+
+struct ListNode
+{
+ ListNode* prev;
+ ListNode* next;
+ int payload;
+};
+bool tryRemove( ListNode * x ); // also accepts a `nullptr`
+```
+
+But this convention does not apply to every situation. For example, accepting a pointer argument can also emphasize the fact
+that the object's memory address may be taken and stored, as in the case of a list or tree node. Storing the memory address
+of a by-reference argument "feels" wrong, and may be flagged by static analyzers:
+```c++
+void insertAfter( ListNode & x, ListNode & newNode )
+{
+ newNode.prev = &x; // <-- Eww.
+ newNode.next = x.next;
+ x.next = &newNode; // <-- Eww.
+}
+```
+The function would be less awkward if it accepted pointers.
+
+To make sure a pointer argument is not `nullptr`, we can add a precondition check to the function:
+```c++
+void insertAfter( ListNode * x, ListNode * newNode )
+{
+ gsl_Expects( x != nullptr );
+ gsl_Expects( newNode != nullptr );
+
+ newNode->prev = x;
+ newNode->next = x->next;
+ x->next = newNode;
+}
+```
+
+Writing all the precondition checks against `nullptr` quickly becomes tedious. And unlike the contract checks once envisioned
+for C++20, precondition checks expressed with `gsl_Expects()` are not part of the function signature, which therefore does
+not convey that it cannot handle `nullptr` input.
+
+This is where `not_null<>` comes in. With `not_null<>`, the precondition can be "lifted" into the type system,
+and thus into the function signature:
+
+```c++
+void insertAfter( not_null<ListNode *> x, not_null<ListNode *> newNode )
+{
+ newNode->prev = x;
+ newNode->next = x->next;
+ x->next = newNode;
+}
+```
+
+All `not_null<>` constructors check their arguments for `nullptr` with `gsl_Expects()`, so the functions above can already assume
+that their arguments will never be `nullptr`, and the explicit precondition checks can be omitted.
+
+When calling the function `insertAfter()`, it is understood that the caller passes ownership of the node `newNode`.
+Transfer of ownership is best expressed with a smart pointer such as `std::unique_ptr<>`, which can also be used as an
+argument to `not_null<>`:
+
+```c++
+void insertAfter( not_null<ListNode *> x, not_null<std::unique_ptr<ListNode>> newNode );
+```
+
+A `not_null<std::unique_ptr<>>` can be passed around just like a `std::unique_ptr<>`:
+```c++
+void insertAfterEnd( not_null<ListNode *> lastNode, not_null<std::unique_ptr<ListNode>> newNode )
+{
+ gsl_Expects( lastNode->next == nullptr );
+
+ insertAfter( lastNode, std::move( newNode ) );
+}
+```
+
+Because `newNode` is non-nullable, releasing the pointer it holds is not straightforward:
+
+```c++
+void insertAfter( not_null<ListNode *> x, not_null<std::unique_ptr<ListNode>> newNode )
+{
+ newNode->prev = x;
+ newNode->next = x->next;
+ x->next = newNode.release(); // error: `not_null<>` has no member function `release()`
+}
+```
+
+To extract the raw pointer, we first have to extract a nullable `unique_ptr<>`:
+
+```c++
+ std::unique_ptr<ListNode> rawNewNode = std::move( newNode );
+ x->next = rawNewNode.release();
+```
+
+This can be written as a one-liner with `gsl_lite::as_nullable()`:
+
+```c++
+ x->next = gsl_lite::as_nullable( std::move( newNode ) ).release();
+```
+
+
+#### Reference
+
+`not_null<P>` strives to behave like the underlying type `P` as transparently as reasonably possible:
+
+- There is no runtime size overhead: `sizeof( not_null<P> ) == sizeof( P )`.
+- `not_null<P>` implicitly converts to `Q` if `P` implicitly converts to `Q`.
+ For example, `not_null<int *>` implicitly converts to `int const *`.
+- `not_null<P>` explicitly converts to `Q` if `P` explicitly converts to `Q`.
+- `not_null<P>` can be dereferenced if `P` can be dereferenced.
+- If `P` can be copied, `not_null<P>` can be copied. If `P` can be moved, `not_null<P>` can be moved.
+ For example, `not_null<T *>` is copyable, `not_null<std::unique_ptr<T>>` is movable but not copyable, and `not_null<std::shared_ptr<T>>` is copyable and movable.
+- If `P` points to a `struct`, `class`, or `union`, `not_null<P>` defines the member access operator `operator->`.
+- If `P` has a member function `P::get()`, `not_null<P>` also defines a member function `not_null<P>::get()` which forwards to `P::get()`.
+- If `P` is a function pointer or a nullable function object such as [`std::function<>`](https://en.cppreference.com/w/cpp/utility/functional/function),
+ `not_null<>` defines the function call operator `operator()` which forwards the call to `P`:
+ ```c++
+ long call( not_null<long (*)(long)> func, long arg )
+ {
+ return func( arg );
+ }
+ ```
+- `Q` implicitly converts to `not_null<P>` if `Q` is non-nullable and implicitly converts to `P`.
+ For example, [`std::labs`](https://en.cppreference.com/w/cpp/numeric/math/abs) implicitly converts to `not_null<long (*)(long)>`:
+ ```c++
+ long callAbs( long val )
+ {
+ return call( std::labs, val );
+ }
+ ```
+- `Q` explicitly converts to `not_null<P>` if `Q` is nullable and implicitly converts to `P`, or if `Q` explicitly converts to `P`.
+ For example:
+ ```c++
+ std::string readLine( not_null<std::FILE*> file );
+ std::FILE* file = ...;
+ //readLine( file ); // does not compile: `file` is nullable
+ readLine( not_null( file ) ); // compiles and executes a check at runtime
+ ```
+- If `P` is hashable (that is, the [`std::hash<P>`](https://en.cppreference.com/w/cpp/utility/hash) specialization is *enabled*), `not_null<P>` is hashable.
+
+For C++14 and older, where [class template argument deduction](https://en.cppreference.com/w/cpp/language/class_template_argument_deduction)
+is not available, *gsl-lite* defines a set of helper functions `make_not_null()` for explicitly constructing `not_null<>` objects.
+
+*gsl-lite* additionally defines the helper functions `make_unique<T>()` and `make_shared<T>()` which behave like
+[`std::make_unique<T>()`](https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) and
+[`std::make_shared<T>()`](https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared) but return `not_null<std::unique_ptr<T>>`
+and `not_null<std::shared_ptr<T>>`, respectively.
+
+`not_null<P>` is meant to point to single objects, not arrays of objects. It therefore does not define a subscript operator,
+pointer increment or decrement operators, or pointer addition or subtraction operators, and
+`gsl_lite::make_unique<T>()` and `gsl_lite::make_shared<T>()` are not defined for array types.
+
+To extract the nullable object wrapped by a `not_null<>` object, call `gsl_lite::as_nullable()`:
+```c++
+auto npi = gsl_lite::make_unique<int>( 42 ); // not_null<std::unique_ptr<int>>
+auto pi = gsl_lite::as_nullable( std::move( npi ) ); // std::unique_ptr<int>
+```
+
+This is useful when accessing operations of `P` not forwarded by `not_null<P>`:
+```c++
+void insertAfter( not_null<ListNode *> x, not_null<std::unique_ptr<ListNode>> newNode )
+{
+ newNode->prev = x;
+ newNode->next = x->next;
+ // no `not_null<>::release()` member function
+ x->next = gsl_lite::as_nullable( std::move( newNode ) ).release();
+}
+```
+
+
+#### Nullability and the moved-from state
+
+Because `not_null<P>` retains the copyability and movability of `P`, a `not_null<P>` object may have a *moved-from state* if the
+underlying pointer `P` has one. Therefore, a `not_null<P>` object may in fact be `nullptr` after it has been moved from:
+```c++
+auto x = gsl_lite::make_unique<int>( 42 ); // not_null<std::unique_ptr<int>>()
+auto y = std::move( x ); // x is now nullptr
+*x = 43; // dereferencing a nullptr ⇒ runtime contract violation
+```
+This is where *gsl-lite*'s implementation of `not_null<>` differs from the implementation of Microsoft GSL, which ensures that
+its `not_null<P>` cannot ever become `nullptr`, rendering its `not_null<std::unique_ptr<T>>` immovable (cf. [microsoft/GSL#1022](https://github.com/microsoft/GSL/issues/1022)).
+While this choice would prevent the error above, it inhibits many interesting use cases for `not_null<>`.
+For example, consider the following resource handle class:
+
+```c++
+struct FileCloser
+{
+ void operator ()(std::FILE* file) const noexcept
+ {
+ std::fclose( file );
+ }
+};
+using FilePtr = std::unique_ptr<std::FILE, FileCloser>;
+
+class FileHandle
+{
+private:
+ FilePtr file_;
+
+public:
+ FileHandle( FileHandle & rhs ) = default;
+ FileHandle & operator =( FileHandle & rhs ) = default;
+
+ explicit FileHandle( FilePtr _file )
+ : file_( std::move( _file ) )
+ {
+ }
+ int getc()
+ {
+ return std::fgetc( file_.get() );
+ }
+ ...
+};
+```
+
+To make `FileHandle` null-safe, we can add explicit precondition checks:
+
+```c++
+class FileHandle // movable
+{
+private:
+ FilePtr file_;
+
+public:
+ FileHandle( FileHandle & rhs )
+ : file_( std::move( rhs.file_ ) )
+ {
+ gsl_Expects( file_ != nullptr );
+ }
+ FileHandle & operator =( FileHandle & rhs )
+ {
+ gsl_Expects( rhs.file_ != nullptr );
+ file_ = std::move(rhs.file_);
+ return *this;
+ }
+
+ explicit FileHandle( FilePtr _file )
+ : file_( std::move( _file ) )
+ {
+ gsl_Expects( file_ != nullptr );
+ }
+ int getc()
+ {
+ gsl_Expects( file_ != nullptr );
+ return std::fgetc( file_.get() );
+ }
+ ...
+};
+```
+
+This is very tedious, not least because we have to define move constructor and move assignment operator manually.
+
+By using `not_null<>`, we can instead "lift" these preconditions to the type system and have all the
+precondition checks be generated automatically:
+
+```c++
+class FileHandle // still movable
+{
+private:
+ not_null<FilePtr> file_; // <--
+
+public:
+ // implicit precondition check `rhs.file_ != nullptr`
+ FileHandle( FileHandle & rhs ) = default;
+
+ // implicit precondition check `rhs.file_ != nullptr`
+ FileHandle & operator =( FileHandle & rhs ) = default;
+
+ explicit FileHandle( not_null<FilePtr> _file ) // <--
+ : file_( std::move( _file ) )
+ {
+ // implicit precondition check `_file != nullptr`
+ }
+ int getc()
+ {
+ // implicit precondition check `file_ != nullptr`
+ return std::fgetc( file_.get() );
+ }
+ ...
+};
+```
+
+Any code constructing a `FileHandle` will now have to explicitly cast the pointer as `not_null`:
+```c++
+auto filePtr = FilePtr( std::fopen( ... ) );
+if ( filePtr == nullptr ) throw std::runtime_error( ... );
+auto file = FileHandle( not_null( std::move( filePtr ) ) );
+```
+But any function accepting a `FileHandle` can now be sure that the object holds a valid pointer:
+```c++
+std::vector<std::string>
+readLines( FileHandle file )
+{
+ // file cannot hold a nullptr here
+ ...
+}
+```
+
+Although `not_null<>` can be used to inject preconditions and postconditions, it does not inject new
+invariants. After being moved from, a `FileHandle` indeed holds a `nullptr` in its `file_` pointer.
+Therefore, non-nullability of the `file_` pointer is not an invariant of the `FileHandle` class.
+However, a `FileHandle` is still safe to use because of the implicit precondition checks injected by `not_null<>`.
+Also, *use-after-move* errors can often be detected by static analysis tools, so this may be considered
+"safe enough" for practical purposes.
+
+<!--(Recommended further reading: Herb Sutter's article ["Move, simply"](https://herbsutter.com/2020/02/17/move-simply/),
+which argues that objects that have a special moved-from state in which most of their operations may not be used
+are buggy, and [Sean Parent's rebuttal](https://herbsutter.com/2020/02/17/move-simply/#comment-41129) in the comments below.)-->
+
+A `not_null<P>` cannot be directly compared to a `nullptr` because it is not meant to be nullable.
+If you have to check for the moved-from state, use the `gsl_lite::is_valid()` predicate:
+```c++
+auto npi = gsl_lite::make_unique<int>( 42 );
+// ...
+//if ( npi == nullptr ) { ... } // compile error
+if ( !gsl_lite::is_valid( npi ) ) { ... } // ok
+```
+
+*gsl-lite* also defines a set of helper functions `make_not_null()` for explicitly constructing `not_null<>`
+objects. This is useful for type inference in C++14 and older where
+[class template argument deduction](https://en.cppreference.com/w/cpp/language/class_template_argument_deduction)
+is not available. Example:
+```c++
+auto filePtr = FilePtr( std::fopen( ... ) );
+if ( filePtr == nullptr ) throw std::runtime_error( ... );
+auto file = FileHandle( make_not_null( std::move( filePtr ) ) );
+```
+
+
+### `not_null_ic<P>`
+
+(*Note:* `not_null_ic<>` is a *gsl-lite* extension and not part of the C++ Core Guidelines.)
+
+`gsl_lite::not_null_ic<P>` is a class template that wraps a pointer type `P` while enforcing non-nullability.
+It provides all the guarantees and run-time checks of [`not_null<P>`](#not_nullp) but relaxes the requirements
+of its conversion constructors: implicit conversion from `U` to `not_null_ic<P>` is allowed if `U` implicitly
+converts to `P`.
+
+`not_null<>` does not allow implicit conversion from nullable types:
+```c++
+void use( not_null<int *> p );
+int i;
+//use( &i ); // compile error: no implicit conversion
+use( not_null( &i ) ); // runtime check
+```
+
+This choice has the generally desirable consequence that it encourages propagation of non-nullability.
+Explicit conversions are needed only when converting a nullable to a non-nullable pointer; therefore, as
+more and more of a code base is converted to `not_null<>`, fewer explicit conversions need to be used.
+
+However, in some codebases it may not be feasible to insert explicit not-null checks at every invocation
+site. In such a situation, `gsl_lite::not_null_ic<P>` can be used instead. `not_null_ic<P>` derives from `not_null<P>`
+but additionally allows implicit construction from nullable types:
+
+```c++
+void use( not_null_ic<int *> p );
+int i;
+use( &i ); // runtime check
+```
+
+(Compatibility note: Microsoft GSL defines the classes `not_null<>` and `strict_not_null<>` which behave
+like *gsl-lite*'s `not_null_ic<>` and `not_null<>`, respectively.)
+
+
+## Numeric type conversions
+
+(Core Guidelines reference: [GSL.util: Utilities](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslutil-utilities))
+
+- [`narrow<T>( u )`](#narrowt-u-), a checked numeric cast
+- [`narrow_failfast<T>( u )`](#narrow_failfastt-u-), a checked numeric cast
+- [`narrow_cast<T>( u )`](#narrow_castt-u-), an unchecked numeric cast
+
+### `narrow<T>( u )`
+
+`gsl_lite::narrow<T>( u )` is a numeric cast that is not meant to be lossy. If narrowing leads to a change of sign or
+loss of information, an exception of type `gsl_lite::narrowing_error` is thrown.
+
+**Example:**
+```c++
+double volume = ...; // (m³)
+double bucketCapacity = ...; // (m³)
+double numBucketsF = std::ceil( volume/bucketCapacity );
+try
+{
+ auto numBuckets = gsl_lite::narrow<int>( numBucketsF );
+ std::cout << "Number of buckets required: " << numBuckets;
+ fillBuckets( numBuckets );
+}
+catch ( gsl_lite::narrowing_error const & )
+{
+ std::cerr << "This is more than I can handle.\n";
+}
+```
+
+In this example, an exception will be thrown if `numBucketsF` is not an integer (for instance, `std::ceil(-INFINITY)` will return `-INFINITY`),
+or if the value cannot be represented by `int`.
+
+
+### `narrow_failfast<T>( u )`
+
+(*Note:* `narrow_failfast<T>( u )` is a *gsl-lite* extension and not part of the C++ Core Guidelines.)
+
+`gsl_lite::narrow_failfast<T>( u )` is a numeric cast that is not meant to be lossy, which is verified with
+[`gsl_Assert()`](#contract-and-assertion-checks). If narrowing leads to a change of sign or loss of information, an
+assertion violation is triggered.
+
+The `narrow<T>( u )` function specified by the C++ Core Guidelines throws an exception, thereby indicating exceptional circumstances
+(for instance, "input data too large"). The exception may be caught and dealt with at runtime. Contrariwise, the purpose of
+`narrow_failfast<T>( u )` is to detect programming errors which the user of the program cannot do anything about.
+
+**Example 1:**
+```c++
+void printCmdArgs( gsl_lite::span<gsl_lite::zstring const> cmdArgs );
+
+int main( int argc, char * argv[] )
+{
+ auto args = gsl_lite::span(
+ argv,
+ // Something is seriously wrong if this cast fails.
+ gsl_lite::narrow_failfast<std::size_t>( argc ) );
+ printCmdArgs( args );
+}
+```
+
+**Example 2:**
+```c++
+auto vec = std::vector{ 1, 2, 3 };
+int elem = 2;
+auto pos = std::find( vec.begin(), vec.end(), elem );
+
+ // Bug: we accidentally swapped `pos` and `vec.end()`.
+auto delta = pos - vec.end();
+
+ // Assertion violation: `delta` is negative.
+auto subrangeSize = gsl_lite::narrow_failfast<std::size_t>( delta );
+
+auto subrange = std::vector<int>( subrangeSize );
+```
+
+
+### `narrow_cast<T>( u )`
+
+`narrow_cast<T>( u )` is a numeric cast in which loss of information is acceptable. It is exactly equivalent to `static_cast<T>( u )`,
+the only difference being that `narrow_cast<>()` conveys the intent that truncation or sign change is acceptable or even desired.
+
+**Example 1:**
+```c++
+ // Sign change to 0xFFFFFFFF
+auto allBitsSet = gsl_lite::narrow_cast<std::uint32_t>( -1 );
+```
+
+**Example 2:**
+```c++
+int floor( float val )
+{
+ gsl_Expects(
+ val >= std::numeric_limits<int>::lowest() &&
+ val <= std::numeric_limits<int>::max() );
+
+ return gsl_lite::narrow_cast<int>( val ); // truncation is desired here
+}
+```
+
+
+## Safe contiguous ranges
+
+(Core Guidelines reference: [GSL.view: Views](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslview-views))
+
+*gsl-lite* defines a class `gsl_lite::span<T, Extent>` that represents a contiguous sequence of objects. The interface
+of `span<>` is identical to that of [`std::span<>`](https://en.cppreference.com/w/cpp/container/span),
+but all operations in *gsl-lite*'s `span<>` use [`gsl_Expects()`](#contract-and-assertion-checks) to
+check their preconditions at runtime. `span<>::iterator` also verifies the preconditions of all its operations
+with `gsl_ExpectsDebug()`.
+
+*gsl-lite* also defines a set of helper functions `make_span()` for explicitly constructing `span<>` objects. This is useful
+for type inference in C++14 and older where [class template argument deduction](https://en.cppreference.com/w/cpp/language/class_template_argument_deduction)
+is not available. Example:
+```c++
+void printCmdArgs( gsl_lite::span<gsl_lite::zstring const> cmdArgs );
+
+int main( int argc, char * argv[] )
+{
+ auto args = gsl_lite::make_span(
+ argv, gsl_lite::narrow_failfast<std::size_t>( argc ) );
+ printCmdArgs( args );
+}
+```
+
+## Bounds-checked element access
+
+(Core Guidelines reference: [GSL.util: Utilities](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslutil-utilities))
+
+The function `gsl_lite::at( container, index )` offers bounds-checked element access for all sized containers with random access.
+Exposition-only definition:
+
+```c++
+template< class Container >
+auto at( Container& c, index i )
+{
+ gsl_Expects( i >= 0 && i < std::ssize( c ) );
+ return c[ i ];
+}
+```
+
+
+## Integer type aliases
+
+(Core Guidelines reference: [GSL.util: Utilities](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslutil-utilities))
+
+(*Note:* `dim`, `stride`, and `diff` are *gsl-lite* extensions and not part of the C++ Core Guidelines.)
+
+[Rule ES.107](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-subscripts) of the C++ Core Guidelines suggests,
+"Don't use `unsigned` for subscripts, prefer `gsl::index`," giving several good reasons for preferring a signed over an unsigned
+type for indexing. For this purpose, the GSL defines `index` as a type alias for `std::ptrdiff_t`.
+
+*gsl-lite* defines the type alias `gsl_lite::index` along with the aliases `gsl_lite::dim`, `gsl_lite::stride`, and `gsl_lite::diff`:
+
+Type alias | Purpose |
+----------:|:-----------------------------------------------|
+`index` | Signed integer type for indexes and subscripts |
+`dim` | Signed integer type for sizes |
+`stride` | Signed integer type for index strides |
+`diff` | Signed integer type for index differences |
+
+**Example:**
+```c++
+auto x = std::vector<double>{ ... };
+auto dx = std::vector<double>( x.size() - 1 );
+gsl_lite::dim n = std::ssize( x );
+for ( gsl_lite::index i = 0; i < n - 1; ++i )
+{
+ dx[ i ] = x[ i + 1 ] - x[ i ];
+}
+```
+
+`index`, `dim`, `stride`, and `diff` are all aliases for `std::ptrdiff_t` unless the [`gsl_CONFIG_INDEX_TYPE`](#gsl_config_index_typestdptrdiff_t)
+configuration macro is set to a different type (which is not recommended).
+
+
+## String type aliases
+
+(Core Guidelines reference: [GSL.view: Views](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslview-views))
+
+(*Note:* `wzstring` and `cwzstring` are *gsl-lite* extensions and not part of the C++ Core Guidelines.)
+
+*gsl-lite* defines the aliases `gsl_lite::zstring`, `gsl_lite::czstring`, `gsl_lite::wzstring`, and `gsl_lite::cwzstring` for
+C-style strings (where a C-style string is understood to be either a zero-terminated sequence of characters or a `nullptr`):
+
+Type alias | Type |
+-----------:|:------------------|
+`zstring` | `char *` |
+`czstring` | `char const *` |
+`wzstring` | `wchar_t *` |
+`cwzstring` | `wchar_t const *` |
+
+
+## Ad hoc resource management (C++11 and higher)
+
+(Core Guidelines reference: [GSL.util: Utilities](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslutil-utilities))
+
+(*Note:* `on_return()` and `on_error()` are *gsl-lite* extensions and not part of the C++ Core Guidelines.)
+
+*gsl-lite* defines the following helpers for ad hoc resource management:
+
+- `gsl_lite::finally( action )` constructs and returns an object which invokes `action` upon destruction.
+- `gsl_lite::on_return( action )` constructs and returns an object which invokes `action` upon destruction only if no exception was thrown.
+- `gsl_lite::on_error( action )` constructs and returns an object which invokes `action` upon destruction only if an exception was thrown.
+
+[Rule R.1](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#r1-manage-resources-automatically-using-resource-handles-and-raii-resource-acquisition-is-initialization)
+of the C++ Core Guidelines suggests: "Manage resources automatically using resource handles and [RAII](https://en.cppreference.com/w/cpp/language/raii)
+(Resource Acquisition Is Initialization)". While this advice is sound, it may sometimes be inconvenient to always define a resource handle type
+for every situation in which a resource needs to be cleaned up.
+
+For example, we might wish to modernize the following code which uses the [C standard library](https://en.cppreference.com/w/cpp/header/cstdio)
+to read from a file:
+```c++
+std::vector<std::string> readLines( char const * filename )
+{
+ std::FILE * file = std::fopen( filename, "r" );
+ if ( !file ) throw std::runtime_error( ... );
+ std::vector<std::string> result;
+ ... // implementation omitted
+ std::fclose( file );
+ return result;
+}
+```
+This code is not exception-safe: if the (omitted) implementation throws an exception, `fclose()` is never called on the `file` handle.
+The problem of exception safety is typically addressed by defining a resource handle type for `FILE`
+(see the [`FileHandle` example above](#nullability-and-the-moved-from-state)):
+```c++
+struct FileCloser
+{
+ void operator ()(std::FILE* file) const noexcept
+ {
+ std::fclose( file );
+ }
+};
+using FilePtr = std::unique_ptr<std::FILE, FileCloser>;
+
+std::vector<std::string> readLines( char const * filename )
+{
+ auto file = FilePtr( std::fopen( filename, "r" ) );
+ if ( !file ) throw std::runtime_error( ... );
+ std::vector<std::string> result;
+ ... // implementation omitted
+ return result;
+}
+```
+
+Alternatively, we can fix the problem by using `gsl_lite::finally()`:
+```c++
+std::vector<std::string> readLines( char const * filename )
+{
+ std::FILE * file = std::fopen( filename, "r" );
+ if ( !file ) throw std::runtime_error( ... );
+ auto _ = gsl_lite::finally( [&] { std::fclose( file ); } );
+ std::vector<std::string> result;
+ ... // implementation omitted
+ return result;
+}
+```
+The destructor of the local object `_` will call `std::fclose( file )` regardless of whether the function returns normally or is
+interrupted by an exception. This ensures that the `file` handle does not leak.
+
+
+## Feature checking macros
+
+(*Note:* Feature checking macros are a *gsl-lite* extension and not part of the C++ Core Guidelines.)
+
+The following preprocessor macros can be used to identify features of the C++ build environment:
+
+Name | Meaning |
+---------------------------------------:|:----------------|
+**Metadata:** | &nbsp; |
+`gsl_lite_MAJOR` | Major version number of *gsl-lite* |
+`gsl_lite_MINOR` | Minor version number of *gsl-lite* |
+`gsl_lite_PATCH` | Patch version number of *gsl-lite* |
+`gsl_lite_VERSION` | A string holding the semantic version number \<major\>.\<minor\>.\<patch\> of *gsl-lite* (e.g. `"1.0.0"`) |
+**Language and library support:** | &nbsp; |
+`gsl_CPPxx_OR_GREATER` | Whether C++xx language features are available<br>(substitute `11`, `14`, `17`, `20`, `23`, `26`) |
+`gsl_STDLIB_CPPXX_OR_GREATER` | Whether C++xx standard library features are available<br>(substitute `11`, `14`, `17`, `20`, `23`, `26`) |
+**Compiler version detection:** | &nbsp; |
+`gsl_BETWEEN( V, L, H )` | V ≥ L and V < H |
+`gsl_COMPILER_GNUC_VERSION` | Evaluates to version number when compiled with GNU GCC, 0 otherwise |
+`gsl_COMPILER_CLANG_VERSION` | Evaluates to version number when compiled with Clang, 0 otherwise |
+`gsl_COMPILER_MSVC_VERSION` | Evaluates to version number when compiled with Microsoft Visual C++, 0 otherwise |
+`gsl_COMPILER_APPLECLANG_VERSION` | Evaluates to version number when compiled with Apple Clang, 0 otherwise |
+`gsl_COMPILER_NVCC_VERSION` | Evaluates to version number when compiled with NVIDIA NVCC, 0 otherwise |
+`gsl_COMPILER_ARMCC_VERSION` | Evaluates to version number when compiled with ARMCC, 0 otherwise |
+`gsl_DEVICE_CODE` | Whether CUDA device code is being compiled |
+`gsl_HAVE( EXCEPTIONS )` | Evaluates to 1 if exceptions are available, 0 when compiling with exceptions disabled |
+`gsl_HAVE( WCHAR )` | Evaluates to 1 if `wchar_t` type is available, 0 otherwise |
+
+When a new revision of the C++ language is standardized, features often become available gradually in compilers and standard libraries.
+C\+\+20 introduces a set of preprocessor macros to check for the availability of [language features](https://en.cppreference.com/w/cpp/feature_test)
+and [standard library features](https://en.cppreference.com/w/cpp/feature_test#Library_features); but such macros are not necessarily available in
+implementations predating C\+\+20. For this purpose, *gsl-lite* defines a limited set of feature checking macros.
+They all follow the pattern `gsl_HAVE( xx )`, where `xx` is to be replaced by a token representing a given language feature. `gsl_HAVE( xx )` evaluates
+to 1 if the corresponding language or library feature is available, 0 otherwise.
+
+Name | Feature |
+---------------------------------------:|:----------------|
+**Language features:** | &nbsp; |
+`gsl_HAVE( C99_PREPROCESSOR )` | C99-compatible [preprocessor](https://en.cppreference.com/w/c/preprocessor) |
+`gsl_HAVE( AUTO )` | [`auto`](https://en.cppreference.com/w/cpp/language/auto) (C++11) |
+`gsl_HAVE( RVALUE_REFERENCE )` | [rvalue references](https://en.cppreference.com/w/cpp/language/reference) (C++11) |
+`gsl_HAVE( FUNCTION_REF_QUALIFIER )` | [ref-qualified member functions](https://en.cppreference.com/w/cpp/language/member_functions) (C++11) |
+`gsl_HAVE( ENUM_CLASS )` | [`enum class`](https://en.cppreference.com/w/cpp/language/enum) (C++11) |
+`gsl_HAVE( ALIAS_TEMPLATE )` | [alias templates](https://en.cppreference.com/w/cpp/language/type_alias) (C++11) |
+`gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )` | [default template arguments for function templates](https://en.cppreference.com/w/cpp/language/function_template) (C++11) |
+`gsl_HAVE( EXPLICIT )` | [`explicit`](https://en.cppreference.com/w/cpp/language/explicit) specifier (C++11) |
+`gsl_HAVE( VARIADIC_TEMPLATE )` | [variadic templates](https://en.cppreference.com/w/cpp/language/pack) (C++11) |
+`gsl_HAVE( IS_DELETE )` | [deleted functions](https://en.cppreference.com/w/cpp/keyword/delete) (C++11) |
+`gsl_HAVE( IS_DEFAULT )` | [explicitly defaulted functions](https://en.cppreference.com/w/cpp/keyword/default) (C++11) |
+`gsl_HAVE( NOEXCEPT )` | [`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec) specifier and [`noexcept()`](https://en.cppreference.com/w/cpp/language/noexcept) operator (C++11) |
+`gsl_HAVE( NORETURN )` | [`[[noreturn]]`](https://en.cppreference.com/w/cpp/language/attributes/noreturn) attribute (C++11) |
+`gsl_HAVE( EXPRESSION_SFINAE )` | [expression SFINAE](https://en.cppreference.com/w/cpp/language/sfinae) |
+`gsl_HAVE( OVERRIDE_FINAL )` | [`override`](https://en.cppreference.com/w/cpp/language/override) and [`final`](https://en.cppreference.com/w/cpp/language/final) specifiers (C++11) |
+`gsl_HAVE( DECLTYPE_AUTO )` | [`decltype(auto)`](https://en.cppreference.com/w/cpp/language/decltype) (C++11) |
+`gsl_HAVE( DEPRECATED )` | [`[[deprecated]]`](https://en.cppreference.com/w/cpp/language/attributes/deprecated) attribute (C++11) |
+`gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )` | constructing `enum class` from the underlying type (C++17) |
+`gsl_HAVE( DEDUCTION_GUIDES )` | [`class template argument deduction`](https://en.cppreference.com/w/cpp/language/class_template_argument_deduction) guides (C++17) |
+`gsl_HAVE( NODISCARD )` | [`[[nodiscard]]`](https://en.cppreference.com/w/cpp/language/attributes/nodiscard) attribute (C++17) |
+`gsl_HAVE( MAYBE_UNUSED )` | [`[[maybe_unused]]`](https://en.cppreference.com/w/cpp/language/attributes/maybe_unused) attribute (C++17) |
+`gsl_HAVE( CONSTEXPR_xx )` | C++xx [`constexpr`](https://en.cppreference.com/w/cpp/language/constexpr) features (substitute `11`, `14`, `17`, `20`, `23`, `26`) |
+**Standard library features:** | &nbsp; |
+`gsl_HAVE( ADDRESSOF )` | [`std::addressof()`](https://en.cppreference.com/w/cpp/memory/addressof) (C++11) |
+`gsl_HAVE( ARRAY )` | [`std::array<>`](https://en.cppreference.com/w/cpp/container/array) (C++11) |
+`gsl_HAVE( TYPE_TRAITS )` | [`<type_traits>`](https://en.cppreference.com/w/cpp/header/type_traits) header (C++11) |
+`gsl_HAVE( CONTAINER_DATA_METHOD )` | `data()` member function on containers |
+`gsl_HAVE( STD_DATA )` | [`std::data()`](https://en.cppreference.com/w/cpp/iterator/data) (C++17) |
+`gsl_HAVE( STD_SSIZE )` | [`std::ssize()`](https://en.cppreference.com/w/cpp/iterator/size) (C++20) |
+`gsl_HAVE( HASH )` | [`std::hash<>`](https://en.cppreference.com/w/cpp/utility/hash) (C++11) |
+`gsl_HAVE( SIZED_TYPES )` | [sized integer type aliases]() (C++11) |
+`gsl_HAVE( SHARED_PTR )` | [`std::shared_ptr<>`](https://en.cppreference.com/w/cpp/memory/shared_ptr) (C++11) |
+`gsl_HAVE( UNIQUE_PTR )` | [`std::unique_ptr<>`](https://en.cppreference.com/w/cpp/memory/unique_ptr) (C++11) |
+`gsl_HAVE( MAKE_SHARED )` | [`std::make_shared<>()`](https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared) (C++11) |
+`gsl_HAVE( MAKE_UNIQUE )` | [`std::make_unique<>()`](https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) (C++14) |
+`gsl_HAVE( MOVE_FORWARD )` | [`std::move()`](https://en.cppreference.com/w/cpp/utility/move) and [`std::forward<>()`](https://en.cppreference.com/w/cpp/utility/forward) (C++11) |
+`gsl_HAVE( NULLPTR )` | [`nullptr`](https://en.cppreference.com/w/cpp/language/nullptr) keyword (C++11) |
+`gsl_HAVE( UNCAUGHT_EXCEPTIONS )` | [`std::uncaught_exceptions()`](https://en.cppreference.com/w/cpp/error/uncaught_exception) (C++17) |
+`gsl_HAVE( INITIALIZER_LIST )` | [`std::initializer_list<>`](https://en.cppreference.com/w/cpp/utility/initializer_list) (C++11) |
+`gsl_HAVE( REMOVE_CVREF )` | [`std::remove_cvref<>`](https://en.cppreference.com/w/cpp/types/remove_cvref) (C++20) |
+
+
+## Polyfills
+
+(*Note:* Polyfills are a *gsl-lite* extension and not part of the C++ Core Guidelines.)
+
+*gsl-lite* defines some macros, types, and functions for use with earlier versions of C++:
+
+- [Keyword and attribute macros](#keyword-and-attribute-macros)
+- [Code generation macros](#code-generation-macros)
+- [Types and functions](#types-and-functions)
+
+### Keyword and attribute macros
+
+The keyword and attribute macros allow to conditionally take advantage of newer language features if available:
+
+Name | Expands to |
+---------------------------:|:----------------|
+`gsl_DIMENSION_OF( a )` | `( sizeof( a ) / sizeof( 0[ a ] ) )`, which is the number of elements in a C-style array `a` |
+`gsl_constexpr` | [`constexpr`](https://en.cppreference.com/w/cpp/language/constexpr) in C++11 and higher, to nothing otherwise |
+`gsl_constexprXX` | [`constexpr`](https://en.cppreference.com/w/cpp/language/constexpr) in C++XX and higher, to nothing otherwise<br>(substitute 14, 17, 20, 23, 26) |
+`gsl_explicit` | [`explicit`](https://en.cppreference.com/w/cpp/language/explicit) specifier in C++11 and higher, to nothing otherwise |
+`gsl_is_delete` | `= delete` in C++11 and higher, to nothing otherwise |
+`gsl_is_delete_access` | `public` in C++11 and higher, to `private` otherwise |
+`gsl_noexcept` | [`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec) specifier in C++11 and higher, to nothing otherwise |
+`gsl_noexcept_if( expr )` | [`noexcept( expr )`](https://en.cppreference.com/w/cpp/language/noexcept) operator in C++11 and higher, to nothing otherwise |
+`gsl_nullptr` | `nullptr` in C++11 and higher, to `NULL` otherwise |
+`gsl_NORETURN` | [`[[noreturn]]`](https://en.cppreference.com/w/cpp/language/attributes/noreturn) attribute in C++11 and higher, to a compiler-specific attribute if available, or to nothing otherwise |
+`gsl_DEPRECATED` | [`[[deprecated]]`](https://en.cppreference.com/w/cpp/language/attributes/deprecated) attribute in C++14 and higher, to nothing otherwise |
+`gsl_DEPRECATED_MSG( msg )` | [`[[deprecated( msg )]]`](https://en.cppreference.com/w/cpp/language/attributes/deprecated) attribute in C++14 and higher, to nothing otherwise |
+`gsl_NODISCARD` | [`[[nodiscard]]`](https://en.cppreference.com/w/cpp/language/attributes/nodiscard) attribute in C++17 and higher, to nothing otherwise |
+`gsl_MAYBE_UNUSED` | [`[[maybe_unused]]`](https://en.cppreference.com/w/cpp/language/attributes/maybe_unused) attribute in C++17 and higher, or to nothing otherwise |
+`gsl_MAYBE_UNUSED_MEMBER` | [`[[maybe_unused]]`](https://en.cppreference.com/w/cpp/language/attributes/maybe_unused) attribute in C++17 and higher if that attribute does not raise a warning when applied to class data members (as is the case for GNU GCC), or to nothing otherwise |
+`gsl_NO_UNIQUE_ADDRESS`<br>(≥ C++20) | [`[[msvc::no_unique_address]]`](https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/) for MSVC, to [`[[no_unique_address]]`](https://en.cppreference.com/w/cpp/language/attributes/no_unique_address) otherwise |
+
+### Code generation macros
+
+The following macros help avoid writing repetitive code:
+
+- `gsl_DEFINE_ENUM_BITMASK_OPERATORS( e )`:
+ Defines bitmask operators `|`, `&`, `^`, `~`, `|=`, `&=`, and `^=` for the enum type `e`.
+ Example:
+ ```c++
+ enum class Vegetables
+ {
+ tomato = 0b001,
+ onion = 0b010,
+ eggplant = 0b100
+ };
+ gsl_DEFINE_ENUM_BITMASK_OPERATORS( Vegetables )
+ ```
+
+- `gsl_DEFINE_ENUM_RELATIONAL_OPERATORS( e )`:
+ Defines relational operators (`<=>` in C++20 and newer, `<`, `>`, `<=`, and `>=` otherwise) for the enum type `e`.
+ Example:
+ ```c++
+ enum class OperatorPrecedence
+ {
+ additive = 0,
+ multiplicative = 1,
+ power = 2
+ };
+ gsl_DEFINE_ENUM_RELATIONAL_OPERATORS( OperatorPrecedence )
+ ```
+
+### Types and functions
+
+The following types and functions implement some functionality added only in later C++ standards:
+
+Name | C++ feature |
+-------------------------------------------------:|:----------------|
+`gsl_lite::std11::add_const<>` | [`std::add_const<>`](https://en.cppreference.com/w/cpp/types/add_cv) (C++11) |
+`gsl_lite::std11::remove_const<>`<br>`std11::remove_volatile<>`<br>`std11::remove_cv<>` | [`std::remove_const<>`](https://en.cppreference.com/w/cpp/types/remove_cv) (C++11)<br>[`std::remove_volatile<>`](https://en.cppreference.com/w/cpp/types/remove_cv) (C++11)<br>[`std::remove_cv<>`](https://en.cppreference.com/w/cpp/types/remove_cv) (C++11) |
+`gsl_lite::std11::remove_reference<>` | [`std::remove_reference<>`](https://en.cppreference.com/w/cpp/types/remove_reference) (C++11) |
+`gsl_lite::std11::integral_constant<>`<br>`gsl_lite::std11::true_type`<br>`gsl_lite::std11::false_type`<br>`gsl_lite::std17::bool_constant<>`| [`std::integral_constant<>`](https://en.cppreference.com/w/cpp/types/integral_constant) (C++11)<br>[`std::true_type`](https://en.cppreference.com/w/cpp/types/integral_constant) (C++11)<br>[`std::false_type`](https://en.cppreference.com/w/cpp/types/integral_constant) (C++11)<br>[`std::bool_constant<>`](https://en.cppreference.com/w/cpp/types/integral_constant) (C++17) |
+`gsl_lite::std14::make_unique<>()` | [`std::make_unique<>()`](https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) (C++14) |
+`gsl_lite::std17::uncaught_exceptions()` | [`std::uncaught_exceptions()`](https://en.cppreference.com/w/cpp/error/uncaught_exception) (C++17) |
+`gsl_lite::std17::negation<>` | [`std::negation<>`](https://en.cppreference.com/w/cpp/types/negation) (C++17) |
+`gsl_lite::std17::conjunction<>` (≥ C\+\+11) | [`std::conjunction<>`](https://en.cppreference.com/w/cpp/types/conjunction) (C++17) |
+`gsl_lite::std17::disjunction<>` (≥ C\+\+11) | [`std::disjunction<>`](https://en.cppreference.com/w/cpp/types/disjunction) (C++17) |
+`gsl_lite::std17::void_t<>` (≥ C\+\+11) | [`std::void_t<>`](https://en.cppreference.com/w/cpp/types/void_t) (C++17) |
+`gsl_lite::size()`, `gsl_lite::std17::size()`<br>`gsl_lite::ssize()`, `gsl_lite::std20::ssize()` | [`std::size()`](https://en.cppreference.com/w/cpp/iterator/size) (C++17)<br>[`std::ssize()`](https://en.cppreference.com/w/cpp/iterator/size) (C++20) |
+`gsl_lite::data()`, `gsl_lite::std17::data()` | [`std::data()`](https://en.cppreference.com/w/cpp/iterator/data) (C++17) |
+`gsl_lite::std20::endian` | [`std::endian`](https://en.cppreference.com/w/cpp/types/endian) (C++20) |
+`gsl_lite::type_identity<>`, `gsl_lite::std20::type_identity<>` | [`std::type_identity<>`](https://en.cppreference.com/w/cpp/types/type_identity) (C++20) |
+`gsl_lite::identity`, `gsl_lite::std20::identity` | [`std::identity`](https://en.cppreference.com/w/cpp/utility/functional/identity) (C++20) |
+`gsl_lite::std20::remove_cvref<>` | [`std::remove_cvref<>`](https://en.cppreference.com/w/cpp/types/remove_cvref) (C++20) |
+
+
+## Configuration options and switches
+
+- [Contract checking configuration macros](#contract-checking-configuration-macros)
+ - [Runtime enforcement](#runtime-enforcement)
+ - [Contract violation handling](#contract-violation-handling)
+ - [Unenforced contract checks](#unenforced-contract-checks)
+- [Feature selection macros](#feature-selection-macros)
+- [Other configuration macros](#other-configuration-macros)
+
+*gsl-lite* is customizable through a large number of configuration options and switches.
+The configuration of contract checks may be useful for various purposes (performance, unit testing, fail-safe environments).
+The main purpose of the other configuration options is backward compatibility.
+
+The configuration macros may affect the API and ABI of *gsl-lite* in ways that renders it incompatible with other code.
+Therefore, as a general rule, **do not define, or rely on, any of *gsl-lite*'s configuration options or switches when using *gsl-lite* in a library**.
+
+### Contract checking configuration macros
+
+With the configuration macros described in the following sections, the user can exert fine-grained control over the runtime behavior
+of contract checks expressed with [`gsl_Expects()`, `gsl_Ensures()`, `gsl_Assert()` and other contract checking macros](#contract-and-assertion-checks).
+The configuration options for contract violation response follow the suggestions originally suggested in proposal [N4415](http://wg21.link/n4415),
+with some refinements inspired by [P1710](http://wg21.link/P1710)/[P1730](http://wg21.link/P1730).
+
+
+#### Runtime enforcement
+
+The following macros control whether contracts are checked at runtime:
+
+- **`gsl_CONFIG_CONTRACT_CHECKING_AUDIT`**
+ Define this macro to have contracts expressed with `gsl_ExpectsAudit()`, `gsl_EnsuresAudit()`, and `gsl_AssertAudit()` checked
+ at runtime.
+
+- **`gsl_CONFIG_CONTRACT_CHECKING_ON` (default)**
+ Define this macro to have contracts expressed with `gsl_Expects()`, `gsl_Ensures()`, `gsl_Assert()`, and `gsl_FailFast()`
+ checked at runtime, Contracts expressed with `gsl_ExpectsDebug()`, `gsl_EnsuresDebug()`, and `gsl_AssertDebug()` are also
+ checked at runtime (unless `NDEBUG` is defined and `gsl_CONFIG_CONTRACT_CHECKING_AUDIT` is not).
+ **This is the default.**
+
+- **`NDEBUG`**
+ This macro traditionally disables runtime checks for the [`assert()`](https://en.cppreference.com/w/c/error/assert) macro from
+ the C standard library. Additionally, contracts expressed with `gsl_ExpectsDebug()`, `gsl_EnsuresDebug()`, and `gsl_AssertDebug()`
+ are not evaluated or checked at runtime if `NDEBUG` is defined and `gsl_CONFIG_CONTRACT_CHECKING_AUDIT` is not.
+
+- **`gsl_CONFIG_CONTRACT_CHECKING_OFF`**
+ Define this macro to disable all runtime checking of contracts and invariants.
+
+ Note that `gsl_FailFast()` checks will trigger runtime failure even if runtime checking is disabled.
+
+- If desired, the macros **`gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT`**, **`gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON`**, and
+ **`gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF`** can be used to configure contract checking for CUDA device code separately. If
+ neither of these macros is defined, device code uses the same configuration as host code.
+
+ It may be reasonable to define `gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF` in Release builds because the performance impact of
+ runtime checks can be grave in device code, while it is often negligible in host code.
+
+The following macros can be used to selectively disable checking for a particular kind of contract:
+
+- **`gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF`**
+ Define this macro to disable runtime checking of precondition contracts expressed with `gsl_Expects()`, `gsl_ExpectsDebug()`, and `gsl_ExpectsAudit()`.
+
+- **`gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF`**
+ Define this macro to disable runtime checking of postcondition contracts expressed with `gsl_Ensures()`, `gsl_EnsuresDebug()`, and `gsl_EnsuresAudit()`.
+
+- **`gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF`**
+ Define this macro to disable runtime checking of assertions expressed with `gsl_Assert()`, `gsl_AssertDebug()`, and `gsl_AssertAudit()`.
+
+
+#### Contract violation handling
+
+The following macros control the handling of runtime contract violations:
+
+- **`gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS` (default)**
+ If this macro is defined, and if the `assert()` macro is available for runtime checks (that is, if `NDEBUG` is not defined),
+ contract checking macros are implemented in terms of `assert()`. If `assert()` is unavailable (i.e. if `NDEBUG` was defined),
+ `std::abort()` is called directly when a contract is violated.
+ **This is the default.**
+
+ This option may be preferable over `gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES` because `assert()` prints diagnostic information
+ (such as the current source file, a line number, and the function name), and because vendor-specific extensions of `assert()`
+ can be used (for instance, the `assert()` implementation of the Microsoft C runtime displays a dialog box which permits breaking
+ into the debugger or continuing execution).
+
+ Note that `gsl_FailFast()` will call `std::abort()` if `assert()` continues execution.
+
+- **`gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES`**
+ Define this macro to call `std::terminate()` on a contract violation.
+
+- **`gsl_CONFIG_CONTRACT_VIOLATION_TRAPS`**
+ Define this macro to execute a trap instruction on a contract violation.
+
+ Trap instructions may yield smaller codegen and can thus result in better-performing code. However, they usually lead to
+ catastrophic failure and may be difficult to diagnose for some platforms.
+
+- **`gsl_CONFIG_CONTRACT_VIOLATION_THROWS`**
+ Define this macro to throw a `std::runtime_error`-derived exception `gsl_lite::fail_fast` on contract violation.
+ Handling contract violations with exceptions can be desirable when executing in an interactive programming environment, or if
+ there are other reasons why process termination must be avoided.
+
+ This setting is also useful for writing unit tests that exercise contract checks.
+
+- **`gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER`**
+ Define this macro to call a user-defined handler function `gsl_lite::fail_fast_assert_handler()` on a contract violation.
+ The user must provide a definition of the following function:
+ ```c++
+ namespace gsl_lite {
+ gsl_api void fail_fast_assert_handler(
+ char const * expression, char const * message,
+ char const * file, int line );
+ } // namespace gsl_lite
+ ```
+
+ Note that `gsl_FailFast()` will call `std::terminate()` if `fail_fast_assert_handler()` returns.
+
+- If desired, the macros **`gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS`**, **`gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS`**, and
+ **`gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER`** can be used to configure contract violation handling for CUDA device
+ code separately. If neither of these macros is defined, device code uses the following defaults:
+ - `gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES` → `gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS`
+ - `gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS` → `gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS`
+ - `gsl_CONFIG_CONTRACT_VIOLATION_THROWS` → `gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS`
+ - `gsl_CONFIG_CONTRACT_VIOLATION_TRAPS` → `gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS`
+ - `gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER` → `gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER`
+
+
+#### Unenforced contract checks
+
+The following macros control what happens with individual contract checks which are not enforced at runtime. Note that these
+macros do not disable runtime contract checking; they only configure what happens to contracts which are not checked as a result
+of configuration, e.g. for any contract check if `gsl_CONFIG_CONTRACT_CHECKING_OFF` is defined, or for audit-level and debug-level
+contract checks if `NDEBUG` is defined.
+
+- **`gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE` (default)**
+ Contract checks disabled by configuration will be discarded.
+ **This is the default.**
+
+ Note that `gsl_FailFast()` calls are never discarded.
+
+ Even for discarded contract checks, *gsl-lite* will by default still verify that the contract check forms a valid Boolean
+ expression using the C++11 features `decltype()` and `static_assert()`. This may lead to problems if the contract check
+ expression cannot be used in an unevaluated context, for instance, when using a lambda expression in C++11/14/17.
+
+ The compile-time verification of contract check expressions is controlled by the configuration macro
+ `gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS`, which defaults to *`1`*. To suppress the verification, define
+ `gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS=0`.
+
+- **`gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME`**
+ For contracts expressed with `gsl_Expects()`, `gsl_Ensures()`, and `gsl_Assert()` which are not checked as a result of
+ configuration, instruct the compiler to assume that they always hold true. This is expressed with compiler-specific intrinsics
+ such as `__assume()`.
+
+ Contract checks expressed with `gsl_ExpectsDebug()`, `gsl_EnsuresDebug()`, `gsl_AssertDebug()` , `gsl_ExpectsAudit()`,
+ `gsl_EnsuresAudit()`, and `gsl_AssertAudit()` which are not checked at runtime (due to definition of `NDEBUG` or one of the
+ aforementioned configuration macros) are discarded.
+
+ Explicitly injecting the assumption that contracts hold true implies that violating contracts causes undefined behavior. This
+ may give the compiler more opportunities for optimization, but it is usually dangerous and, like all occurrences of undefined
+ behavior, it can have devastating consequences.
+
+ The use of compiler-specific "assume" intrinsics may lead to spurious runtime evaluation of contract expressions. Because
+ *gsl-lite* implements contract checks with macros (rather than as a language feature as the defunct C++2a Contracts proposal
+ did), it cannot reliably suppress runtime evaluation for all compilers. For instance, if the contract check fed to the "assume"
+ intrinsic comprises a function call which is opaque to the compiler, many compilers will generate the runtime function call.
+ Therefore, `gsl_Expects()`, `gsl_Ensures()`, and `gsl_Assert()` should be used only for conditions that can be proven
+ side-effect-free by the compiler, and `gsl_ExpectsDebug()`, `gsl_EnsuresDebug()`, `gsl_AssertDebug()`, `gsl_ExpectsAudit()`,
+ `gsl_EnsuresAudit()`, and `gsl_AssertAudit()` for everything else. In practice, this means that `gsl_Expects()`,
+ `gsl_Ensures()`, and `gsl_Assert()` should only be used for simple comparisons of scalar values, for simple inlineable getters,
+ and for comparisons of class objects with trivially inlineable comparison operators.
+
+ Revisiting the [example given above](#contract-and-assertion-checks):
+ ```c++
+ template< class RandomIt >
+ auto median( RandomIt first, RandomIt last )
+ {
+ // Comparing iterators for equality boils down to a comparison of pointers. An optimizing
+ // compiler will inline the comparison operator and understand that the comparison is free of
+ // side-effects, and hence generate no code in `gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME` mode.
+ gsl_Expects( first != last );
+
+ // If we cannot trust the compiler to understand that this function call is free of
+ // side-effects, we should use `gsl_ExpectsDebug()` or `gsl_ExpectsAudit()`. This particular
+ // function call is expensive, so we use an audit-level contract check.
+ gsl_ExpectsAudit( std::is_sorted( first, last ) );
+
+ auto count = last - first;
+ return count % 2 != 0
+ ? first[ count / 2 ]
+ : std::midpoint( first[ count / 2 ], first[ count / 2 + 1 ] );
+ }
+ ```
+
+- If desired, the macros **`gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE`** and **`gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME`**
+ can be used to configure handling of unenforced contract checks for CUDA device code separately. If neither of these macros is
+ defined, device code uses the same configuration as host code.
+
+
+### Feature selection macros
+
+#### `gsl_FEATURE_GSL_COMPATIBILITY_MODE=0`
+
+To minimize the impact of the breaking changes, *gsl-lite* v1.0 introduces an optional *GSL compatibility mode* controlled by the new configuration switch
+`gsl_FEATURE_GSL_COMPATIBILITY_MODE`, which is is disabled by default and can be enabled by defining `gsl_FEATURE_GSL_COMPATIBILITY_MODE=1`.
+**Default is 0.**
+
+If the GSL compatibility mode is enabled, *gsl-lite* additionally makes the following global definitions:
+```c++
+namespace gsl = ::gsl_lite;
+#define Expects( x ) gsl_Expects( x )
+#define Ensures( x ) gsl_Ensures( x )
+```
+
+The GSL compatibility mode precludes the use of *gsl-lite* and Microsoft GSL in the same translation unit. Therefore, when making use of *gsl-lite*
+in a public header file of a library, the GSL compatibility mode should not be enabled.
+
+The GSL compatibility mode causes no link-time interference between *gsl-lite* and as Microsoft GSL. Both libraries may be used in the same project as
+long as no translation unit includes both at the same time.
+
+The legacy header file `<gsl/gsl-lite.hpp>` now forwards to `<gsl-lite/gsl-lite.hpp>` and implicitly enables the GSL compatibility mode. When the legacy
+header is included, it emits a warning message which urges to either migrate to header `<gsl-lite/gsl-lite.hpp>`, namespace `gsl_lite` and the prefixed
+contract checking macros `gsl_Expects()` and `gsl_Ensures()`, or to explicitly request GSL compatibility by defining `gsl_FEATURE_GSL_COMPATIBILITY_MODE=1`.
+
+#### `gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD=0`
+Provide experimental resource management helper functions [`on_return()` and `on_error()`](#ad-hoc-resource-management-c11-and-higher).
+**Default is 0.**
+
+#### `gsl_FEATURE_STRING_SPAN=0`
+String spans and related functionality are no longer part of the GSL specification. If the macro `gsl_FEATURE_STRING_SPAN` is set to 1, *gsl-lite*
+continues to provide an implementation of the class `basic_string_span<>` along with the aliases `string_span`, `cstring_span`, `wstring_span`, `cwstring_span`,
+the deprecated class `basic_zstring_span<>` with the aliases `zstring_span`, `czstring_span`, `wzstring_span`, `cwzstring_span`, and related classes and
+functions such as `to_string()`, and `ensure_z()`.
+**Default is 0.**
+
+#### `gsl_FEATURE_BYTE=0`
+The `byte` type has been superseded by [`std::byte`](https://en.cppreference.com/w/cpp/types/byte) in C++17 and thus is no longer part of the GSL specification.
+If the macro `gsl_FEATURE_BYTE` is set to 1, *gsl-lite* continues to provide an implementation of `byte` and related functions such as `as_bytes()`, `to_byte()`,
+`as_bytes()`, and `as_writable_bytes()`.
+**Default is 0.**
+
+#### `gsl_FEATURE_WITH_CONTAINER_TO_STD=0`
+Define this to the highest C++ standard (98, 3, 11, 14, 17, 20) you want to include tagged-construction via `with_container`, or 0 to disable the feature.
+**Default is 0.**
+
+#### `gsl_FEATURE_MAKE_SPAN_TO_STD=99`
+Define this to the highest C++ standard (98, 3, 11, 14, 17, 20) you want to include `make_span()` creator functions, or 0 to disable the feature.
+**Default is 99 for inclusion with any standard.**
+
+#### `gsl_FEATURE_BYTE_SPAN_TO_STD=99`
+Define this to the highest C++ standard (98, 3, 11, 14, 17, 20) you want to include `byte_span()` creator functions, or 0 to disable the feature.
+**Default is 99 for inclusion with any standard.**
+
+
+### Other configuration macros
+
+#### `gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI=0`
+Define this to 1 to explicitly acknowledge that you are using *gsl-lite* with a non-standard ABI and that you control the build flags of all components linked into your target.
+**Default is 0.**
+
+#### `gsl_api`
+
+Functions in *gsl-lite* are decorated with `gsl_api` where appropriate. Define this macro to specify your own function decoration.
+**By default `gsl_api` is defined empty for non-CUDA platforms and `__host__ __device__` for the CUDA platform.**
+
+*Note:* When a custom `gsl_api` macro is defined, *gsl-lite* emits a warning to notify the programmer that this alters the binary interface of *gsl-lite*, leading to possible ODR violations.
+The warning can be explicitly overridden by defining `gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI=1`.
+
+#### `gsl_CONFIG_DEFAULTS_VERSION=1`
+Define this macro to 0 to revert the default configuration to that of *gsl-lite* v0.\*. Cf. [Configuration changes](#configuration-changes) for a comprehensive list of configuration
+values affected by this switch.
+**Default is 1 for version-1 defaults.**
+
+*Note:* Defining `gsl_CONFIG_DEFAULTS_VERSION=0` changes the default value of [`gsl_CONFIG_INDEX_TYPE`](#gsl_config_index_typestdptrdiff_t).
+This makes *gsl-lite* emit a warning to notify the programmer that this alters the binary interface of *gsl-lite*, leading to possible ODR violations.
+The warning can be explicitly overridden by defining `gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI=1`.
+
+#### `gsl_CPLUSPLUS`
+Define this macro to override the auto-detection of the supported C++ standard if your compiler does not set the `__cplusplus` macro correctly.
+
+#### `gsl_CONFIG_DEPRECATE_TO_LEVEL=9`
+Define this to and including the level you want deprecation; see table [Deprecated features](#deprecated-features) below.
+**Default is 9.**
+
+#### `gsl_CONFIG_SPAN_INDEX_TYPE=std::size_t`
+Define this macro to the type to use for indices in `span<>` and `basic_string_span<>`.
+**Default is `std::size_t`.**
+
+*Note:* When a custom span index type is defined, *gsl-lite* emits a warning to notify the programmer that this alters the binary interface of *gsl-lite*, leading to possible ODR violations.
+The warning can be explicitly overridden by defining `gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI=1`.
+
+#### `gsl_CONFIG_INDEX_TYPE=std::ptrdiff_t`
+Define this macro to the type to use for `gsl_lite::index`, `gsl_lite::dim`, `gsl_lite::stride`, and `gsl_lite::diff`.
+**Default is `std::ptrdiff_t`.**
+
+*Note:* When a custom index type is defined, *gsl-lite* emits a warning to notify the programmer that this alters the binary interface of *gsl-lite*, leading to possible ODR violations.
+The warning can be explicitly overridden by defining `gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI=1`.
+
+#### `gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR=1`
+Define this macro to 0 to make `not_null<>`'s constructor implicit.
+**Default is 1.**
+
+Preferably, rather than defining this macro to 0, use [`not_null_ic<>`](#not_null_icp) if you desire implicit construction.
+
+#### `gsl_CONFIG_TRANSPARENT_NOT_NULL=1`
+If this macro is defined to 1, `not_null<>` supports typical member functions of the underlying smart pointer transparently (currently `get()`), while adding precondition checks.
+This is conformant behavior but may be incompatible with older code which expects that `not_null<>::get()` returns the underlying pointer itself.
+**Default is 1.**
+
+#### `gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF=0`
+Define this macro to 1 to have the legacy non-transparent version of `not_null<>::get()` return `T const &` instead of `T`. This may improve performance with types that have an expensive copy-constructor.
+This macro must not be defined if `gsl_CONFIG_TRANSPARENT_NOT_NULL` is 1.
+**Default is 0 for `T`.**
+
+#### `gsl_CONFIG_ALLOWS_SPAN_COMPARISON=0`
+Define this macro to 1 to support equality comparison and relational comparison of spans. C++20 `std::span<>` does not support comparison because semantics (deep vs. shallow) are unclear.
+**Default is 0.**
+
+#### `gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=0`
+Define this macro to 1 to support equality comparison and relational comparison of spans of different types, e.g. of different const-volatile-ness. To be able to compare a string_span with a cstring_span, non-strict span comparison must be available.
+**Default is 0.**
+
+#### `gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR=0`
+Define this macro to 1 to add the unconstrained span constructor for containers for pre-C++11 compilers that cannot constrain the constructor. This constructor may prove too greedy and interfere with other constructors.
+**Default is 0.**
+
+*Note:* An alternative is to use the constructor tagged `with_container`: `span<V> s(gsl_lite::with_container, cont)`.
+
+#### `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=1`
+If this macro is 1, `narrow<>()` always throws a `narrowing_error` exception if the narrowing conversion loses information due to truncation.
+If `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION` is 0 and `gsl_CONFIG_CONTRACT_VIOLATION_THROWS` is not defined, `narrow<>()` instead terminates on
+information loss (using `std::terminate()` if available and a trap instruction otherwise, e.g. for CUDA device code).
+**Default is 1.**
+
+*Note:* When `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION` is defined as 0, *gsl-lite* emits a warning to notify the programmer that this may lead to possible ODR violations.
+The warning can be explicitly overridden by defining `gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI=1`.
+
+#### `gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS=0`
+Define this macro to 1 to experience the by-design compile-time errors of the GSL components in the test suite.
+**Default is 0.**
+
+
+## Configuration changes, deprecated and removed features
+
+- [Configuration changes](#configuration-changes)
+- [Deprecated features](#deprecated-features)
+- [Removed features](#removed-features)
+
+### Configuration changes
+
+*gsl-lite* v1.0 changed the default values for several configuration options and switches:
+
+ - [`gsl_FEATURE_STRING_SPAN`](#gsl_feature_string_span0):
+ Version-1 default: `gsl_FEATURE_STRING_SPAN=0`
+ Version-0 default: `gsl_FEATURE_STRING_SPAN=1`
+ Reason: string spans are no longer part of the GSL specification.
+
+ - [`gsl_FEATURE_BYTE`](#gsl_feature_byte0):
+ Version-1 default: `gsl_FEATURE_BYTE=0`
+ Version-0 default: `gsl_FEATURE_BYTE=1`
+ Reason: `byte` has been superseded by [`std::byte`](https://en.cppreference.com/w/cpp/types/byte) in C++17.
+
+ - [`gsl_CONFIG_DEPRECATE_TO_LEVEL`](#gsl_config_deprecate_to_level9):
+ Version-1 default: `gsl_CONFIG_DEPRECATE_TO_LEVEL=9`
+ Version-0 default: `gsl_CONFIG_DEPRECATE_TO_LEVEL=0`
+
+ - [`gsl_CONFIG_INDEX_TYPE`](#gsl_config_index_typestdptrdiff_t):
+ Version-1 default: `std::ptrdiff_t`
+ Version-0 default: `gsl_CONFIG_SPAN_INDEX_TYPE` (defaults to `std::size_t`)
+ Reason: the GSL specifies `gsl_lite::index` to be a signed type.
+
+ - [`gsl_CONFIG_ALLOWS_SPAN_COMPARISON`](#gsl_config_allows_span_comparison0):
+ Version-1 default: `gsl_CONFIG_ALLOWS_SPAN_COMPARISON=0`
+ Version-0 default: `gsl_CONFIG_ALLOWS_SPAN_COMPARISON=1`
+ Reason: C++20 `std::span<>` does not support comparison because semantics (deep vs. shallow) are unclear.
+
+ - [`gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR`](#gsl_config_not_null_explicit_ctor1):
+ Version-1 default: `gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR=1`
+ Version-0 default: `gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR=0`
+ Reason: see [M-GSL/#395](https://github.com/Microsoft/GSL/issues/395). (Note that `not_null<>` in Microsoft GSL has an implicit
+ constructor, cf. [M-GSL/#699](https://github.com/Microsoft/GSL/issues/699).)
+
+ - [`gsl_CONFIG_TRANSPARENT_NOT_NULL`](#gsl_config_transparent_not_null1):
+ Version-1 default: `gsl_CONFIG_TRANSPARENT_NOT_NULL=1`
+ Version-0 default: `gsl_CONFIG_TRANSPARENT_NOT_NULL=0`
+ Reason: enables conformant behavior for `not_null<>::get()`.
+
+ - [`gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION`](#gsl_config_narrow_throws_on_truncation1):
+ Version-1 default: `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=1`
+ Version-0 default: `gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=0`
+ Reason: enables conformant behavior for `narrow<>()` (cf. [#52](https://github.com/gsl-lite/gsl-lite/issues/52)).
+
+ - [default runtime contract violation handling](#contract-checking-configuration-macros):
+ Version-1 default: `gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS`
+ Version-0 default: `gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES`
+ Reason: the mode enabled by `gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS` is consistent with the behavior of the `assert()` macro
+ while retaining runtime contract checks even if `NDEBUG` is defined.
+
+
+### Deprecated features
+
+The following features are deprecated since the indicated version. See macro [`gsl_CONFIG_DEPRECATE_TO_LEVEL`](#gsl_config_deprecate_to_level9) on how to control deprecation using the indicated level.
+
+Version | Level | Feature / Notes |
+-------:|:-----:|:----------------|
+ 1.0.0 | 9 | `span<>::as_span<>()` (unsafe) |
+0.41.0 | 7 | `basic_string_span<>`, `basic_zstring_span<>` and related aliases<br>(no longer part of the C++ Core Guidelines specification) |
+0.35.0 | - | `gsl_CONFIG_CONTRACT_LEVEL_ON`, `gsl_CONFIG_CONTRACT_LEVEL_OFF`, `gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY` and `gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY`<br>(use `gsl_CONFIG_CONTRACT_CHECKING_ON`, `gsl_CONFIG_CONTRACT_CHECKING_OFF`, &nbs;`gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF`, `gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF` instead) |
+0.7.0 | - | `gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR`<br>(use `gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR` instead,<br>or consider `span(with_container, cont)`) |
+
+
+### Removed features
+
+The following features are removed since the indicated version.
+
+Version | Feature / Notes |
+-------:|:----------------|
+1.0.0 | `finally()`, `on_return()`, and `on_error()` for pre-C++11 |
+&nbsp; | `Owner()` and `implicit` macros |
+&nbsp; | `basic_string_span<>`, `basic_zstring_span<>` and related aliases |
+&nbsp; | `as_writeable_bytes()`, call indexing for spans, and `span::at()` |
+&nbsp; | `span( std::nullptr_t, index_type )`<br>(`span( pointer, index_type )` is called instead) |
+&nbsp; | `span( U *, index_type )`<br>(`span( pointer, index_type )` is called instead) |
+&nbsp; | `span( std::shared_ptr<T> const & p )` |
+&nbsp; | `span( std::unique_ptr<T> const & p )` |
+&nbsp; | `span<>::length()`<br>(use `span<>::size()` instead) |
+&nbsp; | `span<>::length_bytes()`<br>(use `span<>::size_bytes()` instead) |
+&nbsp; | `span<>::as_bytes()`, `span<>::as_writeable_bytes()` |
diff --git a/thirdparty/gsl-lite/example/01-basic.cpp b/thirdparty/gsl-lite/example/01-basic.cpp
new file mode 100644
index 000000000..a593453f0
--- /dev/null
+++ b/thirdparty/gsl-lite/example/01-basic.cpp
@@ -0,0 +1,34 @@
+
+#include <gsl-lite/gsl-lite.hpp>
+
+using namespace gsl_lite;
+
+int * use( not_null<int *> p )
+{
+ // use p knowing it's not nullptr, NULL or 0.
+
+ return p;
+}
+
+struct Widget
+{
+ Widget() : owned_ptr( new int(42) ) {}
+
+ ~Widget() { delete owned_ptr; }
+
+ void work() { non_owned_ptr = use( make_not_null( owned_ptr ) ); }
+
+#if gsl_HAVE( ALIAS_TEMPLATE )
+ owner<int *> owned_ptr; // if alias template support
+#else // ! gsl_HAVE( ALIAS_TEMPLATE )
+ int * owned_ptr; // otherwise
+#endif // gsl_HAVE( ALIAS_TEMPLATE )
+
+ int * non_owned_ptr;
+};
+
+int main()
+{
+ Widget w;
+ w.work();
+}
diff --git a/thirdparty/gsl-lite/example/02-span.cpp b/thirdparty/gsl-lite/example/02-span.cpp
new file mode 100644
index 000000000..7bba66060
--- /dev/null
+++ b/thirdparty/gsl-lite/example/02-span.cpp
@@ -0,0 +1,65 @@
+// Use span
+
+#include <array>
+#include <vector>
+#include <iostream>
+
+#include <gsl-lite/gsl-lite.hpp>
+
+using namespace gsl_lite;
+
+int line = 0;
+
+void bad( int * arr, size_t num )
+{
+ std::cout << ++line << ": ";
+ for ( size_t i = 0; i != num; ++i )
+ {
+ std::cout << (i==0 ? "[":"") << arr[i] << (i!=num-1 ? ", ":"]\n");
+ }
+}
+
+void good( span<int> arr )
+{
+ std::cout << ++line << ": ";
+ for ( size_t i = 0; i != arr.size(); ++i )
+ {
+ std::cout << (i==0 ? "[":"") << arr[i] << (i!=arr.size()-1 ? ", ":"]\n");
+ }
+}
+
+int main()
+{
+ int arr[] = { 1, 2, 3, 4, 5, };
+
+ good( arr ); // 1. Good: deduce length
+
+#if gsl_CPP11_OR_GREATER
+ std::array<int, 6> ary = { 1, 2, 3, 4, 5, 6, };
+ std::vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, };
+
+ good( ary ); // 2. Good: single function handles
+ good( vec ); // 3. C-array, std::array and containers such as std::vector
+#else
+ line += 2;
+#endif
+
+ bad( arr, gsl_DIMENSION_OF(arr) ); // 4. Avoid: specify elements and length separately
+ bad( arr, 3 ); // 5. Avoid, but not wrong
+ bad( arr, 7 ); // 6. Wrong, array length exceeded
+
+#if gsl_CPP11_OR_GREATER
+ good( { arr, 3 } ); // 7. Avoid, but not wrong
+ good( { arr, 7 } ); // 8. Wrong, array length exceeded
+#else
+ good( span<int>( arr, 3 ) ); // 7. Avoid, but not wrong
+ good( span<int>( arr, 7 ) ); // 8. Wrong, array length exceeded
+#endif
+
+ span<int> s( arr );
+ good( s.first ( 3 ) ); // 9. Fine
+ good( s.last ( 3 ) ); // 10. Fine
+ good( s.subspan( 1 ) ); // 11. Fine
+ good( s.subspan( 1, 3 ) ); // 12. Fine
+ good( s.subspan( 1, 5 ) ); // 13. Run-time error, terminate
+}
diff --git a/thirdparty/gsl-lite/example/with-CPM/README.md b/thirdparty/gsl-lite/example/with-CPM/README.md
new file mode 100644
index 000000000..06e6f55b2
--- /dev/null
+++ b/thirdparty/gsl-lite/example/with-CPM/README.md
@@ -0,0 +1,30 @@
+# gsl-lite example project (CPM)
+
+
+This is a simple CMake project that demonstrates how to use *gsl-lite* with the [CPM](https://github.com/cpm-cmake/CPM.cmake) package manager.
+
+Requirements:
+
+- [CMake](https://cmake.org/) 3.20 or newer must be in the path.
+- A C++ compiler must be installed and available in the path.
+- An internet connection must be available to allow CPM to retrieve the *gsl-lite* dependency from GitHub.
+
+To set up the project, open a command-line window, navigate to the directory containing this readme, and execute the following commands:
+
+
+## Configure
+```
+cmake --preset default
+```
+
+
+## Build
+```
+cmake --build build/default --config Debug
+```
+
+## Run
+
+| Windows | Linux, MacOS |
+|----------------------------------|------------------------------------|
+| `build\default\Debug\my-program` | `./build/default/Debug/my-program` |
diff --git a/thirdparty/gsl-lite/example/with-CPM/cmake/CPM.cmake b/thirdparty/gsl-lite/example/with-CPM/cmake/CPM.cmake
new file mode 100644
index 000000000..eea292118
--- /dev/null
+++ b/thirdparty/gsl-lite/example/with-CPM/cmake/CPM.cmake
@@ -0,0 +1,1291 @@
+# CPM.cmake - CMake's missing package manager
+# ===========================================
+# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions.
+#
+# MIT License
+# -----------
+#[[
+ Copyright (c) 2019-2023 Lars Melchior and contributors
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+]]
+
+cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
+
+# Initialize logging prefix
+if(NOT CPM_INDENT)
+ set(CPM_INDENT
+ "CPM:"
+ CACHE INTERNAL ""
+ )
+endif()
+
+if(NOT COMMAND cpm_message)
+ function(cpm_message)
+ message(${ARGV})
+ endfunction()
+endif()
+
+if(DEFINED EXTRACTED_CPM_VERSION)
+ set(CURRENT_CPM_VERSION "${EXTRACTED_CPM_VERSION}${CPM_DEVELOPMENT}")
+else()
+ set(CURRENT_CPM_VERSION 0.40.8)
+endif()
+
+get_filename_component(CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" REALPATH)
+if(CPM_DIRECTORY)
+ if(NOT CPM_DIRECTORY STREQUAL CPM_CURRENT_DIRECTORY)
+ if(CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION)
+ message(
+ AUTHOR_WARNING
+ "${CPM_INDENT} \
+A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \
+It is recommended to upgrade CPM to the most recent version. \
+See https://github.com/cpm-cmake/CPM.cmake for more information."
+ )
+ endif()
+ if(${CMAKE_VERSION} VERSION_LESS "3.17.0")
+ include(FetchContent)
+ endif()
+ return()
+ endif()
+
+ get_property(
+ CPM_INITIALIZED GLOBAL ""
+ PROPERTY CPM_INITIALIZED
+ SET
+ )
+ if(CPM_INITIALIZED)
+ return()
+ endif()
+endif()
+
+if(CURRENT_CPM_VERSION MATCHES "development-version")
+ message(
+ WARNING "${CPM_INDENT} Your project is using an unstable development version of CPM.cmake. \
+Please update to a recent release if possible. \
+See https://github.com/cpm-cmake/CPM.cmake for details."
+ )
+endif()
+
+set_property(GLOBAL PROPERTY CPM_INITIALIZED true)
+
+macro(cpm_set_policies)
+ # the policy allows us to change options without caching
+ cmake_policy(SET CMP0077 NEW)
+ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
+
+ # the policy allows us to change set(CACHE) without caching
+ if(POLICY CMP0126)
+ cmake_policy(SET CMP0126 NEW)
+ set(CMAKE_POLICY_DEFAULT_CMP0126 NEW)
+ endif()
+
+ # The policy uses the download time for timestamp, instead of the timestamp in the archive. This
+ # allows for proper rebuilds when a projects url changes
+ if(POLICY CMP0135)
+ cmake_policy(SET CMP0135 NEW)
+ set(CMAKE_POLICY_DEFAULT_CMP0135 NEW)
+ endif()
+
+ # treat relative git repository paths as being relative to the parent project's remote
+ if(POLICY CMP0150)
+ cmake_policy(SET CMP0150 NEW)
+ set(CMAKE_POLICY_DEFAULT_CMP0150 NEW)
+ endif()
+endmacro()
+cpm_set_policies()
+
+option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies"
+ $ENV{CPM_USE_LOCAL_PACKAGES}
+)
+option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies"
+ $ENV{CPM_LOCAL_PACKAGES_ONLY}
+)
+option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL})
+option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package"
+ $ENV{CPM_DONT_UPDATE_MODULE_PATH}
+)
+option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path"
+ $ENV{CPM_DONT_CREATE_PACKAGE_LOCK}
+)
+option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK
+ "Add all packages added through CPM.cmake to the package lock"
+ $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK}
+)
+option(CPM_USE_NAMED_CACHE_DIRECTORIES
+ "Use additional directory of package name in cache on the most nested level."
+ $ENV{CPM_USE_NAMED_CACHE_DIRECTORIES}
+)
+
+set(CPM_VERSION
+ ${CURRENT_CPM_VERSION}
+ CACHE INTERNAL ""
+)
+set(CPM_DIRECTORY
+ ${CPM_CURRENT_DIRECTORY}
+ CACHE INTERNAL ""
+)
+set(CPM_FILE
+ ${CMAKE_CURRENT_LIST_FILE}
+ CACHE INTERNAL ""
+)
+set(CPM_PACKAGES
+ ""
+ CACHE INTERNAL ""
+)
+set(CPM_DRY_RUN
+ OFF
+ CACHE INTERNAL "Don't download or configure dependencies (for testing)"
+)
+
+if(DEFINED ENV{CPM_SOURCE_CACHE})
+ set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE})
+else()
+ set(CPM_SOURCE_CACHE_DEFAULT OFF)
+endif()
+
+set(CPM_SOURCE_CACHE
+ ${CPM_SOURCE_CACHE_DEFAULT}
+ CACHE PATH "Directory to download CPM dependencies"
+)
+
+if(NOT CPM_DONT_UPDATE_MODULE_PATH AND NOT DEFINED CMAKE_FIND_PACKAGE_REDIRECTS_DIR)
+ set(CPM_MODULE_PATH
+ "${CMAKE_BINARY_DIR}/CPM_modules"
+ CACHE INTERNAL ""
+ )
+ # remove old modules
+ file(REMOVE_RECURSE ${CPM_MODULE_PATH})
+ file(MAKE_DIRECTORY ${CPM_MODULE_PATH})
+ # locally added CPM modules should override global packages
+ set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}")
+endif()
+
+if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
+ set(CPM_PACKAGE_LOCK_FILE
+ "${CMAKE_BINARY_DIR}/cpm-package-lock.cmake"
+ CACHE INTERNAL ""
+ )
+ file(WRITE ${CPM_PACKAGE_LOCK_FILE}
+ "# CPM Package Lock\n# This file should be committed to version control\n\n"
+ )
+endif()
+
+include(FetchContent)
+
+# Try to infer package name from git repository uri (path or url)
+function(cpm_package_name_from_git_uri URI RESULT)
+ if("${URI}" MATCHES "([^/:]+)/?.git/?$")
+ set(${RESULT}
+ ${CMAKE_MATCH_1}
+ PARENT_SCOPE
+ )
+ else()
+ unset(${RESULT} PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Try to infer package name and version from a url
+function(cpm_package_name_and_ver_from_url url outName outVer)
+ if(url MATCHES "[/\\?]([a-zA-Z0-9_\\.-]+)\\.(tar|tar\\.gz|tar\\.bz2|zip|ZIP)(\\?|/|$)")
+ # We matched an archive
+ set(filename "${CMAKE_MATCH_1}")
+
+ if(filename MATCHES "([a-zA-Z0-9_\\.-]+)[_-]v?(([0-9]+\\.)*[0-9]+[a-zA-Z0-9]*)")
+ # We matched <name>-<version> (ie foo-1.2.3)
+ set(${outName}
+ "${CMAKE_MATCH_1}"
+ PARENT_SCOPE
+ )
+ set(${outVer}
+ "${CMAKE_MATCH_2}"
+ PARENT_SCOPE
+ )
+ elseif(filename MATCHES "(([0-9]+\\.)+[0-9]+[a-zA-Z0-9]*)")
+ # We couldn't find a name, but we found a version
+ #
+ # In many cases (which we don't handle here) the url would look something like
+ # `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly
+ # distinguish the package name from the irrelevant bits. Moreover if we try to match the
+ # package name from the filename, we'd get bogus at best.
+ unset(${outName} PARENT_SCOPE)
+ set(${outVer}
+ "${CMAKE_MATCH_1}"
+ PARENT_SCOPE
+ )
+ else()
+ # Boldly assume that the file name is the package name.
+ #
+ # Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but
+ # such cases should be quite rare. No popular service does this... we think.
+ set(${outName}
+ "${filename}"
+ PARENT_SCOPE
+ )
+ unset(${outVer} PARENT_SCOPE)
+ endif()
+ else()
+ # No ideas yet what to do with non-archives
+ unset(${outName} PARENT_SCOPE)
+ unset(${outVer} PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(cpm_find_package NAME VERSION)
+ string(REPLACE " " ";" EXTRA_ARGS "${ARGN}")
+ find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET)
+ if(${CPM_ARGS_NAME}_FOUND)
+ if(DEFINED ${CPM_ARGS_NAME}_VERSION)
+ set(VERSION ${${CPM_ARGS_NAME}_VERSION})
+ endif()
+ cpm_message(STATUS "${CPM_INDENT} Using local package ${CPM_ARGS_NAME}@${VERSION}")
+ CPMRegisterPackage(${CPM_ARGS_NAME} "${VERSION}")
+ set(CPM_PACKAGE_FOUND
+ YES
+ PARENT_SCOPE
+ )
+ else()
+ set(CPM_PACKAGE_FOUND
+ NO
+ PARENT_SCOPE
+ )
+ endif()
+endfunction()
+
+# Create a custom FindXXX.cmake module for a CPM package This prevents `find_package(NAME)` from
+# finding the system library
+function(cpm_create_module_file Name)
+ if(NOT CPM_DONT_UPDATE_MODULE_PATH)
+ if(DEFINED CMAKE_FIND_PACKAGE_REDIRECTS_DIR)
+ # Redirect find_package calls to the CPM package. This is what FetchContent does when you set
+ # OVERRIDE_FIND_PACKAGE. The CMAKE_FIND_PACKAGE_REDIRECTS_DIR works for find_package in CONFIG
+ # mode, unlike the Find${Name}.cmake fallback. CMAKE_FIND_PACKAGE_REDIRECTS_DIR is not defined
+ # in script mode, or in CMake < 3.24.
+ # https://cmake.org/cmake/help/latest/module/FetchContent.html#fetchcontent-find-package-integration-examples
+ string(TOLOWER ${Name} NameLower)
+ file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${NameLower}-config.cmake
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/${NameLower}-extra.cmake\" OPTIONAL)\n"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/${Name}Extra.cmake\" OPTIONAL)\n"
+ )
+ file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${NameLower}-config-version.cmake
+ "set(PACKAGE_VERSION_COMPATIBLE TRUE)\n" "set(PACKAGE_VERSION_EXACT TRUE)\n"
+ )
+ else()
+ file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake
+ "include(\"${CPM_FILE}\")\n${ARGN}\nset(${Name}_FOUND TRUE)"
+ )
+ endif()
+ endif()
+endfunction()
+
+# Find a package locally or fallback to CPMAddPackage
+function(CPMFindPackage)
+ set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS)
+
+ cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN})
+
+ if(NOT DEFINED CPM_ARGS_VERSION)
+ if(DEFINED CPM_ARGS_GIT_TAG)
+ cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION)
+ endif()
+ endif()
+
+ set(downloadPackage ${CPM_DOWNLOAD_ALL})
+ if(DEFINED CPM_DOWNLOAD_${CPM_ARGS_NAME})
+ set(downloadPackage ${CPM_DOWNLOAD_${CPM_ARGS_NAME}})
+ elseif(DEFINED ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}})
+ set(downloadPackage $ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}})
+ endif()
+ if(downloadPackage)
+ CPMAddPackage(${ARGN})
+ cpm_export_variables(${CPM_ARGS_NAME})
+ return()
+ endif()
+
+ cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})
+
+ if(NOT CPM_PACKAGE_FOUND)
+ CPMAddPackage(${ARGN})
+ cpm_export_variables(${CPM_ARGS_NAME})
+ endif()
+
+endfunction()
+
+# checks if a package has been added before
+function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION)
+ if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES)
+ CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION)
+ if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}")
+ message(
+ WARNING
+ "${CPM_INDENT} Requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})."
+ )
+ endif()
+ cpm_get_fetch_properties(${CPM_ARGS_NAME})
+ set(${CPM_ARGS_NAME}_ADDED NO)
+ set(CPM_PACKAGE_ALREADY_ADDED
+ YES
+ PARENT_SCOPE
+ )
+ cpm_export_variables(${CPM_ARGS_NAME})
+ else()
+ set(CPM_PACKAGE_ALREADY_ADDED
+ NO
+ PARENT_SCOPE
+ )
+ endif()
+endfunction()
+
+# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of
+# arguments which can then be parsed idiomatically. For example gh:foo/[email protected] will be converted
+# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3
+function(cpm_parse_add_package_single_arg arg outArgs)
+ # Look for a scheme
+ if("${arg}" MATCHES "^([a-zA-Z]+):(.+)$")
+ string(TOLOWER "${CMAKE_MATCH_1}" scheme)
+ set(uri "${CMAKE_MATCH_2}")
+
+ # Check for CPM-specific schemes
+ if(scheme STREQUAL "gh")
+ set(out "GITHUB_REPOSITORY;${uri}")
+ set(packageType "git")
+ elseif(scheme STREQUAL "gl")
+ set(out "GITLAB_REPOSITORY;${uri}")
+ set(packageType "git")
+ elseif(scheme STREQUAL "bb")
+ set(out "BITBUCKET_REPOSITORY;${uri}")
+ set(packageType "git")
+ # A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine
+ # type
+ elseif(arg MATCHES ".git/?(@|#|$)")
+ set(out "GIT_REPOSITORY;${arg}")
+ set(packageType "git")
+ else()
+ # Fall back to a URL
+ set(out "URL;${arg}")
+ set(packageType "archive")
+
+ # We could also check for SVN since FetchContent supports it, but SVN is so rare these days.
+ # We just won't bother with the additional complexity it will induce in this function. SVN is
+ # done by multi-arg
+ endif()
+ else()
+ if(arg MATCHES ".git/?(@|#|$)")
+ set(out "GIT_REPOSITORY;${arg}")
+ set(packageType "git")
+ else()
+ # Give up
+ message(FATAL_ERROR "${CPM_INDENT} Can't determine package type of '${arg}'")
+ endif()
+ endif()
+
+ # For all packages we interpret @... as version. Only replace the last occurrence. Thus URIs
+ # containing '@' can be used
+ string(REGEX REPLACE "@([^@]+)$" ";VERSION;\\1" out "${out}")
+
+ # Parse the rest according to package type
+ if(packageType STREQUAL "git")
+ # For git repos we interpret #... as a tag or branch or commit hash
+ string(REGEX REPLACE "#([^#]+)$" ";GIT_TAG;\\1" out "${out}")
+ elseif(packageType STREQUAL "archive")
+ # For archives we interpret #... as a URL hash.
+ string(REGEX REPLACE "#([^#]+)$" ";URL_HASH;\\1" out "${out}")
+ # We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url
+ # should do this at a later point
+ else()
+ # We should never get here. This is an assertion and hitting it means there's a problem with the
+ # code above. A packageType was set, but not handled by this if-else.
+ message(FATAL_ERROR "${CPM_INDENT} Unsupported package type '${packageType}' of '${arg}'")
+ endif()
+
+ set(${outArgs}
+ ${out}
+ PARENT_SCOPE
+ )
+endfunction()
+
+# Check that the working directory for a git repo is clean
+function(cpm_check_git_working_dir_is_clean repoPath gitTag isClean)
+
+ find_package(Git REQUIRED)
+
+ if(NOT GIT_EXECUTABLE)
+ # No git executable, assume directory is clean
+ set(${isClean}
+ TRUE
+ PARENT_SCOPE
+ )
+ return()
+ endif()
+
+ # check for uncommitted changes
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} status --porcelain
+ RESULT_VARIABLE resultGitStatus
+ OUTPUT_VARIABLE repoStatus
+ OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET
+ WORKING_DIRECTORY ${repoPath}
+ )
+ if(resultGitStatus)
+ # not supposed to happen, assume clean anyway
+ message(WARNING "${CPM_INDENT} Calling git status on folder ${repoPath} failed")
+ set(${isClean}
+ TRUE
+ PARENT_SCOPE
+ )
+ return()
+ endif()
+
+ if(NOT "${repoStatus}" STREQUAL "")
+ set(${isClean}
+ FALSE
+ PARENT_SCOPE
+ )
+ return()
+ endif()
+
+ # check for committed changes
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} diff -s --exit-code ${gitTag}
+ RESULT_VARIABLE resultGitDiff
+ OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_QUIET
+ WORKING_DIRECTORY ${repoPath}
+ )
+
+ if(${resultGitDiff} EQUAL 0)
+ set(${isClean}
+ TRUE
+ PARENT_SCOPE
+ )
+ else()
+ set(${isClean}
+ FALSE
+ PARENT_SCOPE
+ )
+ endif()
+
+endfunction()
+
+# Add PATCH_COMMAND to CPM_ARGS_UNPARSED_ARGUMENTS. This method consumes a list of files in ARGN
+# then generates a `PATCH_COMMAND` appropriate for `ExternalProject_Add()`. This command is appended
+# to the parent scope's `CPM_ARGS_UNPARSED_ARGUMENTS`.
+function(cpm_add_patches)
+ # Return if no patch files are supplied.
+ if(NOT ARGN)
+ return()
+ endif()
+
+ # Find the patch program.
+ find_program(PATCH_EXECUTABLE patch)
+ if(CMAKE_HOST_WIN32 AND NOT PATCH_EXECUTABLE)
+ # The Windows git executable is distributed with patch.exe. Find the path to the executable, if
+ # it exists, then search `../usr/bin` and `../../usr/bin` for patch.exe.
+ find_package(Git QUIET)
+ if(GIT_EXECUTABLE)
+ get_filename_component(extra_search_path ${GIT_EXECUTABLE} DIRECTORY)
+ get_filename_component(extra_search_path_1up ${extra_search_path} DIRECTORY)
+ get_filename_component(extra_search_path_2up ${extra_search_path_1up} DIRECTORY)
+ find_program(
+ PATCH_EXECUTABLE patch HINTS "${extra_search_path_1up}/usr/bin"
+ "${extra_search_path_2up}/usr/bin"
+ )
+ endif()
+ endif()
+ if(NOT PATCH_EXECUTABLE)
+ message(FATAL_ERROR "Couldn't find `patch` executable to use with PATCHES keyword.")
+ endif()
+
+ # Create a temporary
+ set(temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS})
+
+ # Ensure each file exists (or error out) and add it to the list.
+ set(first_item True)
+ foreach(PATCH_FILE ${ARGN})
+ # Make sure the patch file exists, if we can't find it, try again in the current directory.
+ if(NOT EXISTS "${PATCH_FILE}")
+ if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}")
+ message(FATAL_ERROR "Couldn't find patch file: '${PATCH_FILE}'")
+ endif()
+ set(PATCH_FILE "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}")
+ endif()
+
+ # Convert to absolute path for use with patch file command.
+ get_filename_component(PATCH_FILE "${PATCH_FILE}" ABSOLUTE)
+
+ # The first patch entry must be preceded by "PATCH_COMMAND" while the following items are
+ # preceded by "&&".
+ if(first_item)
+ set(first_item False)
+ list(APPEND temp_list "PATCH_COMMAND")
+ else()
+ list(APPEND temp_list "&&")
+ endif()
+ # Add the patch command to the list
+ list(APPEND temp_list "${PATCH_EXECUTABLE}" "-p1" "<" "${PATCH_FILE}")
+ endforeach()
+
+ # Move temp out into parent scope.
+ set(CPM_ARGS_UNPARSED_ARGUMENTS
+ ${temp_list}
+ PARENT_SCOPE
+ )
+
+endfunction()
+
+# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload
+# FetchContent calls. As these are internal cmake properties, this method should be used carefully
+# and may need modification in future CMake versions. Source:
+# https://github.com/Kitware/CMake/blob/dc3d0b5a0a7d26d43d6cfeb511e224533b5d188f/Modules/FetchContent.cmake#L1152
+function(cpm_override_fetchcontent contentName)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "SOURCE_DIR;BINARY_DIR" "")
+ if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "${CPM_INDENT} Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}")
+ endif()
+
+ string(TOLOWER ${contentName} contentNameLower)
+ set(prefix "_FetchContent_${contentNameLower}")
+
+ set(propertyName "${prefix}_sourceDir")
+ define_property(
+ GLOBAL
+ PROPERTY ${propertyName}
+ BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
+ FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
+ )
+ set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}")
+
+ set(propertyName "${prefix}_binaryDir")
+ define_property(
+ GLOBAL
+ PROPERTY ${propertyName}
+ BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
+ FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
+ )
+ set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}")
+
+ set(propertyName "${prefix}_populated")
+ define_property(
+ GLOBAL
+ PROPERTY ${propertyName}
+ BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
+ FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
+ )
+ set_property(GLOBAL PROPERTY ${propertyName} TRUE)
+endfunction()
+
+# Download and add a package from source
+function(CPMAddPackage)
+ cpm_set_policies()
+
+ list(LENGTH ARGN argnLength)
+ if(argnLength EQUAL 1)
+ cpm_parse_add_package_single_arg("${ARGN}" ARGN)
+
+ # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM
+ set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;")
+ endif()
+
+ set(oneValueArgs
+ NAME
+ FORCE
+ VERSION
+ GIT_TAG
+ DOWNLOAD_ONLY
+ GITHUB_REPOSITORY
+ GITLAB_REPOSITORY
+ BITBUCKET_REPOSITORY
+ GIT_REPOSITORY
+ SOURCE_DIR
+ FIND_PACKAGE_ARGUMENTS
+ NO_CACHE
+ SYSTEM
+ GIT_SHALLOW
+ EXCLUDE_FROM_ALL
+ SOURCE_SUBDIR
+ CUSTOM_CACHE_KEY
+ )
+
+ set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES)
+
+ cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}")
+
+ # Set default values for arguments
+
+ if(NOT DEFINED CPM_ARGS_VERSION)
+ if(DEFINED CPM_ARGS_GIT_TAG)
+ cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION)
+ endif()
+ endif()
+
+ if(CPM_ARGS_DOWNLOAD_ONLY)
+ set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY})
+ else()
+ set(DOWNLOAD_ONLY NO)
+ endif()
+
+ if(DEFINED CPM_ARGS_GITHUB_REPOSITORY)
+ set(CPM_ARGS_GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git")
+ elseif(DEFINED CPM_ARGS_GITLAB_REPOSITORY)
+ set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git")
+ elseif(DEFINED CPM_ARGS_BITBUCKET_REPOSITORY)
+ set(CPM_ARGS_GIT_REPOSITORY "https://bitbucket.org/${CPM_ARGS_BITBUCKET_REPOSITORY}.git")
+ endif()
+
+ if(DEFINED CPM_ARGS_GIT_REPOSITORY)
+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY})
+ if(NOT DEFINED CPM_ARGS_GIT_TAG)
+ set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION})
+ endif()
+
+ # If a name wasn't provided, try to infer it from the git repo
+ if(NOT DEFINED CPM_ARGS_NAME)
+ cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME)
+ endif()
+ endif()
+
+ set(CPM_SKIP_FETCH FALSE)
+
+ if(DEFINED CPM_ARGS_GIT_TAG)
+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG})
+ # If GIT_SHALLOW is explicitly specified, honor the value.
+ if(DEFINED CPM_ARGS_GIT_SHALLOW)
+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW})
+ endif()
+ endif()
+
+ if(DEFINED CPM_ARGS_URL)
+ # If a name or version aren't provided, try to infer them from the URL
+ list(GET CPM_ARGS_URL 0 firstUrl)
+ cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl)
+ # If we fail to obtain name and version from the first URL, we could try other URLs if any.
+ # However multiple URLs are expected to be quite rare, so for now we won't bother.
+
+ # If the caller provided their own name and version, they trump the inferred ones.
+ if(NOT DEFINED CPM_ARGS_NAME)
+ set(CPM_ARGS_NAME ${nameFromUrl})
+ endif()
+ if(NOT DEFINED CPM_ARGS_VERSION)
+ set(CPM_ARGS_VERSION ${verFromUrl})
+ endif()
+
+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL "${CPM_ARGS_URL}")
+ endif()
+
+ # Check for required arguments
+
+ if(NOT DEFINED CPM_ARGS_NAME)
+ message(
+ FATAL_ERROR
+ "${CPM_INDENT} 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'"
+ )
+ endif()
+
+ # Check if package has been added before
+ cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")
+ if(CPM_PACKAGE_ALREADY_ADDED)
+ cpm_export_variables(${CPM_ARGS_NAME})
+ return()
+ endif()
+
+ # Check for manual overrides
+ if(NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "")
+ set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE})
+ set(CPM_${CPM_ARGS_NAME}_SOURCE "")
+ CPMAddPackage(
+ NAME "${CPM_ARGS_NAME}"
+ SOURCE_DIR "${PACKAGE_SOURCE}"
+ EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL}"
+ SYSTEM "${CPM_ARGS_SYSTEM}"
+ PATCHES "${CPM_ARGS_PATCHES}"
+ OPTIONS "${CPM_ARGS_OPTIONS}"
+ SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR}"
+ DOWNLOAD_ONLY "${DOWNLOAD_ONLY}"
+ FORCE True
+ )
+ cpm_export_variables(${CPM_ARGS_NAME})
+ return()
+ endif()
+
+ # Check for available declaration
+ if(NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "")
+ set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}})
+ set(CPM_DECLARATION_${CPM_ARGS_NAME} "")
+ CPMAddPackage(${declaration})
+ cpm_export_variables(${CPM_ARGS_NAME})
+ # checking again to ensure version and option compatibility
+ cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")
+ return()
+ endif()
+
+ if(NOT CPM_ARGS_FORCE)
+ if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY)
+ cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})
+
+ if(CPM_PACKAGE_FOUND)
+ cpm_export_variables(${CPM_ARGS_NAME})
+ return()
+ endif()
+
+ if(CPM_LOCAL_PACKAGES_ONLY)
+ message(
+ SEND_ERROR
+ "${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})"
+ )
+ endif()
+ endif()
+ endif()
+
+ CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}")
+
+ if(DEFINED CPM_ARGS_GIT_TAG)
+ set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}")
+ elseif(DEFINED CPM_ARGS_SOURCE_DIR)
+ set(PACKAGE_INFO "${CPM_ARGS_SOURCE_DIR}")
+ else()
+ set(PACKAGE_INFO "${CPM_ARGS_VERSION}")
+ endif()
+
+ if(DEFINED FETCHCONTENT_BASE_DIR)
+ # respect user's FETCHCONTENT_BASE_DIR if set
+ set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR})
+ else()
+ set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps)
+ endif()
+
+ cpm_add_patches(${CPM_ARGS_PATCHES})
+
+ if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND)
+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND})
+ elseif(DEFINED CPM_ARGS_SOURCE_DIR)
+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR})
+ if(NOT IS_ABSOLUTE ${CPM_ARGS_SOURCE_DIR})
+ # Expand `CPM_ARGS_SOURCE_DIR` relative path. This is important because EXISTS doesn't work
+ # for relative paths.
+ get_filename_component(
+ source_directory ${CPM_ARGS_SOURCE_DIR} REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}
+ )
+ else()
+ set(source_directory ${CPM_ARGS_SOURCE_DIR})
+ endif()
+ if(NOT EXISTS ${source_directory})
+ string(TOLOWER ${CPM_ARGS_NAME} lower_case_name)
+ # remove timestamps so CMake will re-download the dependency
+ file(REMOVE_RECURSE "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild")
+ endif()
+ elseif(CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE)
+ string(TOLOWER ${CPM_ARGS_NAME} lower_case_name)
+ set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS})
+ list(SORT origin_parameters)
+ if(CPM_ARGS_CUSTOM_CACHE_KEY)
+ # Application set a custom unique directory name
+ set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${CPM_ARGS_CUSTOM_CACHE_KEY})
+ elseif(CPM_USE_NAMED_CACHE_DIRECTORIES)
+ string(SHA1 origin_hash "${origin_parameters};NEW_CACHE_STRUCTURE_TAG")
+ set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}/${CPM_ARGS_NAME})
+ else()
+ string(SHA1 origin_hash "${origin_parameters}")
+ set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash})
+ endif()
+ # Expand `download_directory` relative path. This is important because EXISTS doesn't work for
+ # relative paths.
+ get_filename_component(download_directory ${download_directory} ABSOLUTE)
+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory})
+
+ if(CPM_SOURCE_CACHE)
+ file(LOCK ${download_directory}/../cmake.lock)
+ endif()
+
+ if(EXISTS ${download_directory})
+ if(CPM_SOURCE_CACHE)
+ file(LOCK ${download_directory}/../cmake.lock RELEASE)
+ endif()
+
+ cpm_store_fetch_properties(
+ ${CPM_ARGS_NAME} "${download_directory}"
+ "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build"
+ )
+ cpm_get_fetch_properties("${CPM_ARGS_NAME}")
+
+ if(DEFINED CPM_ARGS_GIT_TAG AND NOT (PATCH_COMMAND IN_LIST CPM_ARGS_UNPARSED_ARGUMENTS))
+ # warn if cache has been changed since checkout
+ cpm_check_git_working_dir_is_clean(${download_directory} ${CPM_ARGS_GIT_TAG} IS_CLEAN)
+ if(NOT ${IS_CLEAN})
+ message(
+ WARNING "${CPM_INDENT} Cache for ${CPM_ARGS_NAME} (${download_directory}) is dirty"
+ )
+ endif()
+ endif()
+
+ cpm_add_subdirectory(
+ "${CPM_ARGS_NAME}"
+ "${DOWNLOAD_ONLY}"
+ "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"
+ "${${CPM_ARGS_NAME}_BINARY_DIR}"
+ "${CPM_ARGS_EXCLUDE_FROM_ALL}"
+ "${CPM_ARGS_SYSTEM}"
+ "${CPM_ARGS_OPTIONS}"
+ )
+ set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}")
+
+ # As the source dir is already cached/populated, we override the call to FetchContent.
+ set(CPM_SKIP_FETCH TRUE)
+ cpm_override_fetchcontent(
+ "${lower_case_name}" SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"
+ BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}"
+ )
+
+ else()
+ # Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but
+ # it should guarantee no commit hash get mis-detected.
+ if(NOT DEFINED CPM_ARGS_GIT_SHALLOW)
+ cpm_is_git_tag_commit_hash("${CPM_ARGS_GIT_TAG}" IS_HASH)
+ if(NOT ${IS_HASH})
+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE)
+ endif()
+ endif()
+
+ # remove timestamps so CMake will re-download the dependency
+ file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild)
+ set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}")
+ endif()
+ endif()
+
+ if(NOT "${DOWNLOAD_ONLY}")
+ cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(\"${ARGN}\")")
+ endif()
+
+ if(CPM_PACKAGE_LOCK_ENABLED)
+ if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK)
+ cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")
+ elseif(CPM_ARGS_SOURCE_DIR)
+ cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory")
+ else()
+ cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")
+ endif()
+ endif()
+
+ cpm_message(
+ STATUS "${CPM_INDENT} Adding package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (${PACKAGE_INFO})"
+ )
+
+ if(NOT CPM_SKIP_FETCH)
+ # CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare.
+ # Calling FetchContent_MakeAvailable will then internally forward these options to
+ # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and
+ # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30.
+ # A Bug in CMake prevents us to use the non-deprecated functions until 3.30.3.
+ set(fetchContentDeclareExtraArgs "")
+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30.3")
+ if(${CPM_ARGS_EXCLUDE_FROM_ALL})
+ list(APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL)
+ endif()
+ if(${CPM_ARGS_SYSTEM})
+ list(APPEND fetchContentDeclareExtraArgs SYSTEM)
+ endif()
+ if(DEFINED CPM_ARGS_SOURCE_SUBDIR)
+ list(APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR})
+ endif()
+ # For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory
+ if(CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY)
+ foreach(OPTION ${CPM_ARGS_OPTIONS})
+ cpm_parse_option("${OPTION}")
+ set(${OPTION_KEY} "${OPTION_VALUE}")
+ endforeach()
+ endif()
+ endif()
+ cpm_declare_fetch(
+ "${CPM_ARGS_NAME}" ${fetchContentDeclareExtraArgs} "${CPM_ARGS_UNPARSED_ARGUMENTS}"
+ )
+
+ cpm_fetch_package("${CPM_ARGS_NAME}" ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS})
+ if(CPM_SOURCE_CACHE AND download_directory)
+ file(LOCK ${download_directory}/../cmake.lock RELEASE)
+ endif()
+ if(${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.30.3")
+ cpm_add_subdirectory(
+ "${CPM_ARGS_NAME}"
+ "${DOWNLOAD_ONLY}"
+ "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"
+ "${${CPM_ARGS_NAME}_BINARY_DIR}"
+ "${CPM_ARGS_EXCLUDE_FROM_ALL}"
+ "${CPM_ARGS_SYSTEM}"
+ "${CPM_ARGS_OPTIONS}"
+ )
+ endif()
+ cpm_get_fetch_properties("${CPM_ARGS_NAME}")
+ endif()
+
+ set(${CPM_ARGS_NAME}_ADDED YES)
+ cpm_export_variables("${CPM_ARGS_NAME}")
+endfunction()
+
+# Fetch a previously declared package
+macro(CPMGetPackage Name)
+ if(DEFINED "CPM_DECLARATION_${Name}")
+ CPMAddPackage(NAME ${Name})
+ else()
+ message(SEND_ERROR "${CPM_INDENT} Cannot retrieve package ${Name}: no declaration available")
+ endif()
+endmacro()
+
+# export variables available to the caller to the parent scope expects ${CPM_ARGS_NAME} to be set
+macro(cpm_export_variables name)
+ set(${name}_SOURCE_DIR
+ "${${name}_SOURCE_DIR}"
+ PARENT_SCOPE
+ )
+ set(${name}_BINARY_DIR
+ "${${name}_BINARY_DIR}"
+ PARENT_SCOPE
+ )
+ set(${name}_ADDED
+ "${${name}_ADDED}"
+ PARENT_SCOPE
+ )
+ set(CPM_LAST_PACKAGE_NAME
+ "${name}"
+ PARENT_SCOPE
+ )
+endmacro()
+
+# declares a package, so that any call to CPMAddPackage for the package name will use these
+# arguments instead. Previous declarations will not be overridden.
+macro(CPMDeclarePackage Name)
+ if(NOT DEFINED "CPM_DECLARATION_${Name}")
+ set("CPM_DECLARATION_${Name}" "${ARGN}")
+ endif()
+endmacro()
+
+function(cpm_add_to_package_lock Name)
+ if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
+ cpm_prettify_package_arguments(PRETTY_ARGN false ${ARGN})
+ file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name}\n${PRETTY_ARGN})\n")
+ endif()
+endfunction()
+
+function(cpm_add_comment_to_package_lock Name)
+ if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
+ cpm_prettify_package_arguments(PRETTY_ARGN true ${ARGN})
+ file(APPEND ${CPM_PACKAGE_LOCK_FILE}
+ "# ${Name} (unversioned)\n# CPMDeclarePackage(${Name}\n${PRETTY_ARGN}#)\n"
+ )
+ endif()
+endfunction()
+
+# includes the package lock file if it exists and creates a target `cpm-update-package-lock` to
+# update it
+macro(CPMUsePackageLock file)
+ if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
+ get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE)
+ if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH})
+ include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH})
+ endif()
+ if(NOT TARGET cpm-update-package-lock)
+ add_custom_target(
+ cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE}
+ ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}
+ )
+ endif()
+ set(CPM_PACKAGE_LOCK_ENABLED true)
+ endif()
+endmacro()
+
+# registers a package that has been added to CPM
+function(CPMRegisterPackage PACKAGE VERSION)
+ list(APPEND CPM_PACKAGES ${PACKAGE})
+ set(CPM_PACKAGES
+ ${CPM_PACKAGES}
+ CACHE INTERNAL ""
+ )
+ set("CPM_PACKAGE_${PACKAGE}_VERSION"
+ ${VERSION}
+ CACHE INTERNAL ""
+ )
+endfunction()
+
+# retrieve the current version of the package to ${OUTPUT}
+function(CPMGetPackageVersion PACKAGE OUTPUT)
+ set(${OUTPUT}
+ "${CPM_PACKAGE_${PACKAGE}_VERSION}"
+ PARENT_SCOPE
+ )
+endfunction()
+
+# declares a package in FetchContent_Declare
+function(cpm_declare_fetch PACKAGE)
+ if(${CPM_DRY_RUN})
+ cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)")
+ return()
+ endif()
+
+ FetchContent_Declare(${PACKAGE} ${ARGN})
+endfunction()
+
+# returns properties for a package previously defined by cpm_declare_fetch
+function(cpm_get_fetch_properties PACKAGE)
+ if(${CPM_DRY_RUN})
+ return()
+ endif()
+
+ set(${PACKAGE}_SOURCE_DIR
+ "${CPM_PACKAGE_${PACKAGE}_SOURCE_DIR}"
+ PARENT_SCOPE
+ )
+ set(${PACKAGE}_BINARY_DIR
+ "${CPM_PACKAGE_${PACKAGE}_BINARY_DIR}"
+ PARENT_SCOPE
+ )
+endfunction()
+
+function(cpm_store_fetch_properties PACKAGE source_dir binary_dir)
+ if(${CPM_DRY_RUN})
+ return()
+ endif()
+
+ set(CPM_PACKAGE_${PACKAGE}_SOURCE_DIR
+ "${source_dir}"
+ CACHE INTERNAL ""
+ )
+ set(CPM_PACKAGE_${PACKAGE}_BINARY_DIR
+ "${binary_dir}"
+ CACHE INTERNAL ""
+ )
+endfunction()
+
+# adds a package as a subdirectory if viable, according to provided options
+function(
+ cpm_add_subdirectory
+ PACKAGE
+ DOWNLOAD_ONLY
+ SOURCE_DIR
+ BINARY_DIR
+ EXCLUDE
+ SYSTEM
+ OPTIONS
+)
+
+ if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt)
+ set(addSubdirectoryExtraArgs "")
+ if(EXCLUDE)
+ list(APPEND addSubdirectoryExtraArgs EXCLUDE_FROM_ALL)
+ endif()
+ if("${SYSTEM}" AND "${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.25")
+ # https://cmake.org/cmake/help/latest/prop_dir/SYSTEM.html#prop_dir:SYSTEM
+ list(APPEND addSubdirectoryExtraArgs SYSTEM)
+ endif()
+ if(OPTIONS)
+ foreach(OPTION ${OPTIONS})
+ cpm_parse_option("${OPTION}")
+ set(${OPTION_KEY} "${OPTION_VALUE}")
+ endforeach()
+ endif()
+ set(CPM_OLD_INDENT "${CPM_INDENT}")
+ set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:")
+ add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs})
+ set(CPM_INDENT "${CPM_OLD_INDENT}")
+ endif()
+endfunction()
+
+# downloads a previously declared package via FetchContent and exports the variables
+# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope
+function(cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated)
+ set(${populated}
+ FALSE
+ PARENT_SCOPE
+ )
+ if(${CPM_DRY_RUN})
+ cpm_message(STATUS "${CPM_INDENT} Package ${PACKAGE} not fetched (dry run)")
+ return()
+ endif()
+
+ FetchContent_GetProperties(${PACKAGE})
+
+ string(TOLOWER "${PACKAGE}" lower_case_name)
+
+ if(NOT ${lower_case_name}_POPULATED)
+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30.3")
+ if(DOWNLOAD_ONLY)
+ # MakeAvailable will call add_subdirectory internally which is not what we want when
+ # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the
+ # build
+ FetchContent_Populate(
+ ${PACKAGE}
+ SOURCE_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-src"
+ BINARY_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build"
+ SUBBUILD_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild"
+ ${ARGN}
+ )
+ else()
+ FetchContent_MakeAvailable(${PACKAGE})
+ endif()
+ else()
+ FetchContent_Populate(${PACKAGE})
+ endif()
+ set(${populated}
+ TRUE
+ PARENT_SCOPE
+ )
+ endif()
+
+ cpm_store_fetch_properties(
+ ${CPM_ARGS_NAME} ${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR}
+ )
+
+ set(${PACKAGE}_SOURCE_DIR
+ ${${lower_case_name}_SOURCE_DIR}
+ PARENT_SCOPE
+ )
+ set(${PACKAGE}_BINARY_DIR
+ ${${lower_case_name}_BINARY_DIR}
+ PARENT_SCOPE
+ )
+endfunction()
+
+# splits a package option
+function(cpm_parse_option OPTION)
+ string(REGEX MATCH "^[^ ]+" OPTION_KEY "${OPTION}")
+ string(LENGTH "${OPTION}" OPTION_LENGTH)
+ string(LENGTH "${OPTION_KEY}" OPTION_KEY_LENGTH)
+ if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH)
+ # no value for key provided, assume user wants to set option to "ON"
+ set(OPTION_VALUE "ON")
+ else()
+ math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1")
+ string(SUBSTRING "${OPTION}" "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE)
+ endif()
+ set(OPTION_KEY
+ "${OPTION_KEY}"
+ PARENT_SCOPE
+ )
+ set(OPTION_VALUE
+ "${OPTION_VALUE}"
+ PARENT_SCOPE
+ )
+endfunction()
+
+# guesses the package version from a git tag
+function(cpm_get_version_from_git_tag GIT_TAG RESULT)
+ string(LENGTH ${GIT_TAG} length)
+ if(length EQUAL 40)
+ # GIT_TAG is probably a git hash
+ set(${RESULT}
+ 0
+ PARENT_SCOPE
+ )
+ else()
+ string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG})
+ set(${RESULT}
+ ${CMAKE_MATCH_1}
+ PARENT_SCOPE
+ )
+ endif()
+endfunction()
+
+# guesses if the git tag is a commit hash or an actual tag or a branch name.
+function(cpm_is_git_tag_commit_hash GIT_TAG RESULT)
+ string(LENGTH "${GIT_TAG}" length)
+ # full hash has 40 characters, and short hash has at least 7 characters.
+ if(length LESS 7 OR length GREATER 40)
+ set(${RESULT}
+ 0
+ PARENT_SCOPE
+ )
+ else()
+ if(${GIT_TAG} MATCHES "^[a-fA-F0-9]+$")
+ set(${RESULT}
+ 1
+ PARENT_SCOPE
+ )
+ else()
+ set(${RESULT}
+ 0
+ PARENT_SCOPE
+ )
+ endif()
+ endif()
+endfunction()
+
+function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT)
+ set(oneValueArgs
+ NAME
+ FORCE
+ VERSION
+ GIT_TAG
+ DOWNLOAD_ONLY
+ GITHUB_REPOSITORY
+ GITLAB_REPOSITORY
+ BITBUCKET_REPOSITORY
+ GIT_REPOSITORY
+ SOURCE_DIR
+ FIND_PACKAGE_ARGUMENTS
+ NO_CACHE
+ SYSTEM
+ GIT_SHALLOW
+ EXCLUDE_FROM_ALL
+ SOURCE_SUBDIR
+ )
+ set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND)
+ cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ foreach(oneArgName ${oneValueArgs})
+ if(DEFINED CPM_ARGS_${oneArgName})
+ if(${IS_IN_COMMENT})
+ string(APPEND PRETTY_OUT_VAR "#")
+ endif()
+ if(${oneArgName} STREQUAL "SOURCE_DIR")
+ string(REPLACE ${CMAKE_SOURCE_DIR} "\${CMAKE_SOURCE_DIR}" CPM_ARGS_${oneArgName}
+ ${CPM_ARGS_${oneArgName}}
+ )
+ endif()
+ string(APPEND PRETTY_OUT_VAR " ${oneArgName} ${CPM_ARGS_${oneArgName}}\n")
+ endif()
+ endforeach()
+ foreach(multiArgName ${multiValueArgs})
+ if(DEFINED CPM_ARGS_${multiArgName})
+ if(${IS_IN_COMMENT})
+ string(APPEND PRETTY_OUT_VAR "#")
+ endif()
+ string(APPEND PRETTY_OUT_VAR " ${multiArgName}\n")
+ foreach(singleOption ${CPM_ARGS_${multiArgName}})
+ if(${IS_IN_COMMENT})
+ string(APPEND PRETTY_OUT_VAR "#")
+ endif()
+ string(APPEND PRETTY_OUT_VAR " \"${singleOption}\"\n")
+ endforeach()
+ endif()
+ endforeach()
+
+ if(NOT "${CPM_ARGS_UNPARSED_ARGUMENTS}" STREQUAL "")
+ if(${IS_IN_COMMENT})
+ string(APPEND PRETTY_OUT_VAR "#")
+ endif()
+ string(APPEND PRETTY_OUT_VAR " ")
+ foreach(CPM_ARGS_UNPARSED_ARGUMENT ${CPM_ARGS_UNPARSED_ARGUMENTS})
+ string(APPEND PRETTY_OUT_VAR " ${CPM_ARGS_UNPARSED_ARGUMENT}")
+ endforeach()
+ string(APPEND PRETTY_OUT_VAR "\n")
+ endif()
+
+ set(${OUT_VAR}
+ ${PRETTY_OUT_VAR}
+ PARENT_SCOPE
+ )
+
+endfunction()
diff --git a/thirdparty/gsl-lite/example/with-CPM/main.cpp b/thirdparty/gsl-lite/example/with-CPM/main.cpp
new file mode 100644
index 000000000..acf830a96
--- /dev/null
+++ b/thirdparty/gsl-lite/example/with-CPM/main.cpp
@@ -0,0 +1,22 @@
+
+#include <iostream>
+
+#include <gsl-lite/gsl-lite.hpp>
+
+void printCmdArgs( gsl_lite::span<gsl_lite::zstring const> cmdArgs )
+{
+ gsl_Expects( !cmdArgs.empty() );
+
+ auto argsWithoutExeName = cmdArgs.subspan( 1 );
+ for ( auto arg : argsWithoutExeName )
+ {
+ std::cout << arg << "\n";
+ }
+}
+
+int main( int argc, char* argv[] )
+{
+ auto numArgs = gsl_lite::narrow_failfast<std::size_t>( argc );
+ auto cmdArgs = gsl_lite::span( argv, numArgs );
+ printCmdArgs( cmdArgs );
+}
diff --git a/thirdparty/gsl-lite/example/with-Vcpkg/README.md b/thirdparty/gsl-lite/example/with-Vcpkg/README.md
new file mode 100644
index 000000000..19087b1dd
--- /dev/null
+++ b/thirdparty/gsl-lite/example/with-Vcpkg/README.md
@@ -0,0 +1,31 @@
+# gsl-lite example project (Vcpkg)
+
+
+This is a simple CMake project that demonstrates how to use *gsl-lite* with the [Vcpkg](https://vcpkg.io/en/package/gsl-lite) package manager.
+
+Requirements:
+
+- [CMake](https://cmake.org/) 3.20 or newer must be in the path.
+- A C++ compiler must be installed and available in the path.
+- Vcpkg must be installed, and the `VCPKG_ROOT` environment variable must refer to the Vcpkg root directory.
+- An internet connection must be available to allow Vcpkg to retrieve the *gsl-lite* dependency from GitHub.
+
+To set up the project, open a command-line window, navigate to the directory containing this readme, and execute the following commands:
+
+
+## Configure
+```
+cmake --preset default
+```
+
+
+## Build
+```
+cmake --build build/default --config Debug
+```
+
+## Run
+
+| Windows | Linux, MacOS |
+|----------------------------------|------------------------------------|
+| `build\default\Debug\my-program` | `./build/default/Debug/my-program` |
diff --git a/thirdparty/gsl-lite/example/with-Vcpkg/main.cpp b/thirdparty/gsl-lite/example/with-Vcpkg/main.cpp
new file mode 100644
index 000000000..acf830a96
--- /dev/null
+++ b/thirdparty/gsl-lite/example/with-Vcpkg/main.cpp
@@ -0,0 +1,22 @@
+
+#include <iostream>
+
+#include <gsl-lite/gsl-lite.hpp>
+
+void printCmdArgs( gsl_lite::span<gsl_lite::zstring const> cmdArgs )
+{
+ gsl_Expects( !cmdArgs.empty() );
+
+ auto argsWithoutExeName = cmdArgs.subspan( 1 );
+ for ( auto arg : argsWithoutExeName )
+ {
+ std::cout << arg << "\n";
+ }
+}
+
+int main( int argc, char* argv[] )
+{
+ auto numArgs = gsl_lite::narrow_failfast<std::size_t>( argc );
+ auto cmdArgs = gsl_lite::span( argv, numArgs );
+ printCmdArgs( cmdArgs );
+}
diff --git a/thirdparty/gsl-lite/example/with-Vcpkg/vcpkg.json b/thirdparty/gsl-lite/example/with-Vcpkg/vcpkg.json
new file mode 100644
index 000000000..5f046228d
--- /dev/null
+++ b/thirdparty/gsl-lite/example/with-Vcpkg/vcpkg.json
@@ -0,0 +1,6 @@
+{
+ "name": "my-program",
+ "dependencies": [
+ "gsl-lite"
+ ]
+}
diff --git a/thirdparty/gsl-lite/include/gsl-lite/gsl-lite.hpp b/thirdparty/gsl-lite/include/gsl-lite/gsl-lite.hpp
new file mode 100644
index 000000000..aa286f2d2
--- /dev/null
+++ b/thirdparty/gsl-lite/include/gsl-lite/gsl-lite.hpp
@@ -0,0 +1,6014 @@
+//
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// gsl-lite is originally based on Microsoft GSL, which is an implementation of the C++ Core Guidelines Support Library:
+// https://github.com/microsoft/GSL
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2025 Moritz Beutel
+// Copyright (c) 2015-2025 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef GSL_LITE_GSL_LITE_HPP_INCLUDED
+#define GSL_LITE_GSL_LITE_HPP_INCLUDED
+
+#include <exception> // for exception, terminate(), uncaught_exceptions()
+#include <limits>
+#include <memory> // for addressof(), unique_ptr<>, shared_ptr<>
+#include <iosfwd> // for basic_ostream<>
+#include <stdexcept> // for logic_error
+#include <utility> // for move(), forward<>(), swap()
+#include <cstddef> // for size_t, ptrdiff_t, nullptr_t
+#include <cstdlib> // for abort()
+
+#if defined( __has_include )
+# if __has_include( <version> )
+# include <version>
+# endif
+#endif
+
+#define gsl_lite_MAJOR 1
+#define gsl_lite_MINOR 0
+#define gsl_lite_PATCH 1
+
+#define gsl_lite_VERSION gsl_STRINGIFY(gsl_lite_MAJOR) "." gsl_STRINGIFY(gsl_lite_MINOR) "." gsl_STRINGIFY(gsl_lite_PATCH)
+
+#define gsl_STRINGIFY( x ) gsl_STRINGIFY_( x )
+#define gsl_STRINGIFY_( x ) #x
+#define gsl_CONCAT_( a, b ) gsl_CONCAT2_( a, b )
+#define gsl_CONCAT2_( a, b ) a##b
+#define gsl_EVALF_( f ) f()
+
+// Configuration argument checking:
+
+#define gsl_DETAIL_CFG_TOGGLE_VALUE_1 1
+#define gsl_DETAIL_CFG_TOGGLE_VALUE_0 1
+#define gsl_DETAIL_CFG_DEFAULTS_VERSION_VALUE_1 1
+#define gsl_DETAIL_CFG_DEFAULTS_VERSION_VALUE_0 1
+#define gsl_DETAIL_CFG_STD_VALUE_98 1
+#define gsl_DETAIL_CFG_STD_VALUE_0 1
+#define gsl_DETAIL_CFG_STD_VALUE_3 1
+#define gsl_DETAIL_CFG_STD_VALUE_03 1
+#define gsl_DETAIL_CFG_STD_VALUE_11 1
+#define gsl_DETAIL_CFG_STD_VALUE_14 1
+#define gsl_DETAIL_CFG_STD_VALUE_17 1
+#define gsl_DETAIL_CFG_STD_VALUE_20 1
+#define gsl_DETAIL_CFG_STD_VALUE_23 1
+#define gsl_DETAIL_CFG_STD_VALUE_26 1
+#define gsl_DETAIL_CFG_NO_VALUE_ 1
+#define gsl_DETAIL_CFG_NO_VALUE_1 1 // many compilers treat the command-line parameter "-Dfoo" as equivalent to "-Dfoo=1", so we tolerate that
+#define gsl_CHECK_CFG_TOGGLE_VALUE_( x ) gsl_CONCAT_( gsl_DETAIL_CFG_TOGGLE_VALUE_, x )
+#define gsl_CHECK_CFG_DEFAULTS_VERSION_VALUE_( x ) gsl_CONCAT_( gsl_DETAIL_CFG_DEFAULTS_VERSION_VALUE_, x )
+#define gsl_CHECK_CFG_STD_VALUE_( x ) gsl_CONCAT_( gsl_DETAIL_CFG_STD_VALUE_, x )
+#define gsl_CHECK_CFG_NO_VALUE_( x ) gsl_CONCAT_( gsl_DETAIL_CFG_NO_VALUE, gsl_CONCAT_( _, x ) )
+
+// gsl-lite backward compatibility:
+
+#if defined( gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI=" gsl_STRINGIFY(gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI) "; macro must be defined without value")
+# endif
+#endif
+
+#if defined( gsl_CONFIG_DEFAULTS_VERSION )
+# if ! gsl_CHECK_CFG_DEFAULTS_VERSION_VALUE_( gsl_CONFIG_DEFAULTS_VERSION )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEFAULTS_VERSION=" gsl_STRINGIFY(gsl_CONFIG_DEFAULTS_VERSION) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_DEFAULTS_VERSION gsl_lite_MAJOR // default
+#endif
+#define gsl_CONFIG_DEFAULTS_VERSION_() gsl_CONFIG_DEFAULTS_VERSION
+
+#if defined( gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR=" gsl_STRINGIFY(gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR) ", must be 0 or 1")
+# endif
+# define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: configuration macro gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR is deprecated since gsl-lite 0.7; if the constrained container constructor is not usable, define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR instead")
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_LEVEL_ON )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_LEVEL_ON )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_LEVEL_ON=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_LEVEL_ON) "; macro must be defined without value")
+# endif
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: configuration macro gsl_CONFIG_CONTRACT_LEVEL_ON is deprecated since gsl-lite v0.36; define gsl_CONFIG_CONTRACT_CHECKING_ON instead")
+# define gsl_CONFIG_CONTRACT_CHECKING_ON
+#endif
+#if defined( gsl_CONFIG_CONTRACT_LEVEL_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_LEVEL_OFF )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_LEVEL_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_LEVEL_OFF) "; macro must be defined without value")
+# endif
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: configuration macro gsl_CONFIG_CONTRACT_LEVEL_OFF is deprecated since gsl-lite v0.36; define gsl_CONFIG_CONTRACT_CHECKING_OFF instead")
+# define gsl_CONFIG_CONTRACT_CHECKING_OFF
+#endif
+#if defined( gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY) "; macro must be defined without value")
+# endif
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: configuration macro gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY is deprecated since gsl-lite v0.36; define gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF and gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF instead")
+# define gsl_CONFIG_CONTRACT_CHECKING_ON
+# define gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF
+# define gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF
+#elif defined( gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY) "; macro must be defined without value")
+# endif
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: configuration macro gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY is deprecated since gsl-lite v0.36; define gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF and gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF instead")
+# define gsl_CONFIG_CONTRACT_CHECKING_ON
+# define gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF
+# define gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF
+#endif
+
+// M-GSL compatibility:
+
+#if defined( GSL_THROW_ON_CONTRACT_VIOLATION )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: do not use legacy Microsoft GSL configuration macro GSL_THROW_ON_CONTRACT_VIOLATION to configure gsl-lite; define gsl_CONFIG_CONTRACT_VIOLATION_THROWS instead")
+# if ! gsl_CHECK_CFG_NO_VALUE_( GSL_THROW_ON_CONTRACT_VIOLATION )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value GSL_THROW_ON_CONTRACT_VIOLATION=" gsl_STRINGIFY(GSL_THROW_ON_CONTRACT_VIOLATION) "; macro must be defined without value")
+# endif
+# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS
+#endif
+
+#if defined( GSL_TERMINATE_ON_CONTRACT_VIOLATION )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: do not use legacy Microsoft GSL configuration macro GSL_TERMINATE_ON_CONTRACT_VIOLATION to configure gsl-lite; define gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES instead")
+# if ! gsl_CHECK_CFG_NO_VALUE_( GSL_TERMINATE_ON_CONTRACT_VIOLATION )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value GSL_TERMINATE_ON_CONTRACT_VIOLATION=" gsl_STRINGIFY(GSL_TERMINATE_ON_CONTRACT_VIOLATION) "; macro must be defined without value")
+# endif
+# define gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES
+#endif
+
+#if defined( GSL_UNENFORCED_ON_CONTRACT_VIOLATION )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: do not use legacy Microsoft GSL configuration macro GSL_UNENFORCED_ON_CONTRACT_VIOLATION to configure gsl-lite; define gsl_CONFIG_CONTRACT_CHECKING_OFF instead")
+# if ! gsl_CHECK_CFG_NO_VALUE_( GSL_UNENFORCED_ON_CONTRACT_VIOLATION )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value GSL_UNENFORCED_ON_CONTRACT_VIOLATION=" gsl_STRINGIFY(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) "; macro must be defined without value")
+# endif
+# define gsl_CONFIG_CONTRACT_CHECKING_OFF
+#endif
+
+// Configuration: Features
+
+#if defined( gsl_FEATURE_GSL_COMPATIBILITY_MODE )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_GSL_COMPATIBILITY_MODE )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_GSL_COMPATIBILITY_MODE=" gsl_STRINGIFY(gsl_FEATURE_OWNER_MACRO) ", must be 0 or 1")
+# endif
+#else
+# define gsl_FEATURE_GSL_COMPATIBILITY_MODE (gsl_CONFIG_DEFAULTS_VERSION == 0) // default
+#endif
+#define gsl_FEATURE_GSL_COMPATIBILITY_MODE_() gsl_FEATURE_GSL_COMPATIBILITY_MODE
+
+#if defined( gsl_FEATURE_WITH_CONTAINER_TO_STD )
+# if ! gsl_CHECK_CFG_STD_VALUE_( gsl_FEATURE_WITH_CONTAINER_TO_STD )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_WITH_CONTAINER_TO_STD=" gsl_STRINGIFY(gsl_FEATURE_WITH_CONTAINER_TO_STD) ", must be 98, 3, 11, 14, 17, or 20")
+# endif
+#else
+# if gsl_CONFIG_DEFAULTS_VERSION >= 1
+# define gsl_FEATURE_WITH_CONTAINER_TO_STD 0 // version-1 default
+# else // gsl_CONFIG_DEFAULTS_VERSION == 0
+# define gsl_FEATURE_WITH_CONTAINER_TO_STD 99 // version-0 default
+# endif // gsl_CONFIG_DEFAULTS_VERSION >= 1
+#endif
+#define gsl_FEATURE_WITH_CONTAINER_TO_STD_() gsl_FEATURE_WITH_CONTAINER_TO_STD
+
+#if defined( gsl_FEATURE_MAKE_SPAN_TO_STD )
+# if ! gsl_CHECK_CFG_STD_VALUE_( gsl_FEATURE_MAKE_SPAN_TO_STD )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_MAKE_SPAN_TO_STD=" gsl_STRINGIFY(gsl_FEATURE_MAKE_SPAN_TO_STD) ", must be 98, 3, 11, 14, 17, or 20")
+# endif
+#else
+# define gsl_FEATURE_MAKE_SPAN_TO_STD 99 // default
+#endif
+#define gsl_FEATURE_MAKE_SPAN_TO_STD_() gsl_FEATURE_MAKE_SPAN_TO_STD
+
+#if defined( gsl_FEATURE_BYTE_SPAN_TO_STD )
+# if ! gsl_CHECK_CFG_STD_VALUE_( gsl_FEATURE_BYTE_SPAN_TO_STD )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_BYTE_SPAN_TO_STD=" gsl_STRINGIFY(gsl_FEATURE_BYTE_SPAN_TO_STD) ", must be 98, 3, 11, 14, 17, or 20")
+# endif
+#else
+# define gsl_FEATURE_BYTE_SPAN_TO_STD 99 // default
+#endif
+#define gsl_FEATURE_BYTE_SPAN_TO_STD_() gsl_FEATURE_BYTE_SPAN_TO_STD
+
+#if defined( gsl_FEATURE_IMPLICIT_MACRO )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_IMPLICIT_MACRO )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_IMPLICIT_MACRO=" gsl_STRINGIFY(gsl_FEATURE_IMPLICIT_MACRO) ", must be 0 or 1")
+# endif
+# if gsl_FEATURE_IMPLICIT_MACRO
+# error configuration value gsl_FEATURE_IMPLICIT_MACRO=1 is no longer supported since gsl-lite v1.0
+# endif // gsl_FEATURE_IMPLICIT_MACRO
+#else
+# define gsl_FEATURE_IMPLICIT_MACRO 0
+#endif
+#define gsl_FEATURE_IMPLICIT_MACRO_() gsl_FEATURE_IMPLICIT_MACRO
+
+#if defined( gsl_FEATURE_OWNER_MACRO )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_OWNER_MACRO )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_OWNER_MACRO=" gsl_STRINGIFY(gsl_FEATURE_OWNER_MACRO) ", must be 0 or 1")
+# endif
+# if gsl_FEATURE_OWNER_MACRO
+# error configuration value gsl_FEATURE_OWNER_MACRO=1 is no longer supported since gsl-lite v1.0
+# endif // gsl_FEATURE_OWNER_MACRO
+#else
+# define gsl_FEATURE_OWNER_MACRO 0
+#endif
+#define gsl_FEATURE_OWNER_MACRO_() gsl_FEATURE_OWNER_MACRO
+
+#if defined( gsl_FEATURE_STRING_SPAN )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_STRING_SPAN )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_STRING_SPAN=" gsl_STRINGIFY(gsl_FEATURE_STRING_SPAN) ", must be 0 or 1")
+# endif
+#else
+# define gsl_FEATURE_STRING_SPAN (gsl_CONFIG_DEFAULTS_VERSION == 0) // default
+#endif
+#define gsl_FEATURE_STRING_SPAN_() gsl_FEATURE_STRING_SPAN
+
+#if defined( gsl_FEATURE_BYTE )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_BYTE )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_BYTE=" gsl_STRINGIFY(gsl_FEATURE_BYTE) ", must be 0 or 1")
+# endif
+#else
+# define gsl_FEATURE_BYTE (gsl_CONFIG_DEFAULTS_VERSION == 0) // default
+#endif
+#define gsl_FEATURE_BYTE_() gsl_FEATURE_BYTE
+
+#if defined( gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD=" gsl_STRINGIFY(gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD) ", must be 0 or 1")
+# endif
+#else
+# define gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD 0 // default
+#endif
+#define gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD_() gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD
+
+#if defined( gsl_FEATURE_GSL_LITE_NAMESPACE )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_GSL_LITE_NAMESPACE )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_FEATURE_GSL_LITE_NAMESPACE=" gsl_STRINGIFY(gsl_FEATURE_GSL_LITE_NAMESPACE) ", must be 0 or 1")
+# endif
+# if ! gsl_FEATURE_GSL_LITE_NAMESPACE
+# error gsl_FEATURE_GSL_LITE_NAMESPACE is a required feature since gsl-lite v1.0 and cannot be switched off
+# endif
+#else
+# define gsl_FEATURE_GSL_LITE_NAMESPACE 1
+#endif
+#define gsl_FEATURE_GSL_LITE_NAMESPACE_() gsl_FEATURE_GSL_LITE_NAMESPACE
+
+// Configuration: Other
+
+#if defined( gsl_CONFIG_TRANSPARENT_NOT_NULL )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_TRANSPARENT_NOT_NULL )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_TRANSPARENT_NOT_NULL=" gsl_STRINGIFY(gsl_CONFIG_TRANSPARENT_NOT_NULL) ", must be 0 or 1")
+# endif
+# if gsl_CONFIG_TRANSPARENT_NOT_NULL && defined( gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF )
+# error configuration option gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF is meaningless if gsl_CONFIG_TRANSPARENT_NOT_NULL=1
+# endif
+#else
+# define gsl_CONFIG_TRANSPARENT_NOT_NULL (gsl_CONFIG_DEFAULTS_VERSION >= 1) // default
+#endif
+#define gsl_CONFIG_TRANSPARENT_NOT_NULL_() gsl_CONFIG_TRANSPARENT_NOT_NULL
+
+#if ! defined( gsl_CONFIG_DEPRECATE_TO_LEVEL )
+# if gsl_CONFIG_DEFAULTS_VERSION >= 1
+# define gsl_CONFIG_DEPRECATE_TO_LEVEL 9
+# else
+# define gsl_CONFIG_DEPRECATE_TO_LEVEL 0
+# endif
+#endif
+
+#if defined( gsl_CONFIG_SPAN_INDEX_TYPE )
+# if ! defined( gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: defining a custom gsl_CONFIG_SPAN_INDEX_TYPE changes the ABI of gsl-lite, which may lead to ODR violations and undefined behavior; define the macro gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI to explicitly acknowledge that you are using gsl-lite with a non-standard ABI and that you control the build flags of all components linked into your target")
+# endif
+#else // ! defined( gsl_CONFIG_SPAN_INDEX_TYPE )
+# define gsl_CONFIG_SPAN_INDEX_TYPE std::size_t
+#endif
+#define gsl_CONFIG_SPAN_INDEX_TYPE_() gsl_CONFIG_SPAN_INDEX_TYPE
+
+#if defined( gsl_CONFIG_INDEX_TYPE )
+# if ! defined( gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: defining a custom gsl_CONFIG_INDEX_TYPE changes the ABI of gsl-lite, which may lead to ODR violations and undefined behavior; define the macro gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI to explicitly acknowledge that you are using gsl-lite with a non-standard ABI and that you control the build flags of all components linked into your target")
+# endif
+#else // ! defined( gsl_CONFIG_INDEX_TYPE )
+# if gsl_CONFIG_DEFAULTS_VERSION >= 1
+// p0122r3 uses std::ptrdiff_t
+# define gsl_CONFIG_INDEX_TYPE std::ptrdiff_t
+# else
+# if ! defined( gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: with version-0 defaults, gsl_CONFIG_INDEX_TYPE defaults to gsl_CONFIG_SPAN_INDEX_TYPE, which changes the ABI of gsl-lite and may lead to ODR violations and undefined behavior; use version-1 defaults or define the macro gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI to explicitly acknowledge that you are using gsl-lite with a non-standard ABI and that you control the build flags of all components linked into your target")
+# endif
+# define gsl_CONFIG_INDEX_TYPE gsl_CONFIG_SPAN_INDEX_TYPE
+# endif
+#endif
+#define gsl_CONFIG_INDEX_TYPE_() gsl_CONFIG_INDEX_TYPE
+
+#if defined( gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR=" gsl_STRINGIFY(gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR (gsl_CONFIG_DEFAULTS_VERSION >= 1) // default
+#endif
+#define gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR_() gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR
+
+#if defined( gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF=" gsl_STRINGIFY(gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF 0 // default
+#endif
+#define gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF_() gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF
+
+#if defined( gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS=" gsl_STRINGIFY(gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS 0 // default
+#endif
+#define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS_() gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS
+
+#if defined( gsl_CONFIG_ALLOWS_SPAN_COMPARISON )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_ALLOWS_SPAN_COMPARISON )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_ALLOWS_SPAN_COMPARISON=" gsl_STRINGIFY(gsl_CONFIG_ALLOWS_SPAN_COMPARISON) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_ALLOWS_SPAN_COMPARISON (gsl_CONFIG_DEFAULTS_VERSION == 0) // default
+#endif
+#define gsl_CONFIG_ALLOWS_SPAN_COMPARISON_() gsl_CONFIG_ALLOWS_SPAN_COMPARISON
+
+#if defined( gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=" gsl_STRINGIFY(gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON 1 // default
+#endif
+#define gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON_() gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
+
+#if defined( gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR=" gsl_STRINGIFY(gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR 0 // default
+#endif
+#define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR_() gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR
+
+#if defined( gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=" gsl_STRINGIFY(gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION) ", must be 0 or 1")
+# endif
+# if ! gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION && ! defined( gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: the configuration value gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=0 changes the ABI of gsl-lite, which may lead to ODR violations and undefined behavior; define the macro gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI to explicitly acknowledge that you are using gsl-lite with a non-standard ABI and that you control the build flags of all components linked into your target")
+# endif
+#else
+# define gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION (gsl_CONFIG_DEFAULTS_VERSION >= 1) // default
+# if gsl_CONFIG_DEFAULTS_VERSION < 1 && ! defined( gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: with version-0 defaults, gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION defaults to 0, which changes the ABI of gsl-lite and may lead to ODR violations and undefined behavior; use version-1 defaults or define the macro gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI to explicitly acknowledge that you are using gsl-lite with a non-standard ABI and that you control the build flags of all components linked into your target")
+# endif
+#endif
+#define gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION_() gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION
+
+#if defined( gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS=" gsl_STRINGIFY(gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS 1 // default
+#endif
+#define gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS_() gsl_CONFIG_VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS
+
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_AUDIT=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_AUDIT) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_ON )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_ON )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_ON=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_ON) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT=" gsl_STRINGIFY(gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON=" gsl_STRINGIFY(gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF=" gsl_STRINGIFY(gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_THROWS )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_THROWS=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_THROWS) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_TRAPS=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_TRAPS) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS=" gsl_STRINGIFY(gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS=" gsl_STRINGIFY(gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER=" gsl_STRINGIFY(gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME=" gsl_STRINGIFY(gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE=" gsl_STRINGIFY(gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME=" gsl_STRINGIFY(gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: invalid configuration value gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE=" gsl_STRINGIFY(gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE) "; macro must be defined without value")
+# endif
+#endif
+
+#if defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_THROWS )
+# error cannot use gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_THROWS because exceptions are not supported in device code; use gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS or gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS
+#endif
+#if defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TERMINATES )
+# error gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TERMINATES is not supported; use gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS or gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS
+#endif
+
+#if 1 < defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT ) + defined( gsl_CONFIG_CONTRACT_CHECKING_ON ) + defined( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+# error only one of gsl_CONFIG_CONTRACT_CHECKING_AUDIT, gsl_CONFIG_CONTRACT_CHECKING_ON, and gsl_CONFIG_CONTRACT_CHECKING_OFF may be defined
+#endif
+#if 1 < defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT ) + defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON ) + defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF )
+# error only one of gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT, gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON, and gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF may be defined
+#endif
+#if 1 < defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# error only one of gsl_CONFIG_CONTRACT_VIOLATION_THROWS, gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES, gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS, gsl_CONFIG_CONTRACT_VIOLATION_TRAPS, and gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER may be defined
+#endif
+#if 1 < defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS ) + defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS ) + defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER )
+# error only one of gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS, gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS, and gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER may be defined
+#endif
+#if 1 < defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME ) + defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE )
+# error only one of gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME and gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE may be defined
+#endif
+#if 1 < defined( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME ) + defined( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE )
+# error only one of gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME and gsl_CONFIG_UNENFORCED_DEVICE_CONTRACTS_ELIDE may be defined
+#endif
+
+#if 0 == defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT ) + defined( gsl_CONFIG_CONTRACT_CHECKING_ON ) + defined( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+// select default
+# define gsl_CONFIG_CONTRACT_CHECKING_ON
+#endif
+#if 0 == defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT ) + defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON ) + defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF )
+// select default
+# if defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+# define gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT
+# elif defined( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+# define gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF
+# else
+# define gsl_CONFIG_DEVICE_CONTRACT_CHECKING_ON
+# endif
+#endif
+#if 0 == defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+// select default
+# if gsl_CONFIG_DEFAULTS_VERSION >= 1
+# define gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS // version-1 default
+# else // gsl_CONFIG_DEFAULTS_VERSION == 0
+# define gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES // version-0 default
+# endif // gsl_CONFIG_DEFAULTS_VERSION >= 1
+#endif
+#if 0 == defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS ) + defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS ) + defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER )
+// select default
+# if defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# define gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER
+# elif defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+# define gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS
+# else
+# define gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS
+# endif
+#endif
+#if 0 == defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME ) + defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE )
+// select default
+# define gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE
+#endif
+#if 0 == defined( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME ) + defined( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE )
+// select default
+# if defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+# define gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME
+# else
+# define gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE
+# endif
+#endif
+
+// C++ language version detection:
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef gsl_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+# define gsl_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+# define gsl_CPLUSPLUS __cplusplus
+# endif
+#endif
+
+// C++ standard library version:
+
+#ifndef gsl_CPLUSPLUS_STDLIB
+# define gsl_CPLUSPLUS_STDLIB gsl_CPLUSPLUS
+#endif
+
+#define gsl_CPP98_OR_GREATER ( gsl_CPLUSPLUS >= 199711L )
+#define gsl_CPP11_OR_GREATER ( gsl_CPLUSPLUS >= 201103L )
+#define gsl_CPP14_OR_GREATER ( gsl_CPLUSPLUS >= 201402L )
+#define gsl_CPP17_OR_GREATER ( gsl_CPLUSPLUS >= 201703L )
+#define gsl_CPP20_OR_GREATER ( gsl_CPLUSPLUS >= 202002L )
+#define gsl_CPP23_OR_GREATER ( gsl_CPLUSPLUS >= 202302L )
+#define gsl_CPP26_OR_GREATER ( gsl_CPLUSPLUS > 202302L ) // not finalized yet
+
+// C++ language version (represent 98 as 3):
+
+#define gsl_CPLUSPLUS_V ( gsl_CPLUSPLUS / 100 - (gsl_CPLUSPLUS > 200000 ? 2000 : 1994) )
+
+// half-open range [lo..hi):
+#define gsl_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
+
+// Compiler versions:
+
+// MSVC++ 6.0 _MSC_VER == 1200 gsl_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
+// MSVC++ 7.0 _MSC_VER == 1300 gsl_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
+// MSVC++ 7.1 _MSC_VER == 1310 gsl_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
+// MSVC++ 8.0 _MSC_VER == 1400 gsl_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
+// MSVC++ 9.0 _MSC_VER == 1500 gsl_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
+// MSVC++ 10.0 _MSC_VER == 1600 gsl_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
+// MSVC++ 11.0 _MSC_VER == 1700 gsl_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
+// MSVC++ 12.0 _MSC_VER == 1800 gsl_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
+// MSVC++ 14.0 _MSC_VER == 1900 gsl_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
+// MSVC++ 14.1 _MSC_VER >= 1910 gsl_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
+// MSVC++ 14.2 _MSC_VER >= 1920 gsl_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
+// MSVC++ 14.3 _MSC_VER >= 1930 gsl_COMPILER_MSVC_VERSION == 143 (Visual Studio 2022)
+
+#if defined( _MSC_VER ) && ! defined( __clang__ )
+# define gsl_COMPILER_MSVC_VER (_MSC_VER )
+# define gsl_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
+# define gsl_COMPILER_MSVC_VERSION_FULL (_MSC_VER - 100 * ( 5 + (_MSC_VER < 1900 ) ) )
+#else
+# define gsl_COMPILER_MSVC_VER 0
+# define gsl_COMPILER_MSVC_VERSION 0
+# define gsl_COMPILER_MSVC_VERSION_FULL 0
+#endif
+
+#define gsl_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
+
+// AppleClang 7.0.0 __apple_build_version__ == 7000172 gsl_COMPILER_APPLECLANG_VERSION == 700 (Xcode 7.0, 7.0.1) (LLVM 3.7.0)
+// AppleClang 7.0.0 __apple_build_version__ == 7000176 gsl_COMPILER_APPLECLANG_VERSION == 700 (Xcode 7.1) (LLVM 3.7.0)
+// AppleClang 7.0.2 __apple_build_version__ == 7000181 gsl_COMPILER_APPLECLANG_VERSION == 702 (Xcode 7.2, 7.2.1) (LLVM 3.7.0)
+// AppleClang 7.3.0 __apple_build_version__ == 7030029 gsl_COMPILER_APPLECLANG_VERSION == 730 (Xcode 7.3) (LLVM 3.8.0)
+// AppleClang 7.3.0 __apple_build_version__ == 7030031 gsl_COMPILER_APPLECLANG_VERSION == 730 (Xcode 7.3.1) (LLVM 3.8.0)
+// AppleClang 8.0.0 __apple_build_version__ == 8000038 gsl_COMPILER_APPLECLANG_VERSION == 800 (Xcode 8.0) (LLVM 3.9.0)
+// AppleClang 8.0.0 __apple_build_version__ == 8000042 gsl_COMPILER_APPLECLANG_VERSION == 800 (Xcode 8.1, 8.2, 8.2.1) (LLVM 3.9.0)
+// AppleClang 8.1.0 __apple_build_version__ == 8020038 gsl_COMPILER_APPLECLANG_VERSION == 810 (Xcode 8.3) (LLVM 3.9.0)
+// AppleClang 8.1.0 __apple_build_version__ == 8020041 gsl_COMPILER_APPLECLANG_VERSION == 810 (Xcode 8.3.1) (LLVM 3.9.0)
+// AppleClang 8.1.0 __apple_build_version__ == 8020042 gsl_COMPILER_APPLECLANG_VERSION == 810 (Xcode 8.3.2, 8.3.3) (LLVM 3.9.0)
+// AppleClang 9.0.0 __apple_build_version__ == 9000037 gsl_COMPILER_APPLECLANG_VERSION == 900 (Xcode 9.0) (LLVM 4.0.0)
+// AppleClang 9.0.0 __apple_build_version__ == 9000038 gsl_COMPILER_APPLECLANG_VERSION == 900 (Xcode 9.1) (LLVM 4.0.0)
+// AppleClang 9.0.0 __apple_build_version__ == 9000039 gsl_COMPILER_APPLECLANG_VERSION == 900 (Xcode 9.2) (LLVM 4.0.0)
+// AppleClang 9.1.0 __apple_build_version__ == 9020039 gsl_COMPILER_APPLECLANG_VERSION == 910 (Xcode 9.3, 9.3.1) (LLVM 5.0.2)
+// AppleClang 9.1.0 __apple_build_version__ == 9020039 gsl_COMPILER_APPLECLANG_VERSION == 910 (Xcode 9.4, 9.4.1) (LLVM 5.0.2)
+// AppleClang 10.0.0 __apple_build_version__ == 10001145 gsl_COMPILER_APPLECLANG_VERSION == 1000 (Xcode 10.0, 10.1) (LLVM 6.0.1)
+// AppleClang 10.0.1 __apple_build_version__ == 10010046 gsl_COMPILER_APPLECLANG_VERSION == 1001 (Xcode 10.2, 10.2.1, 10.3) (LLVM 7.0.0)
+// AppleClang 11.0.0 __apple_build_version__ == 11000033 gsl_COMPILER_APPLECLANG_VERSION == 1100 (Xcode 11.1, 11.2, 11.3, 11.3.1) (LLVM 8.0.0)
+// AppleClang 11.0.3 __apple_build_version__ == 11030032 gsl_COMPILER_APPLECLANG_VERSION == 1103 (Xcode 11.4, 11.4.1, 11.5, 11.6) (LLVM 9.0.0)
+// AppleClang 12.0.0 __apple_build_version__ == 12000032 gsl_COMPILER_APPLECLANG_VERSION == 1200 (Xcode 12.0–12.4) (LLVM 10.0.0)
+// AppleClang 12.0.5 __apple_build_version__ == 12050022 gsl_COMPILER_APPLECLANG_VERSION == 1205 (Xcode 12.5) (LLVM 11.1.0)
+// AppleClang 13.0.0 __apple_build_version__ == 13000029 gsl_COMPILER_APPLECLANG_VERSION == 1300 (Xcode 13.0–13.2.1) (LLVM 12.0.0)
+// AppleClang 13.1.6 __apple_build_version__ == 13160021 gsl_COMPILER_APPLECLANG_VERSION == 1316 (Xcode 13.3–13.4.1) (LLVM 13.0.0)
+// AppleClang 14.0.0 __apple_build_version__ == 14000029 gsl_COMPILER_APPLECLANG_VERSION == 1400 (Xcode 14.0–14.2) (LLVM 14.0.0)
+// AppleClang 14.0.3 __apple_build_version__ == 14030022 gsl_COMPILER_APPLECLANG_VERSION == 1403 (Xcode 14.3) (LLVM 15.0.0)
+// AppleClang 15.0.0 __apple_build_version__ == 15000040 gsl_COMPILER_APPLECLANG_VERSION == 1500 (Xcode 15.0) (LLVM 16.0.0)
+// AppleClang 15.0.0 __apple_build_version__ == 15000100 gsl_COMPILER_APPLECLANG_VERSION == 1500 (Xcode 15.1–15.2) (LLVM 16.0.0)
+// AppleClang 15.0.0 __apple_build_version__ == 15000309 gsl_COMPILER_APPLECLANG_VERSION == 1500 (Xcode 15.3–15.4) (LLVM 16.0.0)
+// AppleClang 16.0.0 __apple_build_version__ == 16000026 gsl_COMPILER_APPLECLANG_VERSION == 1600 (Xcode 16.0–16.2) (LLVM 17.0.6)
+// AppleClang 17.0.0 __apple_build_version__ == 17000013 gsl_COMPILER_APPLECLANG_VERSION == 1700 (Xcode 16.3) (LLVM 19.1.4)
+// AppleClang 17.0.0 __apple_build_version__ == 17000013 gsl_COMPILER_APPLECLANG_VERSION == 1700 (Xcode 16.4) (LLVM 19.1.5)
+
+#if defined( __apple_build_version__ )
+# define gsl_COMPILER_APPLECLANG_VERSION gsl_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
+# define gsl_COMPILER_CLANG_VERSION 0
+#elif defined( __clang__ )
+# define gsl_COMPILER_APPLECLANG_VERSION 0
+# define gsl_COMPILER_CLANG_VERSION gsl_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
+#else
+# define gsl_COMPILER_APPLECLANG_VERSION 0
+# define gsl_COMPILER_CLANG_VERSION 0
+#endif
+
+#if defined( __GNUC__ ) && ! defined( __clang__ ) && ! defined( __NVCOMPILER )
+# define gsl_COMPILER_GNUC_VERSION gsl_COMPILER_VERSION( __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ )
+#else
+# define gsl_COMPILER_GNUC_VERSION 0
+#endif
+
+#if defined( __NVCC__ )
+# define gsl_COMPILER_NVCC_VERSION ( __CUDACC_VER_MAJOR__ * 10 + __CUDACC_VER_MINOR__ )
+#else
+# define gsl_COMPILER_NVCC_VERSION 0
+#endif
+
+// NVHPC 21.2 gsl_COMPILER_NVHPC_VERSION == 2120
+#if defined( __NVCOMPILER )
+# define gsl_COMPILER_NVHPC_VERSION gsl_COMPILER_VERSION( __NVCOMPILER_MAJOR__, __NVCOMPILER_MINOR__, __NVCOMPILER_PATCHLEVEL__ )
+#else
+# define gsl_COMPILER_NVHPC_VERSION 0
+#endif
+
+#if defined( __ARMCC_VERSION )
+# define gsl_COMPILER_ARMCC_VERSION ( __ARMCC_VERSION / 10000 )
+# define gsl_COMPILER_ARMCC_VERSION_FULL __ARMCC_VERSION
+#else
+# define gsl_COMPILER_ARMCC_VERSION 0
+# define gsl_COMPILER_ARMCC_VERSION_FULL 0
+#endif
+
+
+// Compiler non-strict aliasing:
+
+#if defined(__clang__) || defined(__GNUC__)
+# define gsl_may_alias __attribute__((__may_alias__))
+#else
+# define gsl_may_alias
+#endif
+
+// Presence of gsl, language and library features:
+
+#define gsl_IN_STD( v ) ( ((v) == 98 ? 3 : (v)) >= gsl_CPLUSPLUS_V )
+
+#define gsl_DEPRECATE_TO_LEVEL( level ) ( level <= gsl_CONFIG_DEPRECATE_TO_LEVEL )
+#define gsl_FEATURE_TO_STD( feature ) gsl_IN_STD( gsl_FEATURE( feature##_TO_STD ) )
+#define gsl_FEATURE( feature ) gsl_EVALF_( gsl_FEATURE_##feature##_ )
+#define gsl_CONFIG( feature ) gsl_EVALF_( gsl_CONFIG_##feature##_ )
+#define gsl_HAVE( feature ) gsl_EVALF_( gsl_HAVE_##feature##_ )
+
+// Presence of wide character support:
+
+#if defined(__DJGPP__) || (defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS))
+# define gsl_HAVE_WCHAR 0
+#else
+# define gsl_HAVE_WCHAR 1
+#endif
+#define gsl_HAVE_WCHAR_() gsl_HAVE_WCHAR
+
+// Compiling device code:
+
+#if defined( __CUDACC__ ) && defined( __CUDA_ARCH__ )
+# define gsl_DEVICE_CODE 1
+#else
+# define gsl_DEVICE_CODE 0
+#endif
+
+
+// Presence of language & library features:
+
+#if gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+# ifdef __OBJC__
+ // There are a bunch of inconsistencies about __EXCEPTIONS and __has_feature(cxx_exceptions) in Clang 3.4/3.5/3.6.
+ // We're interested in C++ exceptions, which can be checked by __has_feature(cxx_exceptions) in 3.5+.
+ // In pre-3.5, __has_feature(cxx_exceptions) can be true if ObjC exceptions are enabled, but C++ exceptions are disabled.
+ // The recommended way to check is `__EXCEPTIONS && __has_feature(cxx_exceptions)`.
+ // See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
+ // Note: this is only relevant in Objective-C++, thus the ifdef.
+# if __EXCEPTIONS && __has_feature(cxx_exceptions)
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif // __EXCEPTIONS && __has_feature(cxx_exceptions)
+# else
+ // clang-cl doesn't define __EXCEPTIONS for MSVC compatibility (see https://reviews.llvm.org/D4065).
+ // Neither does Clang in MS-compatiblity mode.
+ // Let's hope no one tries to build Objective-C++ code using MS-compatibility mode or clang-cl.
+# if __has_feature(cxx_exceptions)
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif
+# endif
+#elif defined( __GNUC__ )
+# if __GNUC__ < 5
+# ifdef __EXCEPTIONS
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif // __EXCEPTIONS
+# else
+# ifdef __cpp_exceptions
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif // __cpp_exceptions
+# endif // __GNUC__ < 5
+#elif gsl_COMPILER_MSVC_VERSION
+# ifdef _CPPUNWIND
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif // _CPPUNWIND
+#else
+// For all other compilers, assume exceptions are always enabled.
+# define gsl_HAVE_EXCEPTIONS 1
+#endif
+#define gsl_HAVE_EXCEPTIONS_() gsl_HAVE_EXCEPTIONS
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && ! gsl_HAVE( EXCEPTIONS )
+# error Cannot use gsl_CONFIG_CONTRACT_VIOLATION_THROWS if exceptions are disabled.
+#endif // defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && !gsl_HAVE( EXCEPTIONS )
+
+#ifdef _HAS_CPP0X
+# define gsl_HAS_CPP0X _HAS_CPP0X
+#else
+# define gsl_HAS_CPP0X 0
+#endif
+
+#define gsl_CPP11_100 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1600)
+#define gsl_CPP11_110 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1700)
+#define gsl_CPP11_120 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800)
+#define gsl_CPP11_140 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_CPP14_000 (gsl_CPP14_OR_GREATER)
+#define gsl_CPP14_120 (gsl_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800)
+#define gsl_CPP14_140 (gsl_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_CPP17_000 (gsl_CPP17_OR_GREATER)
+#define gsl_CPP17_140 (gsl_CPP17_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_CPP11_140_CPP0X_90 (gsl_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1500 && gsl_HAS_CPP0X))
+#define gsl_CPP11_140_CPP0X_100 (gsl_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1600 && gsl_HAS_CPP0X))
+
+// Presence of C++11 language features:
+
+#define gsl_HAVE_C99_PREPROCESSOR gsl_CPP11_140
+#define gsl_HAVE_AUTO gsl_CPP11_100
+#define gsl_HAVE_RVALUE_REFERENCE gsl_CPP11_100
+#define gsl_HAVE_FUNCTION_REF_QUALIFIER ( gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 481 ) )
+#define gsl_HAVE_ENUM_CLASS gsl_CPP11_110
+#define gsl_HAVE_ALIAS_TEMPLATE gsl_CPP11_120
+#define gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG gsl_CPP11_120
+#define gsl_HAVE_EXPLICIT gsl_CPP11_120
+#define gsl_HAVE_VARIADIC_TEMPLATE gsl_CPP11_120
+#define gsl_HAVE_IS_DELETE gsl_CPP11_120
+#define gsl_HAVE_CONSTEXPR_11 gsl_CPP11_140
+#define gsl_HAVE_IS_DEFAULT gsl_CPP11_140
+#define gsl_HAVE_NOEXCEPT gsl_CPP11_140
+#define gsl_HAVE_NORETURN ( gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 480 ) )
+#define gsl_HAVE_EXPRESSION_SFINAE gsl_CPP11_140
+#define gsl_HAVE_OVERRIDE_FINAL gsl_CPP11_110
+
+#define gsl_HAVE_C99_PREPROCESSOR_() gsl_HAVE_C99_PREPROCESSOR
+#define gsl_HAVE_AUTO_() gsl_HAVE_AUTO
+#define gsl_HAVE_RVALUE_REFERENCE_() gsl_HAVE_RVALUE_REFERENCE
+#define gsl_HAVE_FUNCTION_REF_QUALIFIER_() gsl_HAVE_FUNCTION_REF_QUALIFIER
+#define gsl_HAVE_ENUM_CLASS_() gsl_HAVE_ENUM_CLASS
+#define gsl_HAVE_ALIAS_TEMPLATE_() gsl_HAVE_ALIAS_TEMPLATE
+#define gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG_() gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+#define gsl_HAVE_EXPLICIT_() gsl_HAVE_EXPLICIT
+#define gsl_HAVE_VARIADIC_TEMPLATE_() gsl_HAVE_VARIADIC_TEMPLATE
+#define gsl_HAVE_IS_DELETE_() gsl_HAVE_IS_DELETE
+#define gsl_HAVE_CONSTEXPR_11_() gsl_HAVE_CONSTEXPR_11
+#define gsl_HAVE_IS_DEFAULT_() gsl_HAVE_IS_DEFAULT
+#define gsl_HAVE_NOEXCEPT_() gsl_HAVE_NOEXCEPT
+#define gsl_HAVE_NORETURN_() gsl_HAVE_NORETURN
+#define gsl_HAVE_EXPRESSION_SFINAE_() gsl_HAVE_EXPRESSION_SFINAE
+#define gsl_HAVE_OVERRIDE_FINAL_() gsl_HAVE_OVERRIDE_FINAL
+
+// Presence of C++14 language features:
+
+#define gsl_HAVE_CONSTEXPR_14 ( gsl_CPP14_000 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 600 ) )
+#define gsl_HAVE_DECLTYPE_AUTO gsl_CPP14_140
+#define gsl_HAVE_DEPRECATED ( gsl_CPP14_140 && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 142 ) )
+
+#define gsl_HAVE_CONSTEXPR_14_() gsl_HAVE_CONSTEXPR_14
+#define gsl_HAVE_DECLTYPE_AUTO_() gsl_HAVE_DECLTYPE_AUTO
+#define gsl_HAVE_DEPRECATED_() gsl_HAVE_DEPRECATED
+
+// Presence of C++17 language features:
+// MSVC: template parameter deduction guides since Visual Studio 2017 v15.7
+
+#define gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE gsl_CPP17_000
+#define gsl_HAVE_DEDUCTION_GUIDES ( gsl_CPP17_000 && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION_FULL, 1, 1414 ) )
+#define gsl_HAVE_NODISCARD gsl_CPP17_000
+#define gsl_HAVE_CONSTEXPR_17 gsl_CPP17_OR_GREATER
+
+#define gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE_() gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
+#define gsl_HAVE_DEDUCTION_GUIDES_() gsl_HAVE_DEDUCTION_GUIDES
+#define gsl_HAVE_NODISCARD_() gsl_HAVE_NODISCARD
+#define gsl_HAVE_MAYBE_UNUSED_() gsl_CPP17_OR_GREATER
+#define gsl_HAVE_CONSTEXPR_17_() gsl_HAVE_CONSTEXPR_17
+
+// Presence of C++20 language features:
+
+#define gsl_HAVE_CONSTEXPR_20 gsl_CPP20_OR_GREATER
+#define gsl_HAVE_CONSTEXPR_20_() gsl_HAVE_CONSTEXPR_20
+
+// Presence of C++23 language features:
+
+#define gsl_HAVE_CONSTEXPR_23 gsl_CPP23_OR_GREATER
+#define gsl_HAVE_CONSTEXPR_23_() gsl_HAVE_CONSTEXPR_23
+
+// Presence of C++26 language features:
+
+#define gsl_HAVE_CONSTEXPR_26 gsl_CPP26_OR_GREATER
+#define gsl_HAVE_CONSTEXPR_26_() gsl_HAVE_CONSTEXPR_26
+
+// Presence of C++ library features:
+
+#if gsl_BETWEEN( gsl_COMPILER_ARMCC_VERSION, 1, 600 )
+// Some versions of the ARM compiler apparently ship without a C++11 standard library despite having some C++11 support.
+# define gsl_STDLIB_CPP98_OR_GREATER gsl_CPP98_OR_GREATER
+# define gsl_STDLIB_CPP11_OR_GREATER 0
+# define gsl_STDLIB_CPP14_OR_GREATER 0
+# define gsl_STDLIB_CPP17_OR_GREATER 0
+# define gsl_STDLIB_CPP20_OR_GREATER 0
+# define gsl_STDLIB_CPP23_OR_GREATER 0
+# define gsl_STDLIB_CPP26_OR_GREATER 0
+#else
+# define gsl_STDLIB_CPP98_OR_GREATER gsl_CPP98_OR_GREATER
+# define gsl_STDLIB_CPP11_OR_GREATER gsl_CPP11_OR_GREATER
+# define gsl_STDLIB_CPP14_OR_GREATER gsl_CPP14_OR_GREATER
+# define gsl_STDLIB_CPP17_OR_GREATER gsl_CPP17_OR_GREATER
+# define gsl_STDLIB_CPP20_OR_GREATER gsl_CPP20_OR_GREATER
+# define gsl_STDLIB_CPP23_OR_GREATER gsl_CPP23_OR_GREATER
+# define gsl_STDLIB_CPP26_OR_GREATER gsl_CPP26_OR_GREATER
+#endif
+
+#define gsl_STDLIB_CPP11_100 (gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1600)
+#define gsl_STDLIB_CPP11_110 (gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1700)
+#define gsl_STDLIB_CPP11_120 (gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800)
+#define gsl_STDLIB_CPP11_140 (gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_STDLIB_CPP14_000 (gsl_STDLIB_CPP14_OR_GREATER)
+#define gsl_STDLIB_CPP14_120 (gsl_STDLIB_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800)
+#define gsl_STDLIB_CPP14_140 (gsl_STDLIB_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_STDLIB_CPP17_000 (gsl_STDLIB_CPP17_OR_GREATER)
+#define gsl_STDLIB_CPP17_140 (gsl_STDLIB_CPP17_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_STDLIB_CPP11_140_CPP0X_90 (gsl_STDLIB_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1500 && gsl_HAS_CPP0X))
+#define gsl_STDLIB_CPP11_140_CPP0X_100 (gsl_STDLIB_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1600 && gsl_HAS_CPP0X))
+
+#define gsl_HAVE_ADDRESSOF gsl_STDLIB_CPP17_000
+#define gsl_HAVE_ARRAY gsl_STDLIB_CPP11_110
+#define gsl_HAVE_TYPE_TRAITS gsl_STDLIB_CPP11_110
+#define gsl_HAVE_TR1_TYPE_TRAITS gsl_STDLIB_CPP11_110
+#define gsl_HAVE_CONTAINER_DATA_METHOD gsl_STDLIB_CPP11_140_CPP0X_90
+#define gsl_HAVE_STD_DATA gsl_STDLIB_CPP17_000
+#ifdef __cpp_lib_ssize
+# define gsl_HAVE_STD_SSIZE 1
+#else
+# define gsl_HAVE_STD_SSIZE ( gsl_COMPILER_GNUC_VERSION >= 1000 && __cplusplus > 201703L )
+#endif
+#define gsl_HAVE_HASH gsl_STDLIB_CPP11_120
+#define gsl_HAVE_SIZED_TYPES gsl_STDLIB_CPP11_140
+#define gsl_HAVE_MAKE_SHARED gsl_STDLIB_CPP11_140_CPP0X_100
+#define gsl_HAVE_SHARED_PTR gsl_STDLIB_CPP11_140_CPP0X_100
+#define gsl_HAVE_UNIQUE_PTR gsl_STDLIB_CPP11_140_CPP0X_100
+#define gsl_HAVE_MAKE_UNIQUE gsl_STDLIB_CPP14_120
+#define gsl_HAVE_MOVE_FORWARD gsl_STDLIB_CPP11_100
+#define gsl_HAVE_NULLPTR gsl_STDLIB_CPP11_100
+#define gsl_HAVE_UNCAUGHT_EXCEPTIONS gsl_STDLIB_CPP17_140
+#define gsl_HAVE_ADD_CONST gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_INITIALIZER_LIST gsl_STDLIB_CPP11_120
+#define gsl_HAVE_INTEGRAL_CONSTANT gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_REMOVE_CONST gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_REMOVE_REFERENCE gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_REMOVE_CVREF gsl_STDLIB_CPP20_OR_GREATER
+#define gsl_HAVE_TR1_ADD_CONST gsl_HAVE_TR1_TYPE_TRAITS
+#define gsl_HAVE_TR1_INTEGRAL_CONSTANT gsl_HAVE_TR1_TYPE_TRAITS
+#define gsl_HAVE_TR1_REMOVE_CONST gsl_HAVE_TR1_TYPE_TRAITS
+#define gsl_HAVE_TR1_REMOVE_REFERENCE gsl_HAVE_TR1_TYPE_TRAITS
+
+#define gsl_HAVE_ADDRESSOF_() gsl_HAVE_ADDRESSOF
+#define gsl_HAVE_ARRAY_() gsl_HAVE_ARRAY
+#define gsl_HAVE_TYPE_TRAITS_() gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_TR1_TYPE_TRAITS_() gsl_HAVE_TR1_TYPE_TRAITS
+#define gsl_HAVE_CONTAINER_DATA_METHOD_() gsl_HAVE_CONTAINER_DATA_METHOD
+#define gsl_HAVE_HASH_() gsl_HAVE_HASH
+#define gsl_HAVE_STD_DATA_() gsl_HAVE_STD_DATA
+#define gsl_HAVE_STD_SSIZE_() gsl_HAVE_STD_SSIZE
+#define gsl_HAVE_SIZED_TYPES_() gsl_HAVE_SIZED_TYPES
+#define gsl_HAVE_MAKE_SHARED_() gsl_HAVE_MAKE_SHARED
+#define gsl_HAVE_MOVE_FORWARD_() gsl_HAVE_MOVE_FORWARD
+#define gsl_HAVE_NULLPTR_() gsl_HAVE_NULLPTR // It's a language feature but needs library support, so we list it as a library feature.
+#define gsl_HAVE_SHARED_PTR_() gsl_HAVE_SHARED_PTR
+#define gsl_HAVE_UNIQUE_PTR_() gsl_HAVE_UNIQUE_PTR
+#define gsl_HAVE_MAKE_UNIQUE_() gsl_HAVE_MAKE_UNIQUE
+#define gsl_HAVE_UNCAUGHT_EXCEPTIONS_() gsl_HAVE_UNCAUGHT_EXCEPTIONS
+#define gsl_HAVE_ADD_CONST_() gsl_HAVE_ADD_CONST
+#define gsl_HAVE_INITIALIZER_LIST_() gsl_HAVE_INITIALIZER_LIST // It's a language feature but needs library support, so we list it as a library feature.
+#define gsl_HAVE_INTEGRAL_CONSTANT_() gsl_HAVE_INTEGRAL_CONSTANT
+#define gsl_HAVE_REMOVE_CONST_() gsl_HAVE_REMOVE_CONST
+#define gsl_HAVE_REMOVE_REFERENCE_() gsl_HAVE_REMOVE_REFERENCE
+#define gsl_HAVE_REMOVE_CVREF_() gsl_HAVE_REMOVE_CVREF
+#define gsl_HAVE_TR1_ADD_CONST_() gsl_HAVE_TR1_ADD_CONST
+#define gsl_HAVE_TR1_INTEGRAL_CONSTANT_() gsl_HAVE_TR1_INTEGRAL_CONSTANT
+#define gsl_HAVE_TR1_REMOVE_CONST_() gsl_HAVE_TR1_REMOVE_CONST
+#define gsl_HAVE_TR1_REMOVE_REFERENCE_() gsl_HAVE_TR1_REMOVE_REFERENCE
+
+// C++ feature usage:
+
+#if gsl_HAVE( ADDRESSOF )
+# define gsl_ADDRESSOF(x) std::addressof(x)
+#else
+# define gsl_ADDRESSOF(x) (&x)
+#endif
+
+#if gsl_HAVE( CONSTEXPR_11 )
+# define gsl_constexpr constexpr
+#else
+# define gsl_constexpr /*constexpr*/
+#endif
+
+#if gsl_HAVE( CONSTEXPR_14 )
+# define gsl_constexpr14 constexpr
+#else
+# define gsl_constexpr14 /*constexpr*/
+#endif
+
+#if gsl_HAVE( CONSTEXPR_17 )
+# define gsl_constexpr17 constexpr
+#else
+# define gsl_constexpr17 /*constexpr*/
+#endif
+
+#if gsl_HAVE( CONSTEXPR_20 )
+# define gsl_constexpr20 constexpr
+#else
+# define gsl_constexpr20 /*constexpr*/
+#endif
+
+#if gsl_HAVE( CONSTEXPR_23 )
+# define gsl_constexpr23 constexpr
+#else
+# define gsl_constexpr23 /*constexpr*/
+#endif
+
+#if gsl_HAVE( CONSTEXPR_26 )
+# define gsl_constexpr26 constexpr
+#else
+# define gsl_constexpr26 /*constexpr*/
+#endif
+
+#if gsl_HAVE( EXPLICIT )
+# define gsl_explicit explicit
+#else
+# define gsl_explicit /*explicit*/
+#endif
+
+#if gsl_HAVE( IS_DELETE )
+# define gsl_is_delete = delete
+#else
+# define gsl_is_delete
+#endif
+
+#if gsl_HAVE( IS_DELETE )
+# define gsl_is_delete_access public
+#else
+# define gsl_is_delete_access private
+#endif
+
+#if gsl_HAVE( NOEXCEPT )
+# define gsl_noexcept noexcept
+# define gsl_noexcept_if( expr ) noexcept( expr )
+#else
+# define gsl_noexcept throw()
+# define gsl_noexcept_if( expr ) /*noexcept( expr )*/
+#endif
+#if defined( gsl_TESTING_ )
+# define gsl_noexcept_not_testing
+#else
+# define gsl_noexcept_not_testing gsl_noexcept
+#endif
+
+#if gsl_HAVE( NULLPTR )
+# define gsl_nullptr nullptr
+#else
+# define gsl_nullptr NULL
+#endif
+
+#if gsl_HAVE( NODISCARD )
+# define gsl_NODISCARD [[nodiscard]]
+#else
+# define gsl_NODISCARD
+#endif
+
+#if gsl_HAVE( NORETURN )
+# define gsl_NORETURN [[noreturn]]
+#elif defined( _MSC_VER )
+# define gsl_NORETURN __declspec(noreturn)
+#elif defined( __GNUC__ ) || gsl_COMPILER_ARMCC_VERSION
+# define gsl_NORETURN __attribute__((noreturn))
+#else
+# define gsl_NORETURN
+#endif
+
+#if gsl_CPP20_OR_GREATER
+# if defined( _MSC_VER ) // MSVC or MSVC-compatible compiler
+# if gsl_COMPILER_MSVC_VERSION >= 1929 || gsl_COMPILER_CLANG_VERSION >= 1800 // VS2019 v16.10 and later, or Clang 18 and later
+# define gsl_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
+# endif
+# else // ! defined( _MSC_VER )
+# define gsl_NO_UNIQUE_ADDRESS [[no_unique_address]]
+# endif // defined( _MSC_VER )
+#endif // gsl_CPP20_OR_GREATER
+
+#if gsl_HAVE( MAYBE_UNUSED )
+# define gsl_MAYBE_UNUSED [[maybe_unused]]
+# if gsl_COMPILER_GNUC_VERSION
+// GCC currently ignores the [[maybe_unused]] attribute on data members and warns accordingly (cf. https://stackoverflow.com/a/65633590).
+# define gsl_MAYBE_UNUSED_MEMBER
+# else // ! gsl_COMPILER_GNUC_VERSION
+# define gsl_MAYBE_UNUSED_MEMBER [[maybe_unused]]
+# endif // gsl_COMPILER_GNUC_VERSION
+#else
+# define gsl_MAYBE_UNUSED
+# define gsl_MAYBE_UNUSED_MEMBER
+#endif
+
+#if gsl_HAVE( DEPRECATED ) && ! defined( gsl_TESTING_ )
+# define gsl_DEPRECATED [[deprecated]]
+# define gsl_DEPRECATED_MSG( msg ) [[deprecated( msg )]]
+#else
+# define gsl_DEPRECATED
+# define gsl_DEPRECATED_MSG( msg )
+#endif
+
+#if gsl_HAVE( C99_PREPROCESSOR )
+# if gsl_CPP20_OR_GREATER
+# define gsl_CONSTRAINT(...) __VA_ARGS__
+# else
+# define gsl_CONSTRAINT(...) typename
+# endif
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS )
+# define gsl_STATIC_ASSERT_( cond, msg ) static_assert( cond, msg )
+#else
+# define gsl_STATIC_ASSERT_( cond, msg ) ( static_cast<void>( sizeof( char[1 - 2*!( cond ) ] ) ) )
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1900 // Visual Studio 2015 and newer, or Clang emulating a corresponding MSVC
+# define gsl_EMPTY_BASES_ __declspec(empty_bases)
+#else
+# define gsl_EMPTY_BASES_
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS )
+
+#define gsl_DEFINE_ENUM_BITMASK_OPERATORS_( ENUM ) \
+ gsl_MAYBE_UNUSED gsl_NODISCARD gsl_api inline gsl_constexpr ENUM \
+ operator~( ENUM val ) gsl_noexcept \
+ { \
+ typedef typename ::gsl_lite::std11::underlying_type<ENUM>::type U; \
+ return ENUM( ~U( val ) ); \
+ } \
+ gsl_MAYBE_UNUSED gsl_NODISCARD gsl_api inline gsl_constexpr ENUM \
+ operator|( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl_lite::std11::underlying_type<ENUM>::type U; \
+ return ENUM( U( lhs ) | U( rhs ) ); \
+ } \
+ gsl_MAYBE_UNUSED gsl_NODISCARD gsl_api inline gsl_constexpr ENUM \
+ operator&( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl_lite::std11::underlying_type<ENUM>::type U; \
+ return ENUM( U( lhs ) & U( rhs ) ); \
+ } \
+ gsl_MAYBE_UNUSED gsl_NODISCARD gsl_api inline gsl_constexpr ENUM \
+ operator^( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl_lite::std11::underlying_type<ENUM>::type U; \
+ return ENUM( U( lhs ) ^ U( rhs ) ); \
+ } \
+ gsl_MAYBE_UNUSED gsl_api inline gsl_constexpr14 ENUM & \
+ operator|=( ENUM & lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ return lhs = lhs | rhs; \
+ } \
+ gsl_MAYBE_UNUSED gsl_api inline gsl_constexpr14 ENUM & \
+ operator&=( ENUM & lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ return lhs = lhs & rhs; \
+ } \
+ gsl_MAYBE_UNUSED gsl_api inline gsl_constexpr14 ENUM & \
+ operator^=( ENUM & lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ return lhs = lhs ^ rhs; \
+ }
+
+#if gsl_STDLIB_CPP20_OR_GREATER
+# define gsl_DEFINE_ENUM_RELATIONAL_OPERATORS_( ENUM ) \
+ [[maybe_unused, nodiscard]] gsl_api inline constexpr std::strong_ordering \
+ operator<=>( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ using U = std::underlying_type_t<ENUM>; \
+ return U( lhs ) <=> U( rhs ); \
+ }
+#else // ! gsl_STDLIB_CPP20_OR_GREATER
+# define gsl_DEFINE_ENUM_RELATIONAL_OPERATORS_( ENUM ) \
+ gsl_MAYBE_UNUSED gsl_NODISCARD gsl_api inline gsl_constexpr bool \
+ operator<( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl_lite::std11::underlying_type<ENUM>::type U; \
+ return U( lhs ) < U( rhs ); \
+ } \
+ gsl_MAYBE_UNUSED gsl_NODISCARD gsl_api inline gsl_constexpr bool \
+ operator>( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl_lite::std11::underlying_type<ENUM>::type U; \
+ return U( lhs ) > U( rhs ); \
+ } \
+ gsl_MAYBE_UNUSED gsl_NODISCARD gsl_api inline gsl_constexpr bool \
+ operator<=( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl_lite::std11::underlying_type<ENUM>::type U; \
+ return U( lhs ) <= U( rhs ); \
+ } \
+ gsl_MAYBE_UNUSED gsl_NODISCARD gsl_api inline gsl_constexpr bool \
+ operator>=( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl_lite::std11::underlying_type<ENUM>::type U; \
+ return U( lhs ) >= U( rhs ); \
+ }
+#endif // gsl_STDLIB_CPP20_OR_GREATER
+
+ //
+ // Defines bitmask operators `|`, `&`, `^`, `~`, `|=`, `&=`, and `^=` for the given enum type.
+ //
+ // enum class Vegetables { tomato = 0b001, onion = 0b010, eggplant = 0b100 };
+ // gsl_DEFINE_ENUM_BITMASK_OPERATORS( Vegetables )
+ //
+#define gsl_DEFINE_ENUM_BITMASK_OPERATORS( ENUM ) gsl_DEFINE_ENUM_BITMASK_OPERATORS_( ENUM )
+
+ //
+ // Defines relational operators `<=>`, `<`, `>`, `<=`, `>=` for the given enum type.
+ //
+ // enum class OperatorPrecedence { additive = 0, multiplicative = 1, power = 2 };
+ // gsl_DEFINE_ENUM_RELATIONAL_OPERATORS( OperatorPrecedence )
+ //
+#define gsl_DEFINE_ENUM_RELATIONAL_OPERATORS( ENUM ) gsl_DEFINE_ENUM_RELATIONAL_OPERATORS_( ENUM )
+
+#endif // gsl_HAVE( TYPE_TRAITS )
+
+#define gsl_DIMENSION_OF( a ) ( sizeof(a) / sizeof(0[a]) )
+
+
+// Method enabling (C++98, VC120 (VS2013) cannot use __VA_ARGS__)
+
+#if gsl_HAVE( EXPRESSION_SFINAE )
+# define gsl_TRAILING_RETURN_TYPE_(T) auto
+# define gsl_RETURN_DECLTYPE_(EXPR) -> decltype( EXPR )
+#else
+# define gsl_TRAILING_RETURN_TYPE_(T) T
+# define gsl_RETURN_DECLTYPE_(EXPR)
+#endif
+
+// NOTE: When using SFINAE in gsl-lite, please note that overloads of function templates must always use SFINAE with non-type default arguments
+// as explained in https://en.cppreference.com/w/cpp/types/enable_if#Notes. `gsl_ENABLE_IF_()` implements graceful fallback to default
+// type arguments (for compilers that don't support non-type default arguments); please verify that this is appropriate in the given
+// situation, and add additional checks if necessary.
+//
+// Also, please note that `gsl_ENABLE_IF_()` doesn't enforce the constraint at all if no compiler/library support is available (i.e. pre-C++11).
+
+#if gsl_HAVE( TYPE_TRAITS )
+# define gsl_ENABLE_IF_R_( VA, T ) typename std::enable_if< ( VA ), T >::type
+#else // ! gsl_HAVE( TYPE_TRAITS )
+# define gsl_ENABLE_IF_R_( VA, T ) T
+#endif // gsl_HAVE( TYPE_TRAITS )
+
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+# define gsl_ENABLE_IF_NTTP_(VA) , typename std::enable_if< ( VA ), int >::type = 0
+# if ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 ) // VS 2013 seems to have trouble with SFINAE for default non-type arguments
+# define gsl_ENABLE_IF_(VA) , typename std::enable_if< ( VA ), int >::type = 0
+# else
+# define gsl_ENABLE_IF_(VA) , typename = typename std::enable_if< ( VA ), ::gsl_lite::detail::enabler >::type
+# endif
+#else
+# define gsl_ENABLE_IF_NTTP_(VA)
+# define gsl_ENABLE_IF_(VA)
+#endif
+
+
+// Link-time ABI incompatibility detection (MSVC only):
+
+#if defined( _MSC_VER ) && _MSC_VER >= 1900 // VS 2015 and newer
+# if gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+# define gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION_VAL_ 1
+# else
+# define gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION_VAL_ 0
+# endif
+# if defined( gsl_api )
+# define gsl_GSL_API_VAL_ gsl_api
+# else
+# define gsl_GSL_API_VAL_ default
+# endif
+//# pragma message( "v" gsl_STRINGIFY( gsl_lite_MAJOR ) " gsl_api:" gsl_STRINGIFY( gsl_GSL_API_VAL_ ) " gsl_CONFIG_SPAN_INDEX_TYPE:" gsl_STRINGIFY( gsl_CONFIG_SPAN_INDEX_TYPE ) " gsl_CONFIG_INDEX_TYPE:" gsl_STRINGIFY( gsl_CONFIG_INDEX_TYPE ) " gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION:" gsl_STRINGIFY( gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION_VAL_ ) )
+# pragma detect_mismatch( "gsl-lite", "v" gsl_STRINGIFY( gsl_lite_MAJOR ) " gsl_api:" gsl_STRINGIFY( gsl_GSL_API_VAL_ ) " gsl_CONFIG_SPAN_INDEX_TYPE:" gsl_STRINGIFY( gsl_CONFIG_SPAN_INDEX_TYPE ) " gsl_CONFIG_INDEX_TYPE:" gsl_STRINGIFY( gsl_CONFIG_INDEX_TYPE ) " gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION:" gsl_STRINGIFY( gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION_VAL_ ) )
+# undef gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION_VAL_
+# undef gsl_GSL_API_VAL_
+#endif // defined( _MSC_VER ) && _MSC_VER >= 1900
+
+
+// Other features:
+
+#define gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR ( gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG && gsl_HAVE_CONTAINER_DATA_METHOD )
+#define gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR_() gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR
+
+#define gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR ( gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR && gsl_COMPILER_NVCC_VERSION == 0 )
+#define gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR_() gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR
+
+// GSL API (e.g. for CUDA platform):
+
+// Guidelines for using `gsl_api`:
+//
+// NVCC imposes the restriction that a function annotated `__host__ __device__` cannot call host-only or device-only functions.
+// This makes `gsl_api` inappropriate for generic functions that call unknown code, e.g. the template constructors of `span<>`
+// or functions like `finally()` which accept an arbitrary function object.
+// It is often preferable to annotate functions only with `gsl_constexpr` or `gsl_constexpr14`. The "extended constexpr" mode
+// of NVCC (currently an experimental feature) will implicitly consider constexpr functions `__host__ __device__` functions
+// but tolerates calls to host-only or device-only functions.
+
+#if ! defined( gsl_api )
+# ifdef __CUDACC__
+# define gsl_api __host__ __device__
+# else
+# define gsl_api /*gsl_api*/
+# endif
+#endif
+
+// Additional includes:
+
+#if gsl_FEATURE( STRING_SPAN )
+# include <ios> // for ios_base, streamsize
+# include <string>
+#endif // gsl_FEATURE( STRING_SPAN )
+
+#if ! gsl_CPP11_OR_GREATER
+# include <algorithm> // for swap() before C++11
+#endif // ! gsl_CPP11_OR_GREATER
+
+#if gsl_HAVE( ARRAY )
+# include <array> // indirectly includes reverse_iterator<>
+#endif
+
+#if ! gsl_HAVE( ARRAY )
+# include <iterator> // for reverse_iterator<>
+#endif
+
+#if gsl_STDLIB_CPP20_OR_GREATER
+# include <compare>
+#endif // gsl_STDLIB_CPP20_OR_GREATER
+
+#if ! gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || ! gsl_HAVE( AUTO )
+# include <vector>
+#endif
+
+#if gsl_HAVE( INITIALIZER_LIST )
+# include <initializer_list>
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS ) || gsl_DEVICE_CODE
+# include <cassert>
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS ) && gsl_COMPILER_MSVC_VERSION >= 110 // __fastfail() supported by VS 2012 and later
+# include <intrin.h>
+#endif
+
+#if gsl_HAVE( ENUM_CLASS ) && ( gsl_COMPILER_ARMCC_VERSION || gsl_COMPILER_NVHPC_VERSION ) && !defined( _WIN32 )
+# include <endian.h>
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS )
+# include <type_traits> // for enable_if<>,
+ // add_const<>, add_pointer<>, common_type<>, make_signed<>, remove_cv<>, remove_const<>, remove_volatile<>, remove_reference<>, remove_cvref<>, remove_pointer<>, underlying_type<>,
+ // is_assignable<>, is_constructible<>, is_const<>, is_convertible<>, is_integral<>, is_pointer<>, is_signed<>,
+ // integral_constant<>, declval()
+#elif gsl_HAVE( TR1_TYPE_TRAITS )
+# include <tr1/type_traits> // for add_const<>, remove_cv<>, remove_const<>, remove_volatile<>, remove_reference<>, integral_constant<>
+#endif
+
+// Declare __cxa_get_globals() or equivalent in namespace gsl_lite::detail for uncaught_exceptions():
+
+#if ! gsl_HAVE( UNCAUGHT_EXCEPTIONS )
+# if defined( _MSC_VER ) // MS-STL with either MSVC or clang-cl
+namespace gsl_lite { namespace detail { extern "C" char * __cdecl _getptd(); } }
+# elif gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_APPLECLANG_VERSION || gsl_COMPILER_NVHPC_VERSION
+# if defined( __GLIBCXX__ ) || defined( __GLIBCPP__ ) // libstdc++: prototype from cxxabi.h
+# include <cxxabi.h>
+# elif ! defined( BOOST_CORE_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED_ ) // libc++: prototype from Boost?
+# if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
+namespace __cxxabiv1 { struct __cxa_eh_globals; extern "C" __cxa_eh_globals * __cxa_get_globals(); }
+# else
+namespace __cxxabiv1 { struct __cxa_eh_globals; extern "C" __cxa_eh_globals * __cxa_get_globals() gsl_noexcept; }
+# endif
+# endif
+ namespace gsl_lite { namespace detail { using ::__cxxabiv1::__cxa_get_globals; } }
+# endif
+#endif // ! gsl_HAVE( UNCAUGHT_EXCEPTIONS )
+
+
+// Warning suppression macros:
+
+#if gsl_COMPILER_MSVC_VERSION >= 140 && ! gsl_COMPILER_NVCC_VERSION
+# define gsl_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
+# define gsl_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) )
+# define gsl_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
+# define gsl_RESTORE_MSVC_WARNINGS() __pragma(warning(pop ))
+#else
+// TODO: define for Clang
+# define gsl_SUPPRESS_MSGSL_WARNING(expr)
+# define gsl_SUPPRESS_MSVC_WARNING(code, descr)
+# define gsl_DISABLE_MSVC_WARNINGS(codes)
+# define gsl_RESTORE_MSVC_WARNINGS()
+#endif
+
+// Warning suppressions:
+
+#if gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wweak-vtables" // because of `fail_fast` and `narrowing_error`
+#endif // gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+
+#if gsl_COMPILER_GNUC_VERSION
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wuseless-cast" // we use `static_cast<>()` in several places where it is possibly redundant depending on the configuration of the library
+#endif // gsl_COMPILER_GNUC_VERSION
+
+// Suppress the following MSVC GSL warnings:
+// - C26432: gsl::c.21 : if you define or delete any default operation in the type '...', define or delete them all
+// - C26410: gsl::r.32 : the parameter 'ptr' is a reference to const unique pointer, use const T* or const T& instead
+// - C26415: gsl::r.30 : smart pointer parameter 'ptr' is used only to access contained pointer. Use T* or T& instead
+// - C26418: gsl::r.36 : shared pointer parameter 'ptr' is not copied or moved. Use T* or T& instead
+// - C26472: gsl::t.1 : don't use a static_cast for arithmetic conversions;
+// use brace initialization, gsl_lite::narrow_cast or gsl_lite::narrow
+// - C26439: gsl::f.6 : special function 'function' can be declared 'noexcept'
+// - C26440: gsl::f.6 : function 'function' can be declared 'noexcept'
+// - C26455: gsl::f.6 : default constructor may not throw. Declare it 'noexcept'
+// - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same
+// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
+// - C26482: gsl::b.2 : only index into arrays using constant expressions
+// - C26446: gsl::b.4 : prefer to use gsl_lite::at() instead of unchecked subscript operator
+// - C26490: gsl::t.1 : don't use reinterpret_cast
+// - C26487: gsl::l.4 : don't return a pointer '(<some number>'s result)' that may be invalid
+// - C26434: gsl::c.128 : function 'symbol_1' hides a non-virtual function 'symbol_2' (false positive for compiler-generated functions such as constructors)
+// - C26456: gsl::c.128 : operator 'symbol_1' hides a non-virtual operator 'symbol_2' (false positive for compiler-generated operators)
+// - C26457: es.48 : (void) should not be used to ignore return values, use 'std::ignore =' instead
+
+gsl_DISABLE_MSVC_WARNINGS( 26432 26410 26415 26418 26472 26439 26440 26455 26473 26481 26482 26446 26490 26487 26434 26456 26457 )
+#if gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 110, 140 ) // VS 2012 and 2013
+# pragma warning(disable: 4127) // conditional expression is constant
+#endif // gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 110, 140 )
+#if gsl_COMPILER_MSVC_VERSION == 140 // VS 2015
+# pragma warning(disable: 4577) // 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
+#endif // gsl_COMPILER_MSVC_VERSION == 140
+
+namespace gsl_lite {
+
+// forward declare span<>:
+
+#if gsl_CPP17_OR_GREATER
+inline
+#endif // gsl_CPP17_OR_GREATER
+gsl_constexpr const gsl_CONFIG_SPAN_INDEX_TYPE dynamic_extent = static_cast<gsl_CONFIG_SPAN_INDEX_TYPE>( -1 );
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent = dynamic_extent >
+class span;
+
+namespace detail {
+
+#if gsl_FEATURE( STRING_SPAN ) || gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+// We implement `equal()` and `lexicographical_compare()` here to avoid having to pull in the <algorithm> header.
+template< class InputIt1, class InputIt2 >
+bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2 )
+{
+ // Implementation borrowed from https://en.cppreference.com/w/cpp/algorithm/equal.
+ for ( ; first1 != last1; ++first1, ++first2 )
+ {
+ if ( ! (*first1 == *first2 ) ) return false;
+ }
+ return true;
+}
+template< class InputIt1, class InputIt2 >
+bool lexicographical_compare( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2 )
+{
+ // Implementation borrowed from https://en.cppreference.com/w/cpp/algorithm/lexicographical_compare.
+ for ( ; first1 != last1 && first2 != last2; ++first1, static_cast< void >( ++first2 ) )
+ {
+ if ( *first1 < *first2 ) return true;
+ if ( *first2 < *first1 ) return false;
+ }
+ return first1 == last1 && first2 != last2;
+}
+#endif // gsl_FEATURE( STRING_SPAN ) || gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+
+} // namespace detail
+
+// C++11 emulation:
+
+namespace std11 {
+
+template< class T > struct add_const { typedef const T type; };
+
+template< class T > struct remove_const { typedef T type; };
+template< class T > struct remove_const<T const> { typedef T type; };
+
+template< class T > struct remove_volatile { typedef T type; };
+template< class T > struct remove_volatile<T volatile> { typedef T type; };
+
+template< class T >
+struct remove_cv
+{
+ typedef typename remove_volatile<typename remove_const<T>::type>::type type;
+};
+
+template< class T > struct remove_reference { typedef T type; };
+template< class T > struct remove_reference<T&> { typedef T type; };
+#if gsl_HAVE( RVALUE_REFERENCE )
+template< class T > struct remove_reference<T&&> { typedef T type; };
+#endif
+
+#if gsl_HAVE( ALIAS_TEMPLATE )
+template< class T > using add_const_t = typename add_const<T>::type;
+template< class T > using remove_const_t = typename remove_const<T>::type;
+template< class T > using remove_volatile_t = typename remove_volatile<T>::type;
+template< class T > using remove_cv_t = typename remove_cv<T>::type;
+template< class T > using remove_reference_t = typename remove_reference<T>::type;
+#endif // gsl_HAVE( ALIAS_TEMPLATE )
+
+
+#if gsl_HAVE( INTEGRAL_CONSTANT )
+
+using std::integral_constant;
+using std::true_type;
+using std::false_type;
+
+#elif gsl_HAVE( TR1_INTEGRAL_CONSTANT )
+
+using std::tr1::integral_constant;
+using std::tr1::true_type;
+using std::tr1::false_type;
+
+#else
+
+template< class T, T v > struct integral_constant { enum { value = v }; };
+typedef integral_constant< bool, true > true_type;
+typedef integral_constant< bool, false > false_type;
+
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS )
+
+using std::underlying_type;
+
+#elif gsl_HAVE( TR1_TYPE_TRAITS )
+
+using std::tr1::underlying_type;
+
+#else
+
+// We could try to define `underlying_type<>` for pre-C++11 here, but let's not until someone actually needs it.
+
+#endif
+
+} // namespace std11
+
+// C++14 emulation:
+
+namespace std14 {
+
+#if gsl_HAVE( UNIQUE_PTR )
+# if gsl_HAVE( MAKE_UNIQUE )
+
+using std::make_unique;
+
+# elif gsl_HAVE( VARIADIC_TEMPLATE )
+
+template< class T, class... Args >
+gsl_NODISCARD std::unique_ptr<T>
+make_unique( Args &&... args )
+{
+# if gsl_HAVE( TYPE_TRAITS )
+ static_assert( !std::is_array<T>::value, "make_unique<T[]>() is not part of C++14" );
+# endif
+ return std::unique_ptr<T>( new T( std::forward<Args>( args )... ) );
+}
+
+# endif // gsl_HAVE( MAKE_UNIQUE ), gsl_HAVE( VARIADIC_TEMPLATE )
+#endif // gsl_HAVE( UNIQUE_PTR )
+
+} // namespace std14
+
+namespace detail {
+
+#if gsl_HAVE( VARIADIC_TEMPLATE )
+
+template < bool V0, class T0, class... Ts > struct conjunction_ { using type = T0; };
+template < class T0, class T1, class... Ts > struct conjunction_<true, T0, T1, Ts...> : conjunction_<T1::value, T1, Ts...> { };
+template < bool V0, class T0, class... Ts > struct disjunction_ { using type = T0; };
+template < class T0, class T1, class... Ts > struct disjunction_<false, T0, T1, Ts...> : disjunction_<T1::value, T1, Ts...> { };
+
+#else // a.k.a. ! gsl_HAVE( VARIADIC_TEMPLATE )
+
+template < bool V0, class T0, class T1 > struct conjunction_ { typedef T0 type; };
+template < class T0, class T1 > struct conjunction_<true, T0, T1> { typedef T1 type; };
+template < bool V0, class T0, class T1 > struct disjunction_ { typedef T0 type; };
+template < class T0, class T1 > struct disjunction_<false, T0, T1> { typedef T1 type; };
+
+#endif // gsl_HAVE( VARIADIC_TEMPLATE )
+
+
+template <typename> struct dependent_false : std11::integral_constant<bool, false> { };
+
+} // namespace detail
+
+// C++17 emulation:
+
+namespace std17 {
+
+template< bool v > struct bool_constant : std11::integral_constant<bool, v>{};
+
+template < class T > struct negation : std11::integral_constant<bool, !T::value> { };
+
+#if gsl_CPP11_120
+
+template < class... Ts > struct conjunction;
+template < > struct conjunction< > : std11::true_type { };
+template < class T0, class... Ts > struct conjunction<T0, Ts...> : detail::conjunction_<T0::value, T0, Ts...>::type { };
+template < class... Ts > struct disjunction;
+template < > struct disjunction< > : std11::false_type { };
+template < class T0, class... Ts > struct disjunction<T0, Ts...> : detail::disjunction_<T0::value, T0, Ts...>::type { };
+
+# if gsl_CPP14_OR_GREATER
+
+template < class... Ts > constexpr bool conjunction_v = conjunction<Ts...>::value;
+template < class... Ts > constexpr bool disjunction_v = disjunction<Ts...>::value;
+template < class T > constexpr bool negation_v = negation<T>::value;
+
+# endif // gsl_CPP14_OR_GREATER
+
+template< class... Ts >
+struct make_void { typedef void type; };
+
+template< class... Ts >
+using void_t = typename make_void< Ts... >::type;
+
+#else // a.k.a. ! gsl_CPP11_120
+
+// For C++98, define simpler binary variants of `conjunction<>` and `disjunction<>`.
+template < class T0, class T1 > struct conjunction : detail::conjunction_<T0::value, T0, T1>::type { };
+template < class T0, class T1 > struct disjunction : detail::disjunction_<T0::value, T0, T1>::type { };
+
+#endif // gsl_CPP11_120
+
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+template< class T, size_t N >
+gsl_NODISCARD gsl_api inline gsl_constexpr auto
+size( T const(&)[N] ) gsl_noexcept -> size_t
+{
+ return N;
+}
+
+template< class C >
+gsl_NODISCARD inline gsl_constexpr auto
+size( C const & cont ) -> decltype( cont.size() )
+{
+ return cont.size();
+}
+
+template< class T, size_t N >
+gsl_NODISCARD gsl_api inline gsl_constexpr auto
+data( T(&arr)[N] ) gsl_noexcept -> T*
+{
+ return &arr[0];
+}
+
+template< class C >
+gsl_NODISCARD inline gsl_constexpr auto
+data( C & cont ) -> decltype( cont.data() )
+{
+ return cont.data();
+}
+
+template< class C >
+gsl_NODISCARD inline gsl_constexpr auto
+data( C const & cont ) -> decltype( cont.data() )
+{
+ return cont.data();
+}
+
+# if gsl_HAVE( INITIALIZER_LIST )
+template< class E >
+gsl_NODISCARD inline gsl_constexpr E const *
+data( std::initializer_list<E> il ) gsl_noexcept
+{
+ return il.begin();
+}
+# endif // gsl_HAVE( INITIALIZER_LIST )
+
+#endif // gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+} // namespace std17
+
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+using std17::data;
+using std17::size;
+#endif // gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+// C++20 emulation:
+
+namespace std20 {
+
+#if gsl_CPP11_100
+
+struct identity
+{
+ template < class T >
+ gsl_constexpr T && operator ()( T && arg ) const gsl_noexcept
+ {
+ return std::forward<T>( arg );
+ }
+};
+
+# if gsl_HAVE( ENUM_CLASS )
+enum class endian
+{
+# if defined( _WIN32 )
+ little = 0,
+ big = 1,
+ native = little
+# elif gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+ little = __ORDER_LITTLE_ENDIAN__,
+ big = __ORDER_BIG_ENDIAN__,
+ native = __BYTE_ORDER__
+# elif gsl_COMPILER_ARMCC_VERSION || gsl_COMPILER_NVHPC_VERSION
+ // from <endian.h> header file
+ little = __LITTLE_ENDIAN,
+ big = __BIG_ENDIAN,
+ native = __BYTE_ORDER
+# else
+// Do not define any endianness constants for unknown compilers.
+# endif
+};
+# endif // gsl_HAVE( ENUM_CLASS )
+
+#endif // gsl_CPP11_100
+
+template< class T >
+struct type_identity
+{
+ typedef T type;
+};
+#if gsl_HAVE( ALIAS_TEMPLATE )
+template< class T >
+using type_identity_t = typename type_identity<T>::type;
+#endif // gsl_HAVE( ALIAS_TEMPLATE )
+
+#if gsl_HAVE( STD_SSIZE )
+
+using std::ssize;
+
+#elif gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+template < class C >
+gsl_NODISCARD gsl_constexpr auto
+ssize( C const & c )
+ -> typename std::common_type<std::ptrdiff_t, typename std::make_signed<decltype(c.size())>::type>::type
+{
+ using R = typename std::common_type<std::ptrdiff_t, typename std::make_signed<decltype(c.size())>::type>::type;
+ return static_cast<R>( c.size() );
+}
+
+template <class T, std::size_t N>
+gsl_NODISCARD gsl_constexpr auto
+ssize( T const(&)[N] ) gsl_noexcept -> std::ptrdiff_t
+{
+ return std::ptrdiff_t( N );
+}
+
+#endif // gsl_HAVE( STD_SSIZE )
+
+template< class T > struct remove_cvref { typedef typename std11::remove_cv< typename std11::remove_reference< T >::type >::type type; };
+#if gsl_HAVE( ALIAS_TEMPLATE )
+template< class T > using remove_cvref_t = typename remove_cvref<T>::type;
+#endif // gsl_HAVE( ALIAS_TEMPLATE )
+
+} // namespace std20
+
+#if gsl_HAVE( STD_SSIZE ) || gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+using std20::ssize;
+#endif // gsl_HAVE( STD_SSIZE ) || gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+#if gsl_CPP11_100
+using std20::identity;
+#endif // gsl_CPP11_100
+using std20::type_identity;
+#if gsl_HAVE( ALIAS_TEMPLATE )
+using std20::type_identity_t;
+#endif // gsl_HAVE( ALIAS_TEMPLATE )
+
+// C++23 emulation:
+
+namespace std23 {
+
+} // namespace std23
+
+namespace detail {
+
+/// for gsl_ENABLE_IF_()
+
+/*enum*/ class enabler{};
+
+#if gsl_HAVE( TYPE_TRAITS )
+
+template< class Q >
+struct is_span_oracle : std::false_type{};
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+struct is_span_oracle< span<T, Extent > > : std::true_type{};
+
+template< class Q >
+struct is_span : is_span_oracle< typename std::remove_cv<Q>::type >{};
+
+template< class Q >
+struct is_std_array_oracle : std::false_type{};
+
+# if gsl_HAVE( ARRAY )
+
+template< class T, std::size_t Extent >
+struct is_std_array_oracle< std::array<T, Extent> > : std::true_type{};
+
+# endif
+
+template< class Q >
+struct is_std_array : is_std_array_oracle< typename std::remove_cv<Q>::type >{};
+
+template< class Q >
+struct is_array : std::false_type{};
+
+template< class T >
+struct is_array<T[]> : std::true_type{};
+
+template< class T, std::size_t N >
+struct is_array<T[N]> : std::true_type{};
+
+# if gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 500 )
+
+template< class, class = void >
+struct has_size_and_data : std::false_type{};
+
+template< class C >
+struct has_size_and_data
+<
+ C, std17::void_t<
+ decltype( std17::size(std::declval<C>()) ),
+ decltype( std17::data(std::declval<C>()) ) >
+> : std::true_type{};
+
+template< class, class, class = void >
+struct is_compatible_element : std::false_type {};
+
+template< class C, class E >
+struct is_compatible_element
+<
+ C, E, std17::void_t<
+ decltype( std17::data(std::declval<C>()) ),
+ typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[] >
+> : std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >{};
+
+template< class C >
+struct is_container : std17::bool_constant
+<
+ ! is_span< C >::value
+ && ! is_array< C >::value
+ && ! is_std_array< C >::value
+ && has_size_and_data< C >::value
+>{};
+
+template< class C, class E >
+struct is_compatible_container : std17::bool_constant
+<
+ is_container<C>::value
+ && is_compatible_element<C,E>::value
+>{};
+
+# else // ^^^ gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 500 ) ^^^ / vvv ! gsl_CPP11_140 || gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 500 ) vvv
+
+template<
+ class C, class E
+ , typename = typename std::enable_if<
+ ! is_span< C >::value
+ && ! is_array< C >::value
+ && ! is_std_array< C >::value
+ && ( std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >::value)
+ // && has_size_and_data< C >::value
+ , enabler>::type
+ , class = decltype( std17::size(std::declval<C>()) )
+ , class = decltype( std17::data(std::declval<C>()) )
+>
+# if gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+// VS2013 has insufficient support for expression SFINAE; we cannot make `is_compatible_container<>` a proper type trait here
+struct is_compatible_container : std::true_type { };
+# else
+struct is_compatible_container_r { is_compatible_container_r(int); };
+template< class C, class E >
+std::true_type is_compatible_container_f( is_compatible_container_r<C, E> );
+template< class C, class E >
+std::false_type is_compatible_container_f( ... );
+
+template< class C, class E >
+struct is_compatible_container : decltype( is_compatible_container_f< C, E >( 0 ) ) { };
+# endif // gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+
+# endif // gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 500 )
+
+#endif // gsl_HAVE( TYPE_TRAITS )
+
+} // namespace detail
+
+//
+// GSL.util: utilities
+//
+
+// Integer type for indices (e.g. in a loop).
+typedef gsl_CONFIG_INDEX_TYPE index;
+
+// Integer type for dimensions.
+typedef gsl_CONFIG_INDEX_TYPE dim;
+
+// Integer type for array strides.
+typedef gsl_CONFIG_INDEX_TYPE stride;
+
+// Integer type for pointer, iterator, or index differences.
+typedef gsl_CONFIG_INDEX_TYPE diff;
+
+//
+// GSL.owner: ownership pointers
+//
+#if gsl_HAVE( SHARED_PTR )
+using std::unique_ptr;
+using std::shared_ptr;
+#endif
+
+#if gsl_HAVE( ALIAS_TEMPLATE )
+ template< class T
+# if gsl_HAVE( TYPE_TRAITS )
+ , typename = typename std::enable_if< std::is_pointer<T>::value >::type
+# endif
+ >
+ using owner = T;
+#endif
+
+#define gsl_HAVE_OWNER_TEMPLATE gsl_HAVE_ALIAS_TEMPLATE
+#define gsl_HAVE_OWNER_TEMPLATE_() gsl_HAVE_OWNER_TEMPLATE
+
+//
+// GSL.assert: assertions
+//
+
+#define gsl_NO_OP_() ( static_cast<void>( 0 ) )
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_CONFIG( VALIDATES_UNENFORCED_CONTRACT_EXPRESSIONS )
+# define gsl_ELIDE_( x ) static_assert( ::std::is_constructible<bool, decltype( x )>::value, "argument of contract check must be convertible to bool" )
+#else
+# define gsl_ELIDE_( x ) gsl_NO_OP_()
+#endif
+
+#if gsl_COMPILER_NVHPC_VERSION
+// Suppress "controlling expression is constant" warning when using `gsl_Expects()`, `gsl_Ensures()`, `gsl_Assert()`, etc.
+# define gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ _Pragma("diag_suppress 236")
+# define gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ _Pragma("diag_default 236")
+#else
+# define gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_
+# define gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_
+#endif
+
+#if gsl_DEVICE_CODE
+# if defined( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME )
+# if gsl_COMPILER_NVCC_VERSION >= 113
+# define gsl_ASSUME_( x ) ( __builtin_assume( !!( x ) ) )
+# define gsl_ASSUME_UNREACHABLE_() __builtin_unreachable()
+# else // unknown device compiler
+# error gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ASSUME: gsl-lite does not know how to generate UB optimization hints in device code for this compiler; use gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE instead
+# endif
+# define gsl_CONTRACT_UNENFORCED_( x ) gsl_ASSUME_( x )
+# else // defined( gsl_CONFIG_DEVICE_UNENFORCED_CONTRACTS_ELIDE ) [default]
+# define gsl_CONTRACT_UNENFORCED_( x ) gsl_ELIDE_( x )
+# endif
+#else // host code
+# if defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+# if gsl_COMPILER_MSVC_VERSION >= 140
+# define gsl_ASSUME_( x ) __assume( x )
+# define gsl_ASSUME_UNREACHABLE_() __assume( 0 )
+# elif gsl_COMPILER_GNUC_VERSION
+# define gsl_ASSUME_( x ) ( ( x ) ? static_cast<void>(0) : __builtin_unreachable() )
+# define gsl_ASSUME_UNREACHABLE_() __builtin_unreachable()
+# elif defined(__has_builtin)
+# if __has_builtin(__builtin_unreachable)
+# define gsl_ASSUME_( x ) ( ( x ) ? static_cast<void>(0) : __builtin_unreachable() )
+# define gsl_ASSUME_UNREACHABLE_() __builtin_unreachable()
+# else
+# error gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME: gsl-lite does not know how to generate UB optimization hints for this compiler; use gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE instead
+# endif
+# else
+# error gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME: gsl-lite does not know how to generate UB optimization hints for this compiler; use gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE instead
+# endif
+# define gsl_CONTRACT_UNENFORCED_( x ) gsl_ASSUME_( x )
+# else // defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE ) [default]
+# define gsl_CONTRACT_UNENFORCED_( x ) gsl_ELIDE_( x )
+# endif
+#endif // gsl_DEVICE_CODE
+
+#if gsl_DEVICE_CODE
+# if gsl_COMPILER_NVCC_VERSION
+# define gsl_TRAP_() __trap()
+# elif defined(__has_builtin)
+# if __has_builtin(__builtin_trap)
+# define gsl_TRAP_() __builtin_trap()
+# else
+# error gsl-lite does not know how to generate a trap instruction for this device compiler
+# endif
+# else
+# error gsl-lite does not know how to generate a trap instruction for this device compiler
+# endif
+# if defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_TRAPS )
+# define gsl_CONTRACT_CHECK_( str, x ) ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ ( x ) ? static_cast<void>(0) : gsl_TRAP_() gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ )
+# define gsl_FAILFAST_() ( gsl_TRAP_() )
+# elif defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_CALLS_HANDLER )
+# define gsl_CONTRACT_CHECK_( str, x ) ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ ( x ) ? static_cast<void>(0) : ::gsl_lite::fail_fast_assert_handler( #x, str, __FILE__, __LINE__ ) gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ )
+# define gsl_FAILFAST_() ( ::gsl_lite::fail_fast_assert_handler( "", "gsl-lite: failure", __FILE__, __LINE__ ), gsl_TRAP_() ) /* do not let the custom assertion handler continue execution */
+# else // defined( gsl_CONFIG_DEVICE_CONTRACT_VIOLATION_ASSERTS ) [default]
+# if ! defined( NDEBUG )
+# define gsl_CONTRACT_CHECK_( str, x ) assert( str && ( x ) )
+# else
+# define gsl_CONTRACT_CHECK_( str, x ) ( ( x ) ? static_cast<void>(0) : gsl_TRAP_() )
+# endif
+# define gsl_FAILFAST_() ( gsl_TRAP_() )
+# endif
+#else // host code
+# if defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+# if gsl_COMPILER_MSVC_VERSION >= 110 // __fastfail() supported by VS 2012 and later
+# define gsl_TRAP_() __fastfail( 0 ) /* legacy failure code for buffer-overrun errors, cf. winnt.h, "Fast fail failure codes" */
+# elif gsl_COMPILER_GNUC_VERSION
+# define gsl_TRAP_() __builtin_trap()
+# elif defined(__has_builtin)
+# if __has_builtin(__builtin_trap)
+# define gsl_TRAP_() __builtin_trap()
+# else
+# error gsl_CONFIG_CONTRACT_VIOLATION_TRAPS: gsl-lite does not know how to generate a trap instruction for this compiler; use gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES instead
+# endif
+# else
+# error gsl_CONFIG_CONTRACT_VIOLATION_TRAPS: gsl-lite does not know how to generate a trap instruction for this compiler; use gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES instead
+# endif
+# define gsl_CONTRACT_CHECK_( str, x ) ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ ( x ) ? static_cast<void>(0) : gsl_TRAP_() gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ )
+# if gsl_COMPILER_MSVC_VERSION
+# define gsl_FAILFAST_() ( gsl_TRAP_(), ::gsl_lite::detail::fail_fast_terminate() )
+# else
+# define gsl_FAILFAST_() ( gsl_TRAP_() )
+# endif
+# elif defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# define gsl_CONTRACT_CHECK_( str, x ) ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ ( x ) ? static_cast<void>(0) : ::gsl_lite::fail_fast_assert_handler( #x, str, __FILE__, __LINE__ ) gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ )
+# define gsl_FAILFAST_() ( ::gsl_lite::fail_fast_assert_handler( "", "gsl-lite: failure", __FILE__, __LINE__ ), ::gsl_lite::detail::fail_fast_terminate() ) /* do not let the custom assertion handler continue execution */
+# elif defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS )
+# if ! defined( NDEBUG )
+# define gsl_CONTRACT_CHECK_( str, x ) ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ assert( str && ( x ) ) gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ )
+# define gsl_FAILFAST_() ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ assert( ! "gsl-lite: failure" ) gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_, ::gsl_lite::detail::fail_fast_abort() )
+# else
+# define gsl_CONTRACT_CHECK_( str, x ) ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ ( x ) ? static_cast<void>(0) : ::gsl_lite::detail::fail_fast_abort() gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ )
+# define gsl_FAILFAST_() ( ::gsl_lite::detail::fail_fast_abort() )
+# endif
+# elif defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS )
+# define gsl_CONTRACT_CHECK_( str, x ) ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ ( ( x ) ? static_cast<void>(0) : ::gsl_lite::detail::fail_fast_throw( str ": '" #x "' at " __FILE__ ":" gsl_STRINGIFY(__LINE__) ) ) gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ )
+# define gsl_FAILFAST_() ( ::gsl_lite::detail::fail_fast_throw( "gsl-lite: failure at " __FILE__ ":" gsl_STRINGIFY(__LINE__) ) )
+# else // defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) [default]
+# define gsl_CONTRACT_CHECK_( str, x ) ( gsl_SUPPRESS_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ ( ( x ) ? static_cast<void>(0) : ::gsl_lite::detail::fail_fast_terminate() ) gsl_RESTORE_NVHPC_CONTROLLING_EXPRESSION_IS_CONSTANT_ )
+# define gsl_FAILFAST_() ( ::gsl_lite::detail::fail_fast_terminate() )
+# endif
+#endif // gsl_DEVICE_CODE
+
+#if ( !gsl_DEVICE_CODE && defined( gsl_CONFIG_CONTRACT_CHECKING_OFF ) ) || ( gsl_DEVICE_CODE && defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_OFF ) )
+# define gsl_CHECK_CONTRACTS_ 0
+# define gsl_CHECK_DEBUG_CONTRACTS_ 0
+# define gsl_CHECK_AUDIT_CONTRACTS_ 0
+#elif ( !gsl_DEVICE_CODE && defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT ) ) || ( gsl_DEVICE_CODE && defined( gsl_CONFIG_DEVICE_CONTRACT_CHECKING_AUDIT ) )
+# define gsl_CHECK_CONTRACTS_ 1
+# define gsl_CHECK_DEBUG_CONTRACTS_ 1
+# define gsl_CHECK_AUDIT_CONTRACTS_ 1
+#else // gsl_CONFIG_[DEVICE_]CONTRACT_CHECKING_ON [default]
+# define gsl_CHECK_CONTRACTS_ 1
+# if !defined( NDEBUG )
+# define gsl_CHECK_DEBUG_CONTRACTS_ 1
+# else // defined( NDEBUG )
+# define gsl_CHECK_DEBUG_CONTRACTS_ 0
+# endif
+# define gsl_CHECK_AUDIT_CONTRACTS_ 0
+#endif
+
+#if gsl_CHECK_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# define gsl_Expects( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Precondition failure", x )
+#else
+# define gsl_Expects( x ) gsl_CONTRACT_UNENFORCED_( x )
+#endif
+#if gsl_CHECK_DEBUG_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# define gsl_ExpectsDebug( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Precondition failure (debug)", x )
+#else
+# define gsl_ExpectsDebug( x ) gsl_ELIDE_( x )
+#endif
+#if gsl_CHECK_AUDIT_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# define gsl_ExpectsAudit( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Precondition failure (audit)", x )
+#else
+# define gsl_ExpectsAudit( x ) gsl_ELIDE_( x )
+#endif
+
+#if gsl_CHECK_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# define gsl_Ensures( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Postcondition failure", x )
+#else
+# define gsl_Ensures( x ) gsl_CONTRACT_UNENFORCED_( x )
+#endif
+#if gsl_CHECK_DEBUG_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# define gsl_EnsuresDebug( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Postcondition failure (debug)", x )
+#else
+# define gsl_EnsuresDebug( x ) gsl_ELIDE_( x )
+#endif
+#if gsl_CHECK_AUDIT_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# define gsl_EnsuresAudit( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Postcondition failure (audit)", x )
+#else
+# define gsl_EnsuresAudit( x ) gsl_ELIDE_( x )
+#endif
+
+#if gsl_CHECK_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# define gsl_Assert( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Assertion failure", x )
+#else
+# define gsl_Assert( x ) gsl_CONTRACT_UNENFORCED_( x )
+#endif
+#if gsl_CHECK_DEBUG_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# define gsl_AssertDebug( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Assertion failure (debug)", x )
+#else
+# define gsl_AssertDebug( x ) gsl_ELIDE_( x )
+#endif
+#if gsl_CHECK_AUDIT_CONTRACTS_ && !defined( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# define gsl_AssertAudit( x ) gsl_CONTRACT_CHECK_( "gsl-lite: Assertion failure (audit)", x )
+#else
+# define gsl_AssertAudit( x ) gsl_ELIDE_( x )
+#endif
+
+#define gsl_FailFast() gsl_FAILFAST_()
+
+#undef gsl_CHECK_CONTRACTS_
+#undef gsl_CHECK_DEBUG_CONTRACTS_
+#undef gsl_CHECK_AUDIT_CONTRACTS_
+
+
+struct fail_fast : public std::logic_error
+{
+ explicit fail_fast( char const * message )
+ : std::logic_error( message ) {}
+};
+
+namespace detail {
+
+
+#if gsl_HAVE( EXCEPTIONS )
+gsl_NORETURN inline void fail_fast_throw( char const * message )
+{
+ throw fail_fast( message );
+}
+#endif // gsl_HAVE( EXCEPTIONS )
+gsl_NORETURN inline void fail_fast_terminate() gsl_noexcept
+{
+ std::terminate();
+}
+gsl_NORETURN inline void fail_fast_abort() gsl_noexcept
+{
+ std::abort();
+}
+
+} // namespace detail
+
+// Should be defined by user
+gsl_api void fail_fast_assert_handler( char const * expression, char const * message, char const * file, int line );
+
+//
+// GSL.util: utilities
+//
+
+// Add uncaught_exceptions() for pre-2017 MSVC, GCC and Clang
+
+namespace std17 {
+
+#if gsl_HAVE( UNCAUGHT_EXCEPTIONS )
+
+inline int uncaught_exceptions() gsl_noexcept
+{
+ return std::uncaught_exceptions();
+}
+
+#else // ! gsl_HAVE( UNCAUGHT_EXCEPTIONS )
+# if defined( _MSC_VER ) // MS-STL with either MSVC or clang-cl
+
+inline int uncaught_exceptions() gsl_noexcept
+{
+ return static_cast<int>( *reinterpret_cast<unsigned const*>( detail::_getptd() + (sizeof(void *) == 8 ? 0x100 : 0x90 ) ) );
+}
+
+# elif gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_APPLECLANG_VERSION || gsl_COMPILER_NVHPC_VERSION
+
+inline int uncaught_exceptions() gsl_noexcept
+{
+ return ( static_cast<int>( *reinterpret_cast<unsigned const *>( reinterpret_cast<unsigned char const *>(detail::__cxa_get_globals()) + sizeof(void *) ) ) );
+}
+
+# endif
+#endif
+
+} // namespace std17
+
+namespace std11 {
+
+#if gsl_HAVE( UNCAUGHT_EXCEPTIONS ) || defined( _MSC_VER ) || gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_APPLECLANG_VERSION || gsl_COMPILER_NVHPC_VERSION
+// Retain alias for backward compatibility
+using ::gsl_lite::std17::uncaught_exceptions;
+#endif
+
+} // namespace std11
+
+#if gsl_STDLIB_CPP11_110
+
+gsl_DISABLE_MSVC_WARNINGS( 4702 ) // unreachable code
+
+template< class F >
+class final_action
+# if gsl_HAVE( OVERRIDE_FINAL )
+final
+# endif
+{
+public:
+ explicit final_action( F action ) gsl_noexcept
+ : action_( std::move( action ) ), invoke_( true )
+ {
+ }
+
+ // We only provide the move constructor for legacy defaults, or if we cannot rely on C++17 guaranteed copy elision.
+# if ! gsl_CPP17_OR_GREATER
+ final_action( final_action && other ) gsl_noexcept
+ : action_( std::move( other.action_ ) )
+ , invoke_( other.invoke_ )
+ {
+ other.invoke_ = false;
+ }
+# endif // ! gsl_CPP17_OR_GREATER
+
+ gsl_SUPPRESS_MSGSL_WARNING(f.6)
+ ~final_action() gsl_noexcept
+ {
+ // Let the optimizer figure out that this check is redundant.
+ if ( invoke_ )
+ {
+ action_();
+ }
+ }
+
+gsl_is_delete_access:
+ final_action( final_action const & ) gsl_is_delete;
+ final_action & operator=( final_action const & ) gsl_is_delete;
+ final_action & operator=( final_action && ) gsl_is_delete;
+
+private:
+ F action_;
+ gsl_MAYBE_UNUSED_MEMBER bool invoke_; // member is defined unconditionally so as not to have ABI depend on C++ language support
+};
+
+template< class F >
+gsl_NODISCARD inline final_action<typename std::decay<F>::type>
+finally( F && action ) gsl_noexcept
+{
+ return final_action<typename std::decay<F>::type>( std::forward<F>( action ) );
+}
+
+# if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+template< class F >
+class final_action_return
+# if gsl_HAVE( OVERRIDE_FINAL )
+final
+# endif
+{
+public:
+ explicit final_action_return( F action ) gsl_noexcept
+ : action_( std::move( action ) )
+ , exception_count_( std17::uncaught_exceptions() )
+ {
+ }
+
+ // We only provide the move constructor if we cannot rely on C++17 guaranteed copy elision.
+# if ! gsl_CPP17_OR_GREATER
+ final_action_return( final_action_return && other ) gsl_noexcept
+ : action_( std::move( other.action_ ) )
+ , exception_count_( other.exception_count_ )
+ {
+ other.exception_count_ = -1; // abuse member as special "no-invoke" marker
+ }
+# endif // ! gsl_CPP17_OR_GREATER
+
+ gsl_SUPPRESS_MSGSL_WARNING(f.6)
+ ~final_action_return() gsl_noexcept
+ {
+ if ( std17::uncaught_exceptions() == exception_count_ ) // always false if `exception_count_ == -1`
+ {
+ action_();
+ }
+ }
+
+gsl_is_delete_access:
+ final_action_return( final_action_return const & ) gsl_is_delete;
+ final_action_return & operator=( final_action_return const & ) gsl_is_delete;
+ final_action_return & operator=( final_action_return && ) gsl_is_delete;
+
+private:
+ F action_;
+ int exception_count_;
+};
+template< class F >
+class final_action_error
+# if gsl_HAVE( OVERRIDE_FINAL )
+final
+# endif
+{
+public:
+ explicit final_action_error( F action ) gsl_noexcept
+ : action_( std::move( action ) )
+ , exception_count_( std17::uncaught_exceptions() )
+ {
+ }
+
+ // We only provide the move constructor if we cannot rely on C++17 guaranteed copy elision.
+# if ! gsl_CPP17_OR_GREATER
+ final_action_error( final_action_error && other ) gsl_noexcept
+ : action_( std::move( other.action_ ) )
+ , exception_count_( other.exception_count_ )
+ {
+ other.exception_count_ = -1; // abuse member as special "no-invoke" marker
+ }
+# endif // ! gsl_CPP17_OR_GREATER
+
+ gsl_SUPPRESS_MSGSL_WARNING(f.6)
+ ~final_action_error() gsl_noexcept
+ {
+ if ( exception_count_ != -1 ) // abuse member as special "no-invoke" marker
+ {
+ if ( std17::uncaught_exceptions() != exception_count_ )
+ {
+ action_();
+ }
+ }
+ }
+
+gsl_is_delete_access:
+ final_action_error( final_action_error const & ) gsl_is_delete;
+ final_action_error & operator=( final_action_error const & ) gsl_is_delete;
+ final_action_error & operator=( final_action_error && ) gsl_is_delete;
+
+private:
+ F action_;
+ int exception_count_;
+};
+
+template< class F >
+gsl_NODISCARD inline final_action_return<typename std::decay<F>::type>
+on_return( F && action ) gsl_noexcept
+{
+ return final_action_return<typename std::decay<F>::type>( std::forward<F>( action ) );
+}
+
+template< class F >
+gsl_NODISCARD inline final_action_error<typename std::decay<F>::type>
+on_error( F && action ) gsl_noexcept
+{
+ return final_action_error<typename std::decay<F>::type>( std::forward<F>( action ) );
+}
+
+# endif // gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+gsl_RESTORE_MSVC_WARNINGS()
+
+#endif // gsl_STDLIB_CPP11_110
+
+#if gsl_STDLIB_CPP11_120
+
+template< class T, class U >
+gsl_NODISCARD gsl_api inline gsl_constexpr T
+narrow_cast( U && u ) gsl_noexcept
+{
+ return static_cast<T>( std::forward<U>( u ) );
+}
+
+#else // ! gsl_STDLIB_CPP11_120
+
+template< class T, class U >
+gsl_api inline T
+narrow_cast( U u ) gsl_noexcept
+{
+ return static_cast<T>( u );
+}
+
+#endif // gsl_STDLIB_CPP11_120
+
+struct narrowing_error : public std::exception
+{
+ char const * what() const gsl_noexcept
+#if gsl_HAVE( OVERRIDE_FINAL )
+ override
+#endif
+ {
+ return "narrowing_error";
+ }
+};
+
+#if gsl_HAVE( TYPE_TRAITS )
+
+namespace detail {
+
+ template< class T, class U >
+ struct is_same_signedness : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value> {};
+
+# if gsl_COMPILER_NVCC_VERSION || gsl_COMPILER_NVHPC_VERSION
+ // We do this to circumvent NVCC warnings about pointless unsigned comparisons with 0.
+ template< class T >
+ gsl_constexpr gsl_api bool is_negative( T value, std::true_type /*isSigned*/ ) gsl_noexcept
+ {
+ return value < T();
+ }
+ template< class T >
+ gsl_constexpr gsl_api bool is_negative( T /*value*/, std::false_type /*isUnsigned*/ ) gsl_noexcept
+ {
+ return false;
+ }
+ template< class T, class U >
+ gsl_constexpr gsl_api bool have_same_sign( T, U, std::true_type /*isSameSignedness*/ ) gsl_noexcept
+ {
+ return true;
+ }
+ template< class T, class U >
+ gsl_constexpr gsl_api bool have_same_sign( T t, U u, std::false_type /*isSameSignedness*/ ) gsl_noexcept
+ {
+ return detail::is_negative( t, std::is_signed<T>() ) == detail::is_negative( u, std::is_signed<U>() );
+ }
+# endif // gsl_COMPILER_NVCC_VERSION || gsl_COMPILER_NVHPC_VERSION
+
+} // namespace detail
+
+#endif
+
+template< class T, class U >
+gsl_NODISCARD gsl_constexpr14
+#if ! gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+gsl_api
+#endif // ! gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+inline
+gsl_ENABLE_IF_R_( std::is_arithmetic<T>::value, T )
+narrow( U u )
+{
+#if ! gsl_HAVE( EXCEPTIONS ) && gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ gsl_STATIC_ASSERT_( detail::dependent_false< T >::value,
+ "According to the GSL specification, narrow<>() throws an exception of type narrowing_error on truncation. Therefore "
+ "it cannot be used if exceptions are disabled. Consider using narrow_failfast<>() instead which raises a precondition "
+ "violation if the given value cannot be represented in the target type." );
+#endif
+
+ T t = static_cast<T>( u );
+
+#if gsl_HAVE( TYPE_TRAITS )
+# if gsl_COMPILER_NVCC_VERSION || gsl_COMPILER_NVHPC_VERSION
+ if ( static_cast<U>( t ) != u
+ || ! detail::have_same_sign( t, u, detail::is_same_signedness<T, U>() ) )
+# else
+ gsl_SUPPRESS_MSVC_WARNING( 4127, "conditional expression is constant" )
+ if ( static_cast<U>( t ) != u
+ || ( ! detail::is_same_signedness<T, U>::value && ( t < T() ) != ( u < U() ) ) )
+# endif
+#else
+ // Don't assume T() works:
+ gsl_SUPPRESS_MSVC_WARNING( 4127, "conditional expression is constant" )
+# if gsl_COMPILER_NVHPC_VERSION
+ // Suppress: pointless comparison of unsigned integer with zero.
+# pragma diag_suppress 186
+# endif
+ if ( static_cast<U>( t ) != u
+ || ( t < 0 ) != ( u < 0 ) )
+# if gsl_COMPILER_NVHPC_VERSION
+ // Restore: pointless comparison of unsigned integer with zero.
+# pragma diag_default 186
+# endif
+
+#endif
+ {
+#if gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ throw narrowing_error();
+#else // ! gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+# if gsl_DEVICE_CODE
+ gsl_TRAP_();
+# else // host code
+ std::terminate();
+# endif
+#endif // gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ }
+
+ return t;
+}
+#if gsl_HAVE( TYPE_TRAITS )
+template< class T, class U >
+gsl_NODISCARD gsl_constexpr14
+# if ! gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+gsl_api
+# endif // ! gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+inline
+gsl_ENABLE_IF_R_( !std::is_arithmetic<T>::value, T )
+narrow( U u )
+{
+# if ! gsl_HAVE( EXCEPTIONS ) && gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ gsl_STATIC_ASSERT_( detail::dependent_false< T >::value,
+ "According to the GSL specification, narrow<>() throws an exception of type narrowing_error on truncation. Therefore "
+ "it cannot be used if exceptions are disabled. Consider using narrow_failfast<>() instead which raises a precondition "
+ "violation if the given value cannot be represented in the target type." );
+# endif
+
+ T t = static_cast<T>( u );
+
+ if ( static_cast<U>( t ) != u )
+ {
+# if gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ throw narrowing_error();
+# else // ! gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+# if gsl_DEVICE_CODE
+ gsl_TRAP_();
+# else // host code
+ std::terminate();
+# endif
+# endif // gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ }
+
+ return t;
+}
+#endif // gsl_HAVE( TYPE_TRAITS )
+
+template< class T, class U >
+gsl_NODISCARD gsl_api gsl_constexpr14 inline
+gsl_ENABLE_IF_R_( std::is_arithmetic<T>::value, T )
+narrow_failfast( U u )
+{
+ T t = static_cast<T>( u );
+
+#if gsl_HAVE( TYPE_TRAITS )
+# if gsl_COMPILER_NVCC_VERSION || gsl_COMPILER_NVHPC_VERSION
+ gsl_Assert( static_cast<U>( t ) == u
+ && ::gsl_lite::detail::have_same_sign( t, u, ::gsl_lite::detail::is_same_signedness<T, U>() ) );
+# else
+ gsl_SUPPRESS_MSVC_WARNING( 4127, "conditional expression is constant" )
+ gsl_Assert( static_cast<U>( t ) == u
+ && ( ::gsl_lite::detail::is_same_signedness<T, U>::value || ( t < T() ) == ( u < U() ) ) );
+# endif
+#else
+ // Don't assume T() works:
+ gsl_SUPPRESS_MSVC_WARNING( 4127, "conditional expression is constant" )
+# if gsl_COMPILER_NVHPC_VERSION
+ // Suppress: pointless comparison of unsigned integer with zero.
+# pragma diag_suppress 186
+# endif
+ gsl_Assert( static_cast<U>( t ) == u
+ && ( t < 0 ) == ( u < 0 ) );
+# if gsl_COMPILER_NVHPC_VERSION
+ // Restore: pointless comparison of unsigned integer with zero.
+# pragma diag_default 186
+# endif
+#endif
+
+ return t;
+}
+#if gsl_HAVE( TYPE_TRAITS )
+template< class T, class U >
+gsl_NODISCARD gsl_api gsl_constexpr14 inline
+gsl_ENABLE_IF_R_( !std::is_arithmetic<T>::value, T )
+narrow_failfast( U u )
+{
+ T t = static_cast<T>( u );
+ gsl_Assert( static_cast<U>( t ) == u );
+ return t;
+}
+#endif // gsl_HAVE( TYPE_TRAITS )
+
+
+//
+// at() - Bounds-checked way of accessing static arrays, std::array, std::vector.
+//
+
+template< class T, size_t N >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 T &
+at( T(&arr)[N], size_t pos )
+{
+ gsl_Expects( pos < N );
+ return arr[pos];
+}
+
+template< class Container >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 typename Container::value_type &
+at( Container & cont, size_t pos )
+{
+ gsl_Expects( pos < cont.size() );
+ return cont[pos];
+}
+
+template< class Container >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 typename Container::value_type const &
+at( Container const & cont, size_t pos )
+{
+ gsl_Expects( pos < cont.size() );
+ return cont[pos];
+}
+
+#if gsl_HAVE( INITIALIZER_LIST )
+template< class T >
+gsl_NODISCARD gsl_api inline const gsl_constexpr14 T
+at( std::initializer_list<T> cont, size_t pos )
+{
+ gsl_Expects( pos < cont.size() );
+ return *( cont.begin() + pos );
+}
+#endif
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 T &
+at( span<T, Extent> s, size_t pos )
+{
+ return s[ pos ];
+}
+
+//
+// GSL.views: views
+//
+
+//
+// not_null<> - Wrap any indirection and enforce non-null.
+//
+
+template< class T >
+class not_null;
+
+namespace detail {
+
+template< class T > struct is_void : std11::false_type { };
+template< > struct is_void< void > : std11::true_type { };
+
+// helper class to figure out whether a pointer has an element type
+#if gsl_STDLIB_CPP11_OR_GREATER && gsl_HAVE( EXPRESSION_SFINAE )
+// Avoid SFINAE for unary `operator*` (doesn't work for `std::unique_ptr<>` and the like) if an `element_type` member exists.
+template< class T, class E = void >
+struct has_element_type_ : std11::false_type { };
+template< class T >
+struct has_element_type_< T, std17::void_t< decltype( *std::declval<T>() ) > > : std11::true_type { };
+template< class T, class E = void >
+struct has_element_type : has_element_type_< T > { };
+template< class T >
+struct has_element_type< T, std17::void_t< typename T::element_type > > : std11::true_type { };
+# else // a.k.a. ! ( gsl_STDLIB_CPP11_OR_GREATER && gsl_HAVE( EXPRESSION_SFINAE ) )
+// Without C++11 and expression SFINAE, just assume that non-pointer types (e.g. smart pointers) have an `element_type` member
+template< class T, class E = void >
+struct has_element_type : std11::true_type { };
+# endif // gsl_STDLIB_CPP11_OR_GREATER && gsl_HAVE( EXPRESSION_SFINAE )
+
+// helper class to figure out the pointed-to type of a pointer
+#if gsl_STDLIB_CPP11_OR_GREATER
+template< class T, class E = void >
+struct element_type_helper
+{
+ // For types without a member element_type (this could handle typed raw pointers but not `void*`)
+ typedef typename std::remove_reference< decltype( *std::declval<T>() ) >::type type;
+};
+template< class T >
+struct element_type_helper< T, std17::void_t< typename T::element_type > >
+{
+ // For types with a member element_type
+ typedef typename T::element_type type;
+};
+#else // ! gsl_STDLIB_CPP11_OR_GREATER
+// Pre-C++11, we cannot have `decltype`, so we cannot handle non-pointer types without a member `element_type`
+template< class T, class E = void >
+struct element_type_helper
+{
+ typedef typename T::element_type type;
+};
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+template< class T >
+struct element_type_helper< T * >
+{
+ typedef T type;
+};
+
+template< class T >
+struct is_not_null_or_bool_oracle : std11::false_type { };
+template< class T >
+struct is_not_null_or_bool_oracle< not_null<T> > : std11::true_type { };
+template<>
+struct is_not_null_or_bool_oracle< bool > : std11::true_type { };
+
+
+template< class T, bool IsCopyable >
+struct not_null_data;
+#if gsl_HAVE( MOVE_FORWARD )
+template< class T >
+struct not_null_data< T, false >
+{
+ T ptr_;
+
+ gsl_api gsl_constexpr14 not_null_data( T && _ptr ) gsl_noexcept
+ : ptr_( std::move( _ptr ) )
+ {
+ }
+
+ gsl_api gsl_constexpr14 not_null_data( not_null_data && other )
+ gsl_noexcept_not_testing // we want to be nothrow-movable despite the assertion
+ : ptr_( std::move( other.ptr_ ) )
+ {
+ gsl_Assert( ptr_ != gsl_nullptr );
+ }
+ gsl_api gsl_constexpr14 not_null_data & operator=( not_null_data && other )
+ gsl_noexcept_not_testing // we want to be nothrow-movable despite the assertion
+ {
+ gsl_Assert( other.ptr_ != gsl_nullptr || &other == this );
+ ptr_ = std::move( other.ptr_ );
+ return *this;
+ }
+
+gsl_is_delete_access:
+ not_null_data( not_null_data const & ) gsl_is_delete;
+ not_null_data & operator=( not_null_data const & ) gsl_is_delete;
+};
+#endif // gsl_HAVE( MOVE_FORWARD )
+template< class T >
+struct not_null_data< T, true >
+{
+ T ptr_;
+
+ gsl_api gsl_constexpr14 not_null_data( T const & _ptr ) gsl_noexcept
+ : ptr_( _ptr )
+ {
+ }
+
+#if gsl_HAVE( MOVE_FORWARD )
+ gsl_api gsl_constexpr14 not_null_data( T && _ptr ) gsl_noexcept
+ : ptr_( std::move( _ptr ) )
+ {
+ }
+
+ gsl_api gsl_constexpr14 not_null_data( not_null_data && other )
+ gsl_noexcept_not_testing // we want to be nothrow-movable despite the assertion
+ : ptr_( std::move( other.ptr_ ) )
+ {
+ gsl_Assert( ptr_ != gsl_nullptr );
+ }
+ gsl_api gsl_constexpr14 not_null_data & operator=( not_null_data && other )
+ gsl_noexcept_not_testing // we want to be nothrow-movable despite the assertion
+ {
+ gsl_Assert( other.ptr_ != gsl_nullptr || &other == this );
+ ptr_ = std::move( other.ptr_ );
+ return *this;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+ gsl_api gsl_constexpr14 not_null_data( not_null_data const & other )
+ : ptr_( other.ptr_ )
+ {
+ gsl_Assert( ptr_ != gsl_nullptr );
+ }
+ gsl_api gsl_constexpr14 not_null_data & operator=( not_null_data const & other )
+ {
+ gsl_Assert( other.ptr_ != gsl_nullptr );
+ ptr_ = other.ptr_;
+ return *this;
+ }
+};
+template< class T >
+struct not_null_data< T *, true >
+{
+ T * ptr_;
+
+ gsl_api gsl_constexpr14 not_null_data( T * _ptr ) gsl_noexcept
+ : ptr_( _ptr )
+ {
+ }
+};
+
+template< class T >
+struct is_copyable
+#if gsl_HAVE( TYPE_TRAITS )
+: std::integral_constant< bool, std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value >
+#else
+: std11::true_type
+#endif
+{
+};
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( UNIQUE_PTR ) && gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+// Type traits are buggy in VC++ 2013, so we explicitly declare `unique_ptr<>` non-copyable.
+template< class T, class Deleter >
+struct is_copyable< std::unique_ptr< T, Deleter > > : std11::false_type
+{
+};
+#endif
+
+template< class T >
+struct not_null_accessor;
+
+template< class Derived, class T, bool HasElementType >
+struct not_null_elem
+{
+ typedef typename element_type_helper<T>::type element_type;
+
+#if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ gsl_NODISCARD gsl_api gsl_constexpr14 element_type *
+ get() const
+ {
+ return not_null_accessor<T>::get_checked( static_cast< Derived const & >( *this ) ).get();
+ }
+#endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+};
+template< class Derived, class T >
+struct not_null_elem< Derived, T, false >
+{
+};
+template< class Derived, class T, bool IsDereferencable >
+struct gsl_EMPTY_BASES_ not_null_deref
+ : not_null_elem< Derived, T, detail::has_element_type< T >::value >
+{
+ gsl_NODISCARD gsl_api gsl_constexpr14 typename element_type_helper<T>::type &
+ operator*() const
+ {
+ return *not_null_accessor<T>::get_checked( static_cast< Derived const & >( *this ) );
+ }
+};
+template< class Derived, class T >
+struct gsl_EMPTY_BASES_ not_null_deref< Derived, T, false > // e.g. `void*`, `std::function<>`
+ : not_null_elem< Derived, T, detail::has_element_type< T >::value >
+{
+};
+
+template< class T > struct is_void_ptr : is_void< typename detail::element_type_helper< T >::type > { };
+
+template< class T > struct is_dereferencable : std17::conjunction< has_element_type< T >, std17::negation< is_void_ptr< T > > > { };
+
+} // namespace detail
+
+#if gsl_HAVE( TYPE_TRAITS )
+template< class T > struct is_nullable : std::is_assignable< typename std::remove_cv< T >::type &, std::nullptr_t > { };
+
+# if gsl_CPP14_OR_GREATER
+template< class T > constexpr bool is_nullable_v = is_nullable< T >::value;
+# endif // gsl_CPP14_OR_GREATER
+
+#endif // gsl_HAVE( TYPE_TRAITS )
+
+template< class T >
+class
+gsl_EMPTY_BASES_ // not strictly needed, but will become necessary if we add more base classes
+not_null : public detail::not_null_deref< not_null< T >, T, detail::is_dereferencable< T >::value >
+{
+private:
+ detail::not_null_data< T, detail::is_copyable< T >::value > data_;
+
+ // need to access `not_null<U>::data_`
+ template< class U >
+ friend struct detail::not_null_accessor;
+
+ typedef detail::not_null_accessor<T> accessor;
+
+public:
+#if gsl_HAVE( TYPE_TRAITS )
+ static_assert( ! std::is_reference<T>::value, "T may not be a reference type" );
+ static_assert( ! std::is_const<T>::value && ! std::is_volatile<T>::value, "T may not be cv-qualified" );
+ static_assert( is_nullable<T>::value, "T must be a nullable type" );
+#endif
+
+#if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+# if gsl_HAVE( MOVE_FORWARD )
+ template< class U
+ // In Clang 3.x, `is_constructible<not_null<unique_ptr<X>>, unique_ptr<X>>` tries to instantiate the copy constructor of `unique_ptr<>`, triggering an error.
+ // Note that Apple Clang's `__clang_major__` etc. are different from regular Clang.
+# if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_constructible<T, U>::value && is_nullable<U>::value ))
+# endif
+ >
+ gsl_api gsl_constexpr14 explicit not_null( U other )
+ : data_( T( std::move( other ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ // Define the non-explicit constructors for non-nullable arguments only if the explicit constructor has a SFINAE constraint.
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_constructible<T, U>::value && std::is_function<U>::value ))
+ >
+ gsl_api gsl_constexpr14 /*implicit*/ not_null( U const & other )
+ : data_( T( other ) )
+ {
+ }
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_constructible<T, U>::value && ! std::is_function<U>::value && ! is_nullable<U>::value ))
+ >
+ gsl_api gsl_constexpr14 /*implicit*/ not_null( U other )
+ : data_( T( std::move( other ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+# else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+ template< class U >
+ gsl_api gsl_constexpr14 explicit not_null( U const & other )
+ : data_( T( other ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# endif // gsl_HAVE( MOVE_FORWARD )
+#else // a.k.a. !gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+# if gsl_HAVE( MOVE_FORWARD )
+ // In Clang 3.x, `is_constructible<not_null<unique_ptr<X>>, unique_ptr<X>>` tries to instantiate the copy constructor of `unique_ptr<>`, triggering an error.
+ // Note that Apple Clang's `__clang_major__` etc. are different from regular Clang.
+# if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_constructible<T, U>::value && !std::is_convertible<U, T>::value ))
+ >
+ gsl_api gsl_constexpr14 explicit not_null( U other )
+ : data_( T( std::move( other ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_convertible<U, T>::value ))
+ >
+ gsl_api gsl_constexpr14 not_null( U other )
+ : data_( std::move( other ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# else // a.k.a. !( gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ // If type_traits are not available, then we can't distinguish `is_convertible<>` and `is_constructible<>`, so we unconditionally permit implicit construction.
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( U other )
+ : data_( T( std::move( other ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+# else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( U const & other )
+ : data_( T( other ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# endif // gsl_HAVE( MOVE_FORWARD )
+#endif // gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+
+#if gsl_HAVE( MOVE_FORWARD )
+ // In Clang 3.x, `is_constructible<not_null<unique_ptr<X>>, unique_ptr<X>>` tries to instantiate the copy constructor of `unique_ptr<>`, triggering an error.
+ // Note that Apple Clang's `__clang_major__` etc. are different from regular Clang.
+# if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_constructible<T, U>::value && !std::is_convertible<U, T>::value ))
+ >
+ gsl_api gsl_constexpr14 explicit not_null( not_null<U> other )
+ : data_( T( detail::not_null_accessor<U>::get_checked( std::move( other ) ) ) )
+ {
+ }
+
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_convertible<U, T>::value ))
+ >
+ gsl_api gsl_constexpr14 not_null( not_null<U> other )
+ : data_( T( detail::not_null_accessor<U>::get_checked( std::move( other ) ) ) )
+ {
+ }
+# else // a.k.a. ! ( gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ // If type_traits are not available, then we can't distinguish `is_convertible<>` and `is_constructible<>`, so we unconditionally permit implicit construction.
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( not_null<U> other )
+ : data_( T( detail::not_null_accessor<U>::get_checked( std::move( other ) ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+ template< class U >
+ gsl_api gsl_constexpr14 not_null<T>& operator=( not_null<U> other )
+ {
+ data_.ptr_ = detail::not_null_accessor<U>::get_checked( std::move( other ) );
+ return *this;
+ }
+# endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+#else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( not_null<U> const & other )
+ : data_( T( detail::not_null_accessor<U>::get_checked( other ) ) )
+ {
+ }
+ template< class U >
+ gsl_api gsl_constexpr14 not_null<T>& operator=( not_null<U> const & other )
+ {
+ data_.ptr_ = detail::not_null_accessor<U>::get_checked( other );
+ return *this;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+#if ! gsl_CONFIG( TRANSPARENT_NOT_NULL )
+# if gsl_CONFIG( NOT_NULL_GET_BY_CONST_REF )
+ gsl_NODISCARD gsl_api gsl_constexpr14 T const &
+ get() const
+ {
+ return accessor::get_checked( *this );
+ }
+# else // a.k.a. ! gsl_CONFIG( NOT_NULL_GET_BY_CONST_REF )
+ gsl_NODISCARD gsl_api gsl_constexpr14 T
+ get() const
+ {
+ return accessor::get_checked( *this );
+ }
+# endif // gsl_CONFIG( NOT_NULL_GET_BY_CONST_REF )
+#endif // ! gsl_CONFIG( TRANSPARENT_NOT_NULL )
+
+ // We want an implicit conversion operator that can be used to convert from both lvalues (by
+ // const reference or by copy) and rvalues (by move). So it seems like we could define
+ //
+ // template< class U >
+ // operator U const &() const & { ... }
+ // template< class U >
+ // operator U &&() && { ... }
+ //
+ // However, having two conversion operators with different return types renders the assignment
+ // operator of the result type ambiguous:
+ //
+ // not_null<std::unique_ptr<T>> p( ... );
+ // std::unique_ptr<U> q;
+ // q = std::move( p ); // ambiguous
+ //
+ // To avoid this ambiguity, we have both overloads of the conversion operator return `U`
+ // rather than `U const &` or `U &&`. This implies that converting an lvalue always induces
+ // a copy, which can cause unnecessary copies or even fail to compile in some situations:
+ //
+ // not_null<std::shared_ptr<T>> sp( ... );
+ // std::shared_ptr<U> const & rs = sp; // unnecessary copy
+ // std::unique_ptr<U> const & ru = p; // error: cannot copy `unique_ptr<T>`
+ //
+ // However, these situations are rather unusual, and the following, more frequent situations
+ // remain unimpaired:
+ //
+ // std::shared_ptr<U> vs = sp; // no extra copy
+ // std::unique_ptr<U> vu = std::move( p );
+
+#if gsl_HAVE( MOVE_FORWARD ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT )
+ // explicit conversion operator
+
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_constructible<U, T const &>::value && !std::is_convertible<T, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ))
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14 explicit
+ operator U() const
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ &
+# endif
+ {
+ return U( accessor::get_checked( *this ) );
+ }
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_constructible<U, T>::value && !std::is_convertible<T, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ))
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14 explicit
+ operator U() &&
+ {
+ return U( accessor::get_checked( std::move( *this ) ) );
+ }
+# endif
+
+ // implicit conversion operator
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_constructible<U, T const &>::value && std::is_convertible<T, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ))
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ operator U() const
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ &
+# endif
+ {
+ return accessor::get_checked( *this );
+ }
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( std::is_convertible<T, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ))
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ operator U() &&
+ {
+ return accessor::get_checked( std::move( *this ) );
+ }
+# endif
+#else // a.k.a. #if !( gsl_HAVE( MOVE_FORWARD ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT ) )
+ template< class U >
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ operator U() const
+ {
+ return U( accessor::get_checked( *this ) );
+ }
+#endif // gsl_HAVE( MOVE_FORWARD ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT )
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 T const &
+ operator->() const
+ {
+ return accessor::get_checked( *this );
+ }
+
+#if gsl_HAVE( MOVE_FORWARD )
+ // Visual C++ 2013 doesn't generate default move constructors, so we declare them explicitly.
+ gsl_api gsl_constexpr14 not_null( not_null && other )
+ gsl_noexcept_not_testing // we want to be nothrow-movable despite the assertion
+ : data_( std::move( other.data_ ) )
+ {
+ }
+ gsl_api gsl_constexpr14 not_null & operator=( not_null && other )
+ gsl_noexcept_not_testing // we want to be nothrow-movable despite the assertion
+ {
+ data_ = std::move( other.data_ );
+ return *this;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr14 not_null( not_null const & ) = default;
+ gsl_constexpr14 not_null & operator=( not_null const & ) = default;
+#endif
+
+ gsl_api gsl_constexpr20 friend void swap( not_null & lhs, not_null & rhs )
+ gsl_noexcept_not_testing // we want to be nothrow-swappable despite the precondition check
+ {
+ accessor::check( lhs );
+ accessor::check( rhs );
+ using std::swap;
+ swap( lhs.data_.ptr_, rhs.data_.ptr_ );
+ }
+
+gsl_is_delete_access:
+ not_null() gsl_is_delete;
+ // prevent compilation when initialized with a nullptr or literal 0:
+#if gsl_HAVE( NULLPTR )
+ not_null( std::nullptr_t ) gsl_is_delete;
+ not_null & operator=( std::nullptr_t ) gsl_is_delete;
+#else
+ not_null( int ) gsl_is_delete;
+ not_null & operator=( int ) gsl_is_delete;
+#endif
+
+#if gsl_STDLIB_CPP11_140 && ( gsl_CPP14_OR_GREATER || ! gsl_COMPILER_NVCC_VERSION )
+ template< class... Ts >
+ gsl_api gsl_constexpr14 auto
+ operator()( Ts&&... args ) const
+# if ! gsl_COMPILER_NVCC_VERSION
+ // NVCC thinks that Substitution Failure Is An Error here
+ -> decltype( data_.ptr_( std::forward<Ts>( args )... ) )
+# endif // ! gsl_COMPILER_NVCC_VERSION
+ {
+ return accessor::get_checked( *this )( std::forward<Ts>( args )... );
+ }
+#endif // gsl_STDLIB_CPP11_140 && ( gsl_CPP14_OR_GREATER || ! gsl_COMPILER_NVCC_VERSION )
+
+ // unwanted operators...pointers only point to single objects!
+ not_null & operator++() gsl_is_delete;
+ not_null & operator--() gsl_is_delete;
+ not_null operator++( int ) gsl_is_delete;
+ not_null operator--( int ) gsl_is_delete;
+ not_null & operator+ ( size_t ) gsl_is_delete;
+ not_null & operator+=( size_t ) gsl_is_delete;
+ not_null & operator- ( size_t ) gsl_is_delete;
+ not_null & operator-=( size_t ) gsl_is_delete;
+ not_null & operator+=( std::ptrdiff_t ) gsl_is_delete;
+ not_null & operator-=( std::ptrdiff_t ) gsl_is_delete;
+ void operator[]( std::ptrdiff_t ) const gsl_is_delete;
+};
+#if gsl_HAVE( DEDUCTION_GUIDES )
+template< class U >
+not_null( U ) -> not_null<U>;
+template< class U >
+not_null( not_null<U> ) -> not_null<U>;
+#endif
+
+#if gsl_HAVE( NULLPTR )
+void make_not_null( std::nullptr_t ) gsl_is_delete;
+#endif // gsl_HAVE( NULLPTR )
+#if gsl_HAVE( MOVE_FORWARD )
+template< class U >
+gsl_NODISCARD gsl_api gsl_constexpr14 not_null<U>
+make_not_null( U u )
+{
+ return not_null<U>( std::move( u ) );
+}
+template< class U >
+gsl_NODISCARD gsl_api gsl_constexpr14 not_null<U>
+make_not_null( not_null<U> u )
+{
+ return std::move( u );
+}
+#else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+template< class U >
+gsl_NODISCARD gsl_api not_null<U>
+make_not_null( U const & u )
+{
+ return not_null<U>( u );
+}
+template< class U >
+gsl_NODISCARD gsl_api not_null<U>
+make_not_null( not_null<U> const & u )
+{
+ return u;
+}
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+namespace detail {
+
+template< class T >
+struct as_nullable_helper
+{
+ typedef T type;
+};
+template< class T >
+struct as_nullable_helper< not_null<T> >
+{
+};
+
+template< class T >
+struct not_null_accessor
+{
+#if gsl_HAVE( MOVE_FORWARD )
+ static gsl_api T get( not_null<T>&& p ) gsl_noexcept
+ {
+ return std::move( p.data_.ptr_ );
+ }
+ static gsl_api T get_checked( not_null<T>&& p )
+ {
+ gsl_Assert( p.data_.ptr_ != gsl_nullptr );
+ return std::move( p.data_.ptr_ );
+ }
+#endif
+ static gsl_api T const & get( not_null<T> const & p ) gsl_noexcept
+ {
+ return p.data_.ptr_;
+ }
+ static gsl_api bool is_valid( not_null<T> const & p ) gsl_noexcept
+ {
+ return p.data_.ptr_ != gsl_nullptr;
+ }
+ static gsl_api void check( not_null<T> const & p )
+ {
+ gsl_Assert( p.data_.ptr_ != gsl_nullptr );
+ }
+ static gsl_api T const & get_checked( not_null<T> const & p )
+ {
+ gsl_Assert( p.data_.ptr_ != gsl_nullptr );
+ return p.data_.ptr_;
+ }
+};
+template< class T >
+struct not_null_accessor< T * >
+{
+ static gsl_api T * const & get( not_null< T * > const & p ) gsl_noexcept
+ {
+ return p.data_.ptr_;
+ }
+ static gsl_api bool is_valid( not_null< T * > const & /*p*/ ) gsl_noexcept
+ {
+ return true;
+ }
+ static gsl_api void check( not_null< T * > const & /*p*/ )
+ {
+ }
+ static gsl_api T * const & get_checked( not_null< T * > const & p ) gsl_noexcept
+ {
+ return p.data_.ptr_;
+ }
+};
+
+namespace no_adl {
+
+#if gsl_HAVE( MOVE_FORWARD )
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr auto as_nullable( T && p )
+gsl_noexcept_if( std::is_nothrow_move_constructible<T>::value )
+-> typename detail::as_nullable_helper<typename std20::remove_cvref<T>::type>::type
+{
+ return std::move( p );
+}
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr14 T as_nullable( not_null<T> && p )
+{
+ return detail::not_null_accessor<T>::get_checked( std::move( p ) );
+}
+#else // ! gsl_HAVE( MOVE_FORWARD )
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr T const & as_nullable( T const & p ) gsl_noexcept
+{
+ return p;
+}
+#endif // gsl_HAVE( MOVE_FORWARD )
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr14 T const &
+as_nullable( not_null<T> const & p )
+{
+ return detail::not_null_accessor<T>::get_checked( p );
+}
+
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr bool
+is_valid( not_null<T> const & p )
+{
+ return detail::not_null_accessor<T>::is_valid( p );
+}
+
+} // namespace no_adl
+} // namespace detail
+
+using namespace detail::no_adl;
+
+// not_null with implicit constructor, allowing copy-initialization:
+
+template< class T >
+class not_null_ic : public not_null<T>
+{
+public:
+ template< class U
+ gsl_ENABLE_IF_(( std::is_constructible<T, U>::value ))
+ >
+ gsl_api gsl_constexpr14
+#if gsl_HAVE( MOVE_FORWARD )
+ not_null_ic( U u )
+ : not_null<T>( std::move( u ) )
+#else // ! gsl_HAVE( MOVE_FORWARD )
+ not_null_ic( U const & u )
+ : not_null<T>( u )
+#endif // gsl_HAVE( MOVE_FORWARD )
+ {}
+};
+
+// more not_null unwanted operators
+
+template< class T, class U >
+std::ptrdiff_t operator-( not_null<T> const &, not_null<U> const & ) gsl_is_delete;
+
+template< class T >
+not_null<T> operator-( not_null<T> const &, std::ptrdiff_t ) gsl_is_delete;
+
+template< class T >
+not_null<T> operator+( not_null<T> const &, std::ptrdiff_t ) gsl_is_delete;
+
+template< class T >
+not_null<T> operator+( std::ptrdiff_t, not_null<T> const & ) gsl_is_delete;
+
+// not_null comparisons
+
+#if gsl_HAVE( NULLPTR ) && gsl_HAVE( IS_DELETE )
+template< class T >
+gsl_constexpr bool
+operator==( not_null<T> const &, std::nullptr_t ) = delete;
+template< class T >
+gsl_constexpr bool
+operator==( std::nullptr_t , not_null<T> const & ) = delete;
+template< class T >
+gsl_constexpr bool
+operator!=( not_null<T> const &, std::nullptr_t ) = delete;
+template< class T >
+gsl_constexpr bool
+operator!=( std::nullptr_t , not_null<T> const & ) = delete;
+#endif // gsl_HAVE( NULLPTR ) && gsl_HAVE( IS_DELETE )
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator==( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( l.operator->() == r.operator->() )
+{
+ return l.operator->() == r.operator->();
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator==( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_(l.operator->() == r )
+{
+ return l.operator->() == r;
+}
+#if ! gsl_CPP20_OR_GREATER
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator==( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( l == r.operator->() )
+{
+ return l == r.operator->();
+}
+#endif // ! gsl_CPP20_OR_GREATER
+
+// The C++ Core Guidelines discourage the use of pointer arithmetic, and gsl-lite consequently refrains from defining operators
+// for pointer arithmetic or the subscript operator in `not_null<>`. However, comparison of `not_null<>` objects is supported;
+// although the standard does not mandate a certain ordering for objects with two exceptions (objects from the same array;
+// data members of the same class, as required for `offsetof()`), it does require that `operator<` establishes a total ordering
+// of pointers, as implied by https://eel.is/c++draft/expr.rel#5. Among other things, this guarantees that a list of pointers
+// can be sorted and searched, or that pointers can be used as a key in a relational container such as `std::map<>`.
+// Therefore, we also define relational comparison operators for `not_null<>`.
+
+#if gsl_STDLIB_CPP20_OR_GREATER
+template< class T, class U >
+[[nodiscard]] inline gsl_api constexpr auto
+operator<=>( not_null<T> const & l, not_null<U> const & r )
+-> decltype( l.operator->() <=> r.operator->() )
+{
+ return l.operator->() <=> r.operator->();
+}
+template< class T, class U >
+[[nodiscard]] inline gsl_api constexpr auto
+operator<=>( not_null<T> const & l, U const & r )
+-> decltype( l.operator->() <=> r )
+{
+ return l.operator->() <=> r;
+}
+#endif // gsl_STDLIB_CPP20_OR_GREATER
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( l.operator->() < r.operator->() )
+{
+ return l.operator->() < r.operator->();
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( l.operator->() < r )
+{
+ return l.operator->() < r;
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( l < r.operator->() )
+{
+ return l < r.operator->();
+}
+
+#if ! gsl_CPP20_OR_GREATER
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator!=( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( l == r ) )
+{
+ return !( l == r );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator!=( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( !( l == r ) )
+{
+ return !( l == r );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator!=( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( l == r ) )
+{
+ return !( l == r );
+}
+#endif // ! gsl_CPP20_OR_GREATER
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<=( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( r < l ) )
+{
+ return !( r < l );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<=( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( !( r < l ) )
+{
+ return !( r < l );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<=( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( r < l ) )
+{
+ return !( r < l );
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( r < l )
+{
+ return r < l;
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( r < l )
+{
+ return r < l;
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( r < l )
+{
+ return r < l;
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>=( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( l < r ) )
+{
+ return !( l < r );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>=( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( !( l < r ) )
+{
+ return !( l < r );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>=( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( l < r ) )
+{
+ return !( l < r );
+}
+
+// print not_null
+
+template< class CharType, class Traits, class T >
+std::basic_ostream< CharType, Traits > & operator<<( std::basic_ostream< CharType, Traits > & os, not_null<T> const & p )
+{
+ return os << p.operator->();
+}
+
+
+#if gsl_HAVE( VARIADIC_TEMPLATE )
+# if gsl_HAVE( UNIQUE_PTR )
+template< class T, class... Args >
+gsl_NODISCARD not_null<std::unique_ptr<T>>
+make_unique( Args &&... args )
+{
+# if gsl_HAVE( TYPE_TRAITS )
+ static_assert( !std::is_array<T>::value, "gsl_lite::make_unique<T>() returns `gsl_lite::not_null<std::unique_ptr<T>>`, which is not "
+ "defined for array types because the Core Guidelines advise against pointer arithmetic, cf. \"Bounds safety profile\"." );
+# endif
+ return not_null<std::unique_ptr<T>>( new T( std::forward<Args>( args )... ) );
+}
+# endif // gsl_HAVE( UNIQUE_PTR )
+# if gsl_HAVE( SHARED_PTR )
+template< class T, class... Args >
+gsl_NODISCARD not_null<std::shared_ptr<T>>
+make_shared( Args &&... args )
+{
+# if gsl_HAVE( TYPE_TRAITS )
+ static_assert( !std::is_array<T>::value, "gsl_lite::make_shared<T>() returns `gsl_lite::not_null<std::shared_ptr<T>>`, which is not "
+ "defined for array types because the Core Guidelines advise against pointer arithmetic, cf. \"Bounds safety profile\"." );
+# endif
+ return not_null<std::shared_ptr<T>>( std::make_shared<T>( std::forward<Args>( args )... ) );
+}
+# endif // gsl_HAVE( SHARED_PTR )
+#endif // gsl_HAVE( VARIADIC_TEMPLATE )
+
+
+#if gsl_FEATURE( BYTE )
+//
+// Byte-specific type.
+//
+# if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ enum class gsl_may_alias byte : unsigned char {};
+# else
+# if ! defined( gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI )
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: in pre-C++11 mode, byte is defined as a struct rather than an enum, which changes the ABI of gsl-lite and may lead to ODR violations and undefined behavior; define the macro gsl_CONFIG_ACKNOWLEDGE_NONSTANDARD_ABI to explicitly acknowledge that you are using gsl-lite with a non-standard ABI and that you control the build flags of all components linked into your target")
+# endif
+ struct gsl_may_alias byte { typedef unsigned char type; type v; };
+# endif
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr byte
+to_byte( T v ) gsl_noexcept
+{
+# if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ return static_cast<byte>( v );
+# elif gsl_HAVE( CONSTEXPR_11 )
+ return { static_cast<typename byte::type>( v ) };
+# else
+ byte b = { static_cast<typename byte::type>( v ) }; return b;
+# endif
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_NODISCARD gsl_api inline gsl_constexpr IntegerType
+to_integer( byte b ) gsl_noexcept
+{
+# if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ return static_cast<typename std::underlying_type<byte>::type>( b );
+# else
+ return b.v;
+# endif
+}
+
+gsl_NODISCARD gsl_api inline gsl_constexpr unsigned char
+to_uchar( byte b ) gsl_noexcept
+{
+ return to_integer<unsigned char>( b );
+}
+
+gsl_NODISCARD gsl_api inline gsl_constexpr unsigned char
+to_uchar( int i ) gsl_noexcept
+{
+ return static_cast<unsigned char>( i );
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_api inline gsl_constexpr14 byte &
+operator<<=( byte & b, IntegerType shift ) gsl_noexcept
+{
+# if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ return b = ::gsl_lite::to_byte( ::gsl_lite::to_uchar( b ) << shift );
+# else
+ b.v = ::gsl_lite::to_uchar( b.v << shift ); return b;
+# endif
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_NODISCARD gsl_api inline gsl_constexpr byte
+operator<<( byte b, IntegerType shift ) gsl_noexcept
+{
+ return ::gsl_lite::to_byte( ::gsl_lite::to_uchar( b ) << shift );
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 byte &
+operator>>=( byte & b, IntegerType shift ) gsl_noexcept
+{
+# if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ return b = ::gsl_lite::to_byte( ::gsl_lite::to_uchar( b ) >> shift );
+# else
+ b.v = ::gsl_lite::to_uchar( b.v >> shift ); return b;
+# endif
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_NODISCARD gsl_api inline gsl_constexpr byte
+operator>>( byte b, IntegerType shift ) gsl_noexcept
+{
+ return ::gsl_lite::to_byte( ::gsl_lite::to_uchar( b ) >> shift );
+}
+
+# if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+gsl_DEFINE_ENUM_BITMASK_OPERATORS( byte )
+gsl_DEFINE_ENUM_RELATIONAL_OPERATORS( byte )
+# else // a.k.a. !gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+gsl_api inline gsl_constexpr bool operator==( byte l, byte r ) gsl_noexcept
+{
+ return l.v == r.v;
+}
+
+gsl_api inline gsl_constexpr bool operator!=( byte l, byte r ) gsl_noexcept
+{
+ return !( l == r );
+}
+
+gsl_api inline gsl_constexpr bool operator< ( byte l, byte r ) gsl_noexcept
+{
+ return l.v < r.v;
+}
+
+gsl_api inline gsl_constexpr bool operator<=( byte l, byte r ) gsl_noexcept
+{
+ return !( r < l );
+}
+
+gsl_api inline gsl_constexpr bool operator> ( byte l, byte r ) gsl_noexcept
+{
+ return ( r < l );
+}
+
+gsl_api inline gsl_constexpr bool operator>=( byte l, byte r ) gsl_noexcept
+{
+ return !( l < r );
+}
+
+gsl_api inline gsl_constexpr14 byte & operator|=( byte & l, byte r ) gsl_noexcept
+{
+ l.v |= r.v; return l;
+}
+
+gsl_api inline gsl_constexpr byte operator|( byte l, byte r ) gsl_noexcept
+{
+ return ::gsl_lite::to_byte( l.v | r.v );
+}
+
+gsl_api inline gsl_constexpr14 byte & operator&=( byte & l, byte r ) gsl_noexcept
+{
+ l.v &= r.v; return l;
+}
+
+gsl_api inline gsl_constexpr byte operator&( byte l, byte r ) gsl_noexcept
+{
+ return ::gsl_lite::to_byte( l.v & r.v );
+}
+
+gsl_api inline gsl_constexpr14 byte & operator^=( byte & l, byte r ) gsl_noexcept
+{
+ l.v ^= r.v; return l;
+}
+
+gsl_api inline gsl_constexpr byte operator^( byte l, byte r ) gsl_noexcept
+{
+ return ::gsl_lite::to_byte( l.v ^ r.v );
+}
+
+gsl_api inline gsl_constexpr byte operator~( byte b ) gsl_noexcept
+{
+ return ::gsl_lite::to_byte( ~b.v );
+}
+# endif // gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+#endif // gsl_FEATURE( BYTE )
+
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+
+// Tag to select span constructor taking a container:
+
+struct with_container_t { gsl_constexpr with_container_t( ) gsl_noexcept { } };
+const gsl_constexpr with_container_t with_container; // TODO: this can lead to ODR violations because the symbol will be defined in multiple translation units
+
+#endif
+
+
+// The span<> and span_iterator<> implementation below was mostly borrowed from Microsoft GSL.
+
+
+#if gsl_COMPILER_MSVC_VER
+# pragma warning( push )
+
+// turn off some warnings that are noisy about our Expects statements
+# pragma warning( disable : 4127 ) // conditional expression is constant
+# pragma warning( disable : 4146 ) // unary minus operator applied to unsigned type, result still unsigned
+# pragma warning( disable : 4702 ) // unreachable code
+
+// Turn off MSVC /analyze rules that generate too much noise
+# pragma warning( disable : 26495 ) // uninitialized member when constructor calls constructor
+# pragma warning( disable : 26446 ) // parser bug does not allow attributes on some templates
+
+#endif // gsl_COMPILER_MSVC_VER
+
+// GCC 7 does not like the signed unsigned mismatch (size_t ptrdiff_t)
+// While there is a conversion from signed to unsigned, it happens at
+// compiletime, so the compiler wouldn't have to warn indiscriminately, but
+// could check if the source value actually doesn't fit into the target type
+// and only warn in those cases.
+#if defined( __GNUC__ ) && __GNUC__ > 6
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif // defined( __GNUC__ ) && __GNUC__ > 6
+
+// Turn off clang unsafe buffer warnings as all accessed are guarded by runtime checks
+#if defined( __clang__ )
+# if __has_warning( "-Wunsafe-buffer-usage" )
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
+# endif // __has_warning( "-Wunsafe-buffer-usage" )
+#endif // defined( __clang__ )
+
+namespace detail {
+
+template< class T >
+gsl_api gsl_constexpr14 T * endptr( T * data, gsl_CONFIG_SPAN_INDEX_TYPE size ) // TODO: remove?
+{
+ // Be sure to run the check before doing pointer arithmetics, which would be UB for `nullptr` and non-0 integers.
+ gsl_Expects( size == 0 || data != gsl_nullptr );
+ return data + size;
+}
+
+template< gsl_CONFIG_SPAN_INDEX_TYPE From, gsl_CONFIG_SPAN_INDEX_TYPE To >
+struct is_allowed_extent_conversion
+ : std17::bool_constant< From == To || To == dynamic_extent >
+{
+};
+
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+template< class From, class To >
+struct is_allowed_element_type_conversion
+ : std17::bool_constant< std::is_convertible< From (*)[], To (*)[] >::value >
+{
+};
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+template< class T >
+class span_iterator
+{
+public:
+#if gsl_STDLIB_CPP20_OR_GREATER
+ typedef typename std::contiguous_iterator_tag iterator_concept;
+#endif // gsl_STDLIB_CPP20_OR_GREATER
+ typedef typename std::random_access_iterator_tag iterator_category;
+ typedef typename std11::remove_cv< T >::type value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T * pointer;
+ typedef T & reference;
+
+#ifdef _MSC_VER
+ typedef pointer _Unchecked_type;
+ typedef span_iterator _Prevent_inheriting_unwrap;
+#endif // _MSC_VER
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr span_iterator() = default;
+#else // ! gsl_HAVE( IS_DEFAULT )
+ gsl_api gsl_constexpr span_iterator() gsl_noexcept
+ : begin_( gsl_nullptr ), end_( gsl_nullptr ), current_( gsl_nullptr )
+ {
+ }
+#endif // gsl_HAVE( IS_DEFAULT )
+
+ gsl_api gsl_constexpr14 span_iterator( pointer begin, pointer end, pointer current )
+ : begin_( begin ), end_( end ), current_( current )
+ {
+ gsl_ExpectsDebug( begin_ <= current_ && current <= end_ );
+ }
+
+ gsl_api gsl_constexpr14 operator span_iterator< T const >() const gsl_noexcept
+ {
+ return span_iterator< T const >( begin_, end_, current_ );
+ }
+
+ gsl_api gsl_constexpr14 reference operator*() const
+ {
+ gsl_ExpectsDebug( current_ != end_ );
+ return *current_;
+ }
+
+ gsl_api gsl_constexpr14 pointer operator->() const
+ {
+ gsl_ExpectsDebug( current_ != end_ );
+ return current_;
+ }
+ gsl_api gsl_constexpr14 span_iterator& operator++()
+ {
+ gsl_ExpectsDebug( current_ != end_ );
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ ++current_;
+ return *this;
+ }
+
+ gsl_api gsl_constexpr14 span_iterator operator++( int )
+ {
+ span_iterator ret = *this;
+ ++*this;
+ return ret;
+ }
+
+ gsl_api gsl_constexpr14 span_iterator& operator--()
+ {
+ gsl_ExpectsDebug( begin_ != current_ );
+ --current_;
+ return *this;
+ }
+
+ gsl_api gsl_constexpr14 span_iterator operator--( int )
+ {
+ span_iterator ret = *this;
+ --*this;
+ return ret;
+ }
+
+ gsl_api gsl_constexpr14 span_iterator& operator+=( difference_type const n )
+ {
+ if ( n != 0 ) gsl_ExpectsDebug( begin_ && current_ && end_ );
+ if ( n > 0 ) gsl_ExpectsDebug( end_ - current_ >= n );
+ if ( n < 0 ) gsl_ExpectsDebug( current_ - begin_ >= -n );
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ current_ += n;
+ return *this;
+ }
+
+ gsl_api gsl_constexpr14 span_iterator operator+( difference_type const n ) const
+ {
+ span_iterator ret = *this;
+ ret += n;
+ return ret;
+ }
+
+ friend gsl_api gsl_constexpr14 span_iterator operator+( difference_type const n,
+ span_iterator const & rhs )
+ {
+ return rhs + n;
+ }
+
+ gsl_api gsl_constexpr14 span_iterator& operator-=( difference_type const n )
+ {
+ if ( n != 0 ) gsl_ExpectsDebug( begin_ && current_ && end_ );
+ if ( n > 0 ) gsl_ExpectsDebug( current_ - begin_ >= n );
+ if ( n < 0 ) gsl_ExpectsDebug( end_ - current_ >= -n );
+ gsl_SUPPRESS_MSGSL_WARNING(bounds .1)
+ current_ -= n;
+ return *this;
+ }
+
+ gsl_api gsl_constexpr14 span_iterator operator-( difference_type const n ) const
+ {
+ span_iterator ret = *this;
+ ret -= n;
+ return ret;
+ }
+
+ template<
+ class U
+ gsl_ENABLE_IF_(( std::is_same< typename std::remove_cv< U >::type, value_type >::value ))
+ >
+ gsl_api gsl_constexpr14 difference_type operator-( span_iterator< U > const & rhs ) const
+ {
+ gsl_ExpectsDebug( begin_ == rhs.begin_ && end_ == rhs.end_ );
+ return current_ - rhs.current_;
+ }
+
+ gsl_api gsl_constexpr14 reference operator[]( difference_type const n ) const
+ {
+ return *( *this + n );
+ }
+
+ template <
+ class U
+ gsl_ENABLE_IF_(( std::is_same< typename std::remove_cv< U >::type, value_type >::value ))
+ >
+ gsl_api gsl_constexpr14 bool operator==( span_iterator< U > const & rhs ) const
+ {
+ gsl_ExpectsDebug( begin_ == rhs.begin_ && end_ == rhs.end_ );
+ return current_ == rhs.current_;
+ }
+
+ template <
+ class U
+ gsl_ENABLE_IF_(( std::is_same< typename std::remove_cv< U >::type, value_type >::value ))
+ >
+ gsl_api gsl_constexpr14 bool operator!=( span_iterator< U > const & rhs ) const
+ {
+ return !( *this == rhs );
+ }
+
+ template <
+ class U
+ gsl_ENABLE_IF_(( std::is_same< typename std::remove_cv< U >::type, value_type >::value ))
+ >
+ gsl_api gsl_constexpr14 bool operator<( span_iterator< U > const & rhs ) const
+ {
+ gsl_ExpectsDebug( begin_ == rhs.begin_ && end_ == rhs.end_ );
+ return current_ < rhs.current_;
+ }
+
+ template <
+ class U
+ gsl_ENABLE_IF_(( std::is_same< typename std::remove_cv< U >::type, value_type >::value ))
+ >
+ gsl_api gsl_constexpr14 bool operator>( span_iterator< U > const & rhs ) const
+ {
+ return rhs < *this;
+ }
+
+ template <
+ class U
+ gsl_ENABLE_IF_(( std::is_same< typename std::remove_cv< U >::type, value_type >::value ))
+ >
+ gsl_api gsl_constexpr14 bool operator<=( span_iterator< U > const & rhs ) const
+ {
+ return !( rhs < *this );
+ }
+
+ template <
+ class U
+ gsl_ENABLE_IF_(( std::is_same< typename std::remove_cv< U >::type, value_type >::value ))
+ >
+ gsl_api gsl_constexpr14 bool operator>=( span_iterator< U > const & rhs ) const
+ {
+ return !( *this < rhs );
+ }
+
+#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 gsl_api gsl_constexpr14 void _Verify_range( span_iterator lhs, span_iterator rhs ) gsl_noexcept
+ {
+ // test that [lhs, rhs) forms a valid range inside an STL algorithm
+ gsl_Expects( lhs.begin_ == rhs.begin_ // range spans have to match
+ && lhs.end_ == rhs.end_ &&
+ lhs.current_ <= rhs.current_ ); // range must not be transposed
+ }
+
+ gsl_api gsl_constexpr14 void _Verify_offset( difference_type const n ) const gsl_noexcept
+ {
+ // test that *this + n is within the range of this call
+ if ( n != 0 ) gsl_Expects( begin_ && current_ && end_ );
+ if ( n > 0 ) gsl_Expects( end_ - current_ >= n );
+ if ( n < 0 ) gsl_Expects( current_ - begin_ >= -n );
+ }
+
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ gsl_api gsl_constexpr14 pointer _Unwrapped() const gsl_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 current_;
+ }
+
+ // Tell the STL that span_iterator should not be unwrapped if it can't
+ // validate in advance, even in release / optimized builds:
+# if gsl_CPP17_OR_GREATER
+ static constexpr bool _Unwrap_when_unverified = false;
+# else
+ static gsl_constexpr const bool _Unwrap_when_unverified = false;
+# endif
+ gsl_SUPPRESS_MSGSL_WARNING(con.3) // TODO: false positive
+ gsl_api gsl_constexpr14 void _Seek_to( pointer const p ) gsl_noexcept
+ {
+ // adjust the position of *this to previously verified location p
+ // after _Unwrapped
+ current_ = p;
+ }
+#endif
+
+#if gsl_HAVE( IS_DEFAULT )
+ pointer begin_ = nullptr;
+ pointer end_ = nullptr;
+ pointer current_ = nullptr;
+#else // ! gsl_HAVE( IS_DEFAULT )
+ pointer begin_;
+ pointer end_;
+ pointer current_;
+#endif // gsl_HAVE( IS_DEFAULT )
+
+#if gsl_STDLIB_CPP11_OR_GREATER
+ template< class Ptr >
+ friend struct std::pointer_traits;
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+};
+
+template< gsl_CONFIG_SPAN_INDEX_TYPE Ext >
+class extent_type
+{
+public:
+ typedef gsl_CONFIG_SPAN_INDEX_TYPE size_type;
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr extent_type() gsl_noexcept = default;
+#else // ! gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr extent_type() gsl_noexcept { }
+#endif // gsl_HAVE( IS_DEFAULT )
+
+ gsl_api gsl_constexpr14 gsl_explicit extent_type( extent_type< dynamic_extent > );
+
+ gsl_api gsl_constexpr14 gsl_explicit extent_type( size_type size ) { gsl_Expects( size == Ext ); }
+
+ gsl_api gsl_constexpr size_type size() const gsl_noexcept { return Ext; }
+
+private:
+#if gsl_CPP17_OR_GREATER
+ static constexpr size_type size_ = Ext; // static size equal to Ext
+#else
+ static gsl_constexpr const size_type size_ = Ext; // static size equal to Ext
+#endif
+};
+
+template<>
+class extent_type< dynamic_extent >
+{
+public:
+ typedef gsl_CONFIG_SPAN_INDEX_TYPE size_type;
+
+ template< size_type Other >
+ gsl_api gsl_constexpr gsl_explicit extent_type( extent_type< Other > ext )
+ : size_( ext.size() )
+ {
+ }
+
+ gsl_api gsl_constexpr14 gsl_explicit extent_type( size_type size )
+ : size_( size )
+ {
+ gsl_Expects( size != dynamic_extent );
+ }
+
+ gsl_api gsl_constexpr size_type size() const gsl_noexcept { return size_; }
+
+private:
+ size_type size_;
+};
+
+template< gsl_CONFIG_SPAN_INDEX_TYPE Ext >
+gsl_api gsl_constexpr14 extent_type< Ext >::extent_type( extent_type< dynamic_extent > ext )
+{
+ gsl_Expects( ext.size() == Ext );
+}
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent, gsl_CONFIG_SPAN_INDEX_TYPE Offset, gsl_CONFIG_SPAN_INDEX_TYPE Count >
+struct calculate_subspan_type
+{
+ typedef span< T, Count != dynamic_extent
+ ? Count
+ : ( Extent != dynamic_extent ? Extent - Offset : Extent ) > type;
+};
+
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE Extent, bool StaticExtent >
+struct calculate_recast_span_type_0
+{
+ typedef span< U, dynamic_extent > type;
+};
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+struct calculate_recast_span_type_0< T, U, Extent, true >
+{
+ typedef span< U, Extent * sizeof( T ) / sizeof( U ) > type;
+};
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+struct calculate_recast_span_type : calculate_recast_span_type_0< T, U, Extent, Extent != dynamic_extent >
+{
+};
+
+} // namespace detail
+
+// [span], class template span
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+class span
+{
+public:
+ // constants and types
+ typedef T element_type;
+ typedef typename std11::remove_cv< T >::type value_type;
+ typedef gsl_CONFIG_SPAN_INDEX_TYPE size_type;
+ typedef gsl_CONFIG_SPAN_INDEX_TYPE index_type;
+ typedef element_type * pointer;
+ typedef element_type const * const_pointer;
+ typedef element_type & reference;
+ typedef element_type const & const_reference;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef detail::span_iterator< T > iterator;
+ typedef detail::span_iterator< T const > const_iterator;
+ typedef std::reverse_iterator< iterator > reverse_iterator;
+ typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
+
+#if gsl_CPP17_OR_GREATER
+ static constexpr size_type extent{ Extent };
+#else
+ static gsl_constexpr const size_type extent = Extent;
+#endif
+
+ // [span.cons], span constructors, copy, assignment, and destructor
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( detail::is_allowed_extent_conversion< 0, MyExtent >::value ))
+ >
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+ gsl_api gsl_constexpr span() gsl_noexcept
+ : storage_( detail::extent_type< 0 >( ) )
+ {
+ }
+
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent != dynamic_extent ))
+ >
+ gsl_api gsl_constexpr14 gsl_explicit span( pointer ptr, size_type count )
+ : storage_( ptr, count )
+ {
+ gsl_Expects( count == Extent );
+ }
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent == dynamic_extent ))
+ >
+ gsl_api gsl_constexpr14 span( pointer ptr, size_type count )
+ : storage_( ptr, count )
+ {
+ }
+
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent != dynamic_extent ))
+ >
+ gsl_api gsl_constexpr14 gsl_explicit span( iterator it, size_type count )
+ : storage_( it.current_, count )
+ {
+ gsl_Expects( count == Extent );
+ gsl_Expects( it.end_ - it.current_ == static_cast< difference_type >( Extent ) );
+ }
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent == dynamic_extent ))
+ >
+ gsl_api gsl_constexpr14 span( iterator it, size_type count )
+ : storage_( it.current_, count )
+ {
+ gsl_Expects( it.end_ - it.current_ >= static_cast< difference_type >( count ) );
+ }
+
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent != dynamic_extent ))
+ >
+ gsl_api gsl_constexpr14 gsl_explicit span( pointer firstElem, pointer lastElem )
+ : storage_( firstElem, gsl_lite::narrow_cast< size_type >( lastElem - firstElem ) )
+ {
+ gsl_Expects( lastElem - firstElem == static_cast< difference_type >( Extent ) );
+ }
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent == dynamic_extent ))
+ >
+ gsl_api gsl_constexpr14 span( pointer firstElem, pointer lastElem )
+ : storage_( firstElem, gsl_lite::narrow_cast< size_type >( lastElem - firstElem ) )
+ {
+ gsl_Expects( firstElem <= lastElem );
+ }
+
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent != dynamic_extent ))
+ >
+ gsl_api gsl_constexpr14 gsl_explicit span( iterator firstElem, iterator lastElem )
+ : storage_( firstElem.current_, gsl_lite::narrow_cast< size_type >( lastElem - firstElem ) )
+ {
+ gsl_Expects( lastElem - firstElem == static_cast< difference_type >( Extent ) );
+ }
+ template<
+ gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent == dynamic_extent ))
+ >
+ gsl_api gsl_constexpr14 span( iterator firstElem, iterator lastElem )
+ : storage_( firstElem.current_, gsl_lite::narrow_cast< size_type >( lastElem - firstElem ) )
+ {
+ gsl_Expects( firstElem <= lastElem );
+ }
+#else // !( gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 ) )
+ gsl_api gsl_constexpr14 span( pointer ptr, size_type count )
+ : storage_( ptr, count )
+ {
+ gsl_Expects( Extent == dynamic_extent || count == Extent );
+ }
+ gsl_api gsl_constexpr14 span( iterator it, size_type count )
+ : storage_( it.current_, count )
+ {
+ gsl_Expects( Extent == dynamic_extent || count == Extent );
+ gsl_Expects( it.end_ - it.current_ >= static_cast< difference_type >( count ) );
+ }
+ gsl_api gsl_constexpr14 span( pointer firstElem, pointer lastElem )
+ : storage_( firstElem, gsl_lite::narrow_cast< size_type >( lastElem - firstElem ) )
+ {
+ gsl_Expects( firstElem <= lastElem );
+ gsl_Expects( Extent == dynamic_extent || lastElem - firstElem == static_cast< difference_type >( Extent ) );
+ }
+ gsl_api gsl_constexpr14 span( iterator firstElem, iterator lastElem )
+ : storage_( firstElem.current_, gsl_lite::narrow_cast< size_type >( lastElem - firstElem ) )
+ {
+ gsl_Expects( firstElem <= lastElem );
+ gsl_Expects( Extent == dynamic_extent || lastElem - firstElem == static_cast< difference_type >( Extent ) );
+ }
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+
+ template<
+ class U, std::size_t N
+ gsl_ENABLE_IF_(( detail::is_allowed_extent_conversion< N, Extent >::value &&
+ detail::is_allowed_element_type_conversion< U, element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( U (&arr)[N] ) gsl_noexcept
+ : storage_( known_not_null( arr ), detail::extent_type< N >( ) )
+ {
+ }
+
+#if gsl_HAVE( ARRAY )
+ template<
+ class U, std::size_t N
+ gsl_ENABLE_IF_(( detail::is_allowed_extent_conversion< N, Extent >::value &&
+ detail::is_allowed_element_type_conversion< U, element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( std::array<U, N> & arr ) gsl_noexcept
+ : storage_( known_not_null( arr.data() ), detail::extent_type< N >( ) )
+ {
+ }
+ template<
+ class U, std::size_t N
+ gsl_ENABLE_IF_(( detail::is_allowed_extent_conversion< N, Extent >::value &&
+ detail::is_allowed_element_type_conversion< U const , element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( std::array<U, N> const & arr ) gsl_noexcept
+ : storage_( known_not_null( arr.data() ), detail::extent_type< N >( ) )
+ {
+ }
+#endif // gsl_HAVE( ARRAY )
+
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+# if ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+ template< class Container, gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent != dynamic_extent &&
+ detail::is_compatible_container< Container, element_type >::value ))
+ >
+ gsl_api gsl_constexpr gsl_explicit span( Container & cont ) gsl_noexcept
+ : storage_( std17::data( cont ), std17::size( cont ) )
+ {
+ }
+ template< class Container, gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent == dynamic_extent &&
+ detail::is_compatible_container< Container, element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( Container & cont ) gsl_noexcept
+ : storage_( std17::data( cont ), std17::size( cont ) )
+ {
+ }
+
+ template< class Container, gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent != dynamic_extent &&
+ std::is_const< element_type >::value &&
+ detail::is_compatible_container< Container, element_type >::value ))
+ >
+ gsl_api gsl_constexpr gsl_explicit span( Container const & cont ) gsl_noexcept
+ : storage_( std17::data( cont ), std17::size( cont ) )
+ {
+ }
+ template< class Container, gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent == dynamic_extent &&
+ std::is_const< element_type >::value &&
+ detail::is_compatible_container< Container, element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( Container const & cont ) gsl_noexcept
+ : storage_( std17::data( cont ), std17::size( cont ) )
+ {
+ }
+# else // gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+ template< class Container
+ gsl_ENABLE_IF_(( detail::is_compatible_container< Container, element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( Container & cont ) gsl_noexcept
+ : storage_( std17::data( cont ), std17::size( cont ) )
+ {
+ }
+ template< class Container, gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ gsl_ENABLE_IF_(( std::is_const< element_type >::value &&
+ detail::is_compatible_container< Container, element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( Container const & cont ) gsl_noexcept
+ : storage_( std17::data( cont ), std17::size( cont ) )
+ {
+ }
+# endif // ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+#elif gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ template< class Container >
+ gsl_constexpr span( Container & cont )
+ : storage_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ), cont.size() )
+ {
+ }
+ template< class Container >
+ gsl_constexpr span( Container const & cont )
+ : storage_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ), cont.size() )
+ {
+ }
+#endif
+
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ template< class Container >
+ gsl_constexpr span( with_container_t, Container & cont )
+ : storage_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ), cont.size() )
+ {
+ }
+ template< class Container >
+ gsl_constexpr span( with_container_t, Container const & cont )
+ : storage_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ), cont.size() )
+ {
+ }
+#endif
+
+#if gsl_HAVE( IS_DEFAULT ) && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 430, 600)
+ gsl_constexpr span( span && ) gsl_noexcept = default;
+ gsl_constexpr span( span const & ) = default;
+#else
+ gsl_api gsl_constexpr span( span const & other )
+ : storage_( other.storage_ )
+ {
+ }
+#endif
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr14 span & operator=( span && ) gsl_noexcept = default;
+ gsl_constexpr14 span & operator=( span const & ) gsl_noexcept = default;
+#else
+ gsl_constexpr14 span & operator=( span const & other ) gsl_noexcept
+ {
+ storage_ = other.storage_;
+ return *this;
+ }
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+ template<
+ class OtherElementType, gsl_CONFIG_SPAN_INDEX_TYPE OtherExtent, gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( ( MyExtent == dynamic_extent || MyExtent == OtherExtent ) &&
+ detail::is_allowed_element_type_conversion< OtherElementType, element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( span< OtherElementType, OtherExtent > const & other ) gsl_noexcept
+ : storage_( other.data(), detail::extent_type< OtherExtent >( other.size() ) )
+ {
+ }
+ template<
+ class OtherElementType, gsl_CONFIG_SPAN_INDEX_TYPE OtherExtent, gsl_CONFIG_SPAN_INDEX_TYPE MyExtent = Extent
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ gsl_ENABLE_IF_NTTP_(( MyExtent != dynamic_extent && OtherExtent == dynamic_extent &&
+ detail::is_allowed_element_type_conversion< OtherElementType, element_type >::value ))
+ >
+ gsl_api gsl_constexpr gsl_explicit span( span< OtherElementType, OtherExtent > const & other ) gsl_noexcept
+ : storage_( other.data(), detail::extent_type< OtherExtent >( other.size() ) )
+ {
+ }
+#else // !( gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 ) )
+ template< class OtherElementType, gsl_CONFIG_SPAN_INDEX_TYPE OtherExtent >
+ gsl_api gsl_constexpr14 span( span< OtherElementType, OtherExtent > const & other )
+ : storage_( other.data(), detail::extent_type< OtherExtent >( other.size() ) )
+ {
+ gsl_STATIC_ASSERT_(
+ Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent,
+ "attempting copy-construction from incompatible span" );
+ gsl_Expects( Extent == dynamic_extent || other.size() == Extent );
+ }
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+
+ // [span.sub], span subviews
+
+ template< gsl_CONFIG_SPAN_INDEX_TYPE Count >
+ gsl_NODISCARD gsl_api gsl_constexpr14 span< element_type, Count >
+ first() const
+ {
+ gsl_STATIC_ASSERT_(
+ Extent == dynamic_extent || Count <= Extent,
+ "first() cannot extract more elements from a span than it contains" );
+ gsl_Expects( static_cast<std::size_t>( Count ) <= static_cast<std::size_t>( size() ) );
+ return span< element_type, Count >( data(), Count );
+ }
+
+ template < gsl_CONFIG_SPAN_INDEX_TYPE Count >
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ gsl_NODISCARD gsl_api gsl_constexpr14 span< element_type, Count >
+ last() const
+ {
+ gsl_STATIC_ASSERT_(
+ Extent == dynamic_extent || Count <= Extent,
+ "last() cannot extract more elements from a span than it contains" );
+ gsl_Expects( static_cast<std::size_t>( Count ) <= static_cast<std::size_t>( size() ) );
+ return span< element_type, Count >( data() + ( size() - Count ), Count );
+ }
+
+ template < gsl_CONFIG_SPAN_INDEX_TYPE Offset, gsl_CONFIG_SPAN_INDEX_TYPE Count >
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ gsl_NODISCARD gsl_api gsl_constexpr14 typename detail::calculate_subspan_type< T, Extent, Offset, Count >::type
+ subspan() const
+ {
+ gsl_STATIC_ASSERT_(
+ Extent == dynamic_extent || ( Extent >= Offset && ( Count == dynamic_extent ||
+ Count <= Extent - Offset ) ),
+ "subspan() cannot extract more elements from a span than it contains.");
+ gsl_Expects( static_cast<std::size_t>( size() ) >= static_cast<std::size_t>( Offset ) &&
+ ( Count == dynamic_extent || static_cast<std::size_t>( Count ) <= static_cast<std::size_t>( size() ) - static_cast<std::size_t>( Offset ) ) );
+ typedef typename detail::calculate_subspan_type< T, Extent, Offset, Count >::type type;
+ return type( data() + Offset, Count == dynamic_extent ? size() - Offset : Count );
+ }
+ template < gsl_CONFIG_SPAN_INDEX_TYPE Offset >
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ gsl_NODISCARD gsl_api gsl_constexpr14 typename detail::calculate_subspan_type< T, Extent, Offset, dynamic_extent >::type
+ subspan() const
+ {
+ gsl_STATIC_ASSERT_(
+ Extent == dynamic_extent || Extent >= Offset,
+ "subspan() cannot extract more elements from a span than it contains.");
+ gsl_Expects( static_cast<std::size_t>( size() ) >= static_cast<std::size_t>( Offset ) );
+ typedef typename detail::calculate_subspan_type< T, Extent, Offset, dynamic_extent >::type type;
+ return type( data() + Offset, size() - Offset );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 span< element_type, dynamic_extent >
+ first( size_type count ) const
+ {
+ gsl_Expects( static_cast<std::size_t>( count ) <= static_cast<std::size_t>( size() ) );
+ return span< element_type, dynamic_extent >( data(), count );
+ }
+ gsl_NODISCARD gsl_api gsl_constexpr14 span< element_type, dynamic_extent >
+ last( size_type count ) const
+ {
+ gsl_Expects( static_cast<std::size_t>( count ) <= static_cast<std::size_t>( size() ) );
+ return make_subspan( size() - count, dynamic_extent, subspan_selector< Extent >() );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 span<element_type, dynamic_extent>
+ subspan(size_type offset, size_type count = dynamic_extent) const
+ {
+ return make_subspan(offset, count, subspan_selector< Extent >() );
+ }
+
+ // [span.obs], span observers
+
+ gsl_NODISCARD gsl_api gsl_constexpr size_type
+ size() const gsl_noexcept
+ {
+ return storage_.size();
+ }
+ gsl_NODISCARD gsl_api gsl_constexpr std::ptrdiff_t
+ ssize() const gsl_noexcept
+ {
+ return gsl_lite::narrow_cast< std::ptrdiff_t >( storage_.size() );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr size_type
+ size_bytes() const gsl_noexcept
+ {
+ return size() * sizeof(element_type);
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr bool
+ empty() const gsl_noexcept
+ {
+ return size() == 0;
+ }
+
+ // [span.elem], span element access
+
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ operator[](size_type idx) const
+ {
+ gsl_Expects( static_cast<std::size_t>( idx ) < static_cast<std::size_t>( size() ) );
+ return storage_.data()[ idx ];
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ reference front() const
+ {
+ gsl_Expects( size() > 0 );
+ return storage_.data()[ 0 ];
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ reference back() const
+ {
+ gsl_Expects( size() > 0 );
+ return storage_.data()[ size() - 1 ];
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr pointer
+ data() const gsl_noexcept
+ {
+ return storage_.data();
+ }
+
+ // [span.iter], span iterator support
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 iterator
+ begin() const gsl_noexcept
+ {
+ const pointer data = storage_.data();
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ return iterator( data, data + size(), data );
+ }
+ gsl_NODISCARD gsl_api gsl_constexpr14 iterator
+ end() const gsl_noexcept
+ {
+ const pointer data = storage_.data();
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ const pointer endData = data + storage_.size();
+ return iterator( data, endData, endData );
+ }
+ gsl_NODISCARD gsl_api gsl_constexpr14 const_iterator
+ cbegin() const gsl_noexcept
+ {
+ const pointer data = storage_.data();
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ return const_iterator( data, data + size(), data );
+ }
+ gsl_NODISCARD gsl_api gsl_constexpr14 const_iterator
+ cend() const gsl_noexcept
+ {
+ const pointer data = storage_.data();
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ const pointer endData = data + storage_.size();
+ return const_iterator( data, endData, endData );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reverse_iterator
+ rbegin() const gsl_noexcept
+ {
+ return reverse_iterator( end() );
+ }
+ gsl_NODISCARD gsl_api gsl_constexpr14 reverse_iterator
+ rend() const gsl_noexcept
+ {
+ return reverse_iterator( begin() );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 const_reverse_iterator
+ crbegin() const gsl_noexcept
+ {
+ return const_reverse_iterator( cend() );
+ }
+ gsl_NODISCARD gsl_api gsl_constexpr14 const_reverse_iterator
+ crend() const gsl_noexcept
+ {
+ return const_reverse_iterator( cbegin() );
+ }
+
+ gsl_constexpr14 void
+ swap( span & other ) gsl_noexcept
+ {
+ std::swap( storage_, other.storage_ );
+ }
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 9 )
+ template< class U >
+ gsl_DEPRECATED_MSG("as_span() member function is unsafe")
+ gsl_NODISCARD gsl_api typename detail::calculate_recast_span_type< element_type, U, Extent >::type
+ as_span() const
+ {
+ gsl_Expects( ( this->size_bytes() % sizeof( U ) ) == 0 );
+ typedef typename detail::calculate_recast_span_type< element_type, U, Extent >::type type;
+ return type( reinterpret_cast<U *>( data() ), size_bytes() / sizeof( U ) ); // NOLINT
+ }
+#endif // ! gsl_DEPRECATE_TO_LEVEL( 9 )
+
+#ifdef _MSC_VER
+ // Tell MSVC how to unwrap spans in range-based-for
+ gsl_api gsl_constexpr pointer _Unchecked_begin() const gsl_noexcept { return data(); }
+ gsl_api gsl_constexpr pointer _Unchecked_end() const gsl_noexcept
+ {
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ return data() + size();
+ }
+#endif // _MSC_VER
+
+private:
+ // Needed to remove unnecessary null check in subspans
+ struct known_not_null
+ {
+ pointer p;
+
+ gsl_api gsl_constexpr known_not_null(pointer _p) gsl_noexcept
+ : p( _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
+ template< class ExtentType >
+ class storage_type : public ExtentType
+ {
+ public:
+ gsl_api gsl_constexpr storage_type( detail::extent_type< 0 > ext )
+ : ExtentType( ext ), data_( gsl_nullptr )
+ {
+ }
+
+ // known_not_null parameter is needed to remove unnecessary null check
+ // in subspans and constructors from arrays
+ template< class OtherExtentType >
+ gsl_api gsl_constexpr storage_type( known_not_null data, OtherExtentType ext )
+ : ExtentType( ext ), data_( data.p )
+ {
+ }
+
+ template< class OtherExtentType >
+ gsl_api gsl_constexpr14 storage_type( pointer data, OtherExtentType ext )
+ : ExtentType( ext ), data_( data )
+ {
+ gsl_Expects( data || ExtentType::size() == 0 );
+ }
+
+ gsl_api gsl_constexpr pointer data() const gsl_noexcept { return data_; }
+
+ private:
+ pointer data_;
+ };
+
+ storage_type< detail::extent_type< Extent > > storage_;
+
+ // The rest is needed to remove unnecessary null check
+ // in subspans and constructors from arrays
+ gsl_api gsl_constexpr span( known_not_null ptr, size_type count ) gsl_noexcept
+ : storage_(ptr, count)
+ {
+ }
+
+ template< gsl_CONFIG_SPAN_INDEX_TYPE CallerExtent >
+ class subspan_selector
+ {
+ };
+
+ template < gsl_CONFIG_SPAN_INDEX_TYPE CallerExtent >
+ gsl_api gsl_constexpr14 span< element_type, dynamic_extent >
+ make_subspan( size_type offset, size_type count, subspan_selector< CallerExtent > ) const
+ {
+ span< element_type, dynamic_extent > const tmp( *this );
+ return tmp.subspan( offset, count );
+ }
+
+ gsl_SUPPRESS_MSGSL_WARNING(bounds.1)
+ gsl_api gsl_constexpr14 span< element_type, dynamic_extent >
+ make_subspan( size_type offset, size_type count, subspan_selector< dynamic_extent > ) const
+ {
+ gsl_Expects( static_cast<std::size_t>( size() ) >= static_cast<std::size_t>( offset ) );
+
+ if ( count == dynamic_extent )
+ {
+ return span< element_type, dynamic_extent >( known_not_null( data() + offset ), size() - offset );
+ }
+
+ gsl_Expects( static_cast<std::size_t>( size() ) - static_cast<std::size_t>( offset ) >= static_cast<std::size_t>( count ) );
+ return span< element_type, dynamic_extent >( known_not_null( data() + offset ), count );
+ }
+};
+
+// class template argument deduction guides:
+
+#if gsl_HAVE( DEDUCTION_GUIDES ) // gsl_CPP17_OR_GREATER
+
+template<class Type, std::size_t Extent >
+span( Type (&)[Extent] ) -> span< Type, Extent >;
+
+template< class Type, std::size_t Size >
+span( std::array<Type, Size> & ) -> span< Type, Size >;
+
+template< class Type, std::size_t Size >
+span( std::array<Type, Size> const & ) -> span< Type const, Size >;
+
+template< class Container,
+ class Element = std::remove_pointer_t<decltype( std::declval< Container & >().data()) > >
+span( Container & ) -> span< Element >;
+
+template< class Container,
+ class Element = std::remove_pointer_t<decltype( std::declval< Container const & >().data()) > >
+span( Container const & ) -> span< Element >;
+
+#endif // gsl_HAVE( DEDUCTION_GUIDES )
+
+#if ! gsl_CPP17_OR_GREATER
+# if defined( __clang__ ) && defined( _MSC_VER )
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated" // Bug in clang-cl.exe which raises a C++17 -Wdeprecated warning about this static constexpr workaround in C++14 mode.
+# endif // defined( __clang__ ) && defined( _MSC_VER )
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+gsl_constexpr const typename span< T, Extent >::size_type span< T, Extent >::extent;
+# if defined( __clang__ ) && defined( _MSC_VER )
+# pragma clang diagnostic pop
+# endif // defined( __clang__ ) && defined( _MSC_VER )
+#endif // ! gsl_CPP17_OR_GREATER
+
+#if gsl_COMPILER_MSVC_VER
+# pragma warning( pop )
+#endif // gsl_COMPILER_MSVC_VER
+
+#if defined( __GNUC__ ) && __GNUC__ > 6
+# pragma GCC diagnostic pop
+#endif // defined( __GNUC__ ) && __GNUC__ > 6
+
+#if defined( __clang__ )
+# if __has_warning( "-Wunsafe-buffer-usage" )
+# pragma clang diagnostic pop
+# endif // __has_warning( "-Wunsafe-buffer-usage" )
+#endif // defined( __clang__ )
+
+// 26.7.3.7 Comparison operators [span.comparison]
+
+#if gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+# if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr bool operator==( span<T, LExtent> const & l, span<U, RExtent> const & r )
+{
+ gsl_STATIC_ASSERT_( LExtent == RExtent || LExtent == dynamic_extent || RExtent == dynamic_extent, "comparing spans of mismatching sizes" );
+ return l.size() == r.size()
+ && ( l.data() == r.data() || detail::equal( l.begin(), l.end(), r.begin() ) );
+}
+
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr bool operator< ( span<T, LExtent> const & l, span<U, RExtent> const & r )
+{
+ return detail::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+
+# else // a.k.a. !gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr bool operator==( span<T, LExtent> const & l, span<T, RExtent> const & r )
+{
+ gsl_STATIC_ASSERT_( LExtent == RExtent || LExtent == dynamic_extent || RExtent == dynamic_extent, "comparing spans of mismatching sizes" );
+ return l.size() == r.size()
+ && ( l.data() == r.data() || detail::equal( l.begin(), l.end(), r.begin() ) );
+}
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr bool operator< ( span<T, LExtent> const & l, span<T, RExtent> const & r )
+{
+ return detail::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+# endif // gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_NODISCARD inline gsl_constexpr bool
+operator!=( span<T, LExtent> const & l, span<U, RExtent> const & r )
+{
+ return !( l == r );
+}
+
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_NODISCARD inline gsl_constexpr bool
+operator<=( span<T, LExtent> const & l, span<U, RExtent> const & r )
+{
+ return !( r < l );
+}
+
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_NODISCARD inline gsl_constexpr bool
+operator>( span<T, LExtent> const & l, span<U, RExtent> const & r )
+{
+ return ( r < l );
+}
+
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_NODISCARD inline gsl_constexpr bool
+operator>=( span<T, LExtent> const & l, span<U, RExtent> const & r )
+{
+ return !( l < r );
+}
+#endif // gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+
+// span algorithms
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+gsl_NODISCARD gsl_api inline gsl_constexpr std::size_t
+size( span<T, Extent> const & spn )
+{
+ return static_cast<std::size_t>( spn.size() );
+}
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+gsl_NODISCARD gsl_api inline gsl_constexpr std::ptrdiff_t
+ssize( span<T, Extent> const & spn )
+{
+ return spn.ssize();
+}
+
+namespace detail {
+
+template< class II, class N, class OI >
+gsl_api gsl_constexpr14 inline OI copy_n( II first, N count, OI result )
+{
+ if ( count > 0 )
+ {
+ *result++ = *first;
+ for ( N i = 1; i < count; ++i )
+ {
+ *result++ = *++first;
+ }
+ }
+ return result;
+}
+}
+
+template< class T, class U, gsl_CONFIG_SPAN_INDEX_TYPE LExtent, gsl_CONFIG_SPAN_INDEX_TYPE RExtent >
+gsl_api gsl_constexpr14 inline void copy( span<T, LExtent> src, span<U, RExtent> dest )
+{
+#if gsl_CPP14_OR_GREATER // gsl_HAVE( TYPE_TRAITS ) (circumvent Travis clang 3.4)
+ static_assert( std::is_assignable<U &, T const &>::value, "Cannot assign elements of source span to elements of destination span" );
+#endif
+ gsl_STATIC_ASSERT_( RExtent >= LExtent || LExtent == dynamic_extent || RExtent == dynamic_extent ,"incompatible span extents" );
+ gsl_Expects( dest.size() >= src.size() );
+ detail::copy_n( src.data(), src.size(), dest.data() );
+}
+
+#if gsl_FEATURE( BYTE )
+// span creator functions (see ctors)
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+gsl_NODISCARD gsl_api inline span< const byte >
+as_bytes( span< T, Extent > spn ) gsl_noexcept
+{
+ return span< const byte >( reinterpret_cast<const byte *>( spn.data() ), spn.size_bytes() ); // NOLINT
+}
+
+template< class T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+gsl_NODISCARD gsl_api inline span< byte >
+as_writable_bytes( span< T, Extent > spn ) gsl_noexcept
+{
+ return span< byte >( reinterpret_cast<byte *>( spn.data() ), spn.size_bytes() ); // NOLINT
+}
+#endif // gsl_FEATURE( BYTE )
+
+#if gsl_FEATURE_TO_STD( MAKE_SPAN )
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr span<T>
+make_span( T * ptr, typename span<T>::index_type count )
+{
+ return span<T>( ptr, count );
+}
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr span<T>
+make_span( T * first, T * last )
+{
+ return span<T>( first, last );
+}
+
+template< class T, std::size_t N >
+gsl_NODISCARD inline gsl_constexpr span<T, static_cast<gsl_CONFIG_SPAN_INDEX_TYPE>( N )>
+make_span( T (&arr)[N] )
+{
+ return span<T, static_cast<gsl_CONFIG_SPAN_INDEX_TYPE>( N )>( arr );
+}
+
+# if gsl_HAVE( ARRAY )
+
+template< class T, std::size_t N >
+gsl_NODISCARD inline gsl_constexpr span<T, static_cast<gsl_CONFIG_SPAN_INDEX_TYPE>( N )>
+make_span( std::array<T, N> & arr )
+{
+ return span<T, static_cast<gsl_CONFIG_SPAN_INDEX_TYPE>( N )>( arr );
+}
+
+template< class T, std::size_t N >
+gsl_NODISCARD inline gsl_constexpr span<const T, static_cast<gsl_CONFIG_SPAN_INDEX_TYPE>( N )>
+make_span( std::array<T, N> const & arr )
+{
+ return span<const T, static_cast<gsl_CONFIG_SPAN_INDEX_TYPE>( N )>( arr );
+}
+# endif
+
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && gsl_HAVE( AUTO )
+
+template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
+gsl_NODISCARD inline gsl_constexpr auto
+make_span( Container & cont ) -> span< typename std::remove_pointer<EP>::type >
+{
+ return span< typename std::remove_pointer<EP>::type >( cont );
+}
+
+template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
+gsl_NODISCARD inline gsl_constexpr auto
+make_span( Container const & cont ) -> span< const typename std::remove_pointer<EP>::type >
+{
+ return span< const typename std::remove_pointer<EP>::type >( cont );
+}
+
+# else
+
+template< class T >
+inline span<T>
+make_span( std::vector<T> & cont )
+{
+ return span<T>( cont.data(), cont.data() + cont.size() );
+}
+
+template< class T >
+inline span<const T>
+make_span( std::vector<T> const & cont )
+{
+ return span<const T>( cont.data(), cont.data() + cont.size() );
+}
+
+# endif
+
+# if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+
+template< class Container >
+gsl_NODISCARD inline gsl_constexpr span<typename Container::value_type>
+make_span( with_container_t, Container & cont ) gsl_noexcept
+{
+ return span< typename Container::value_type >( with_container, cont );
+}
+
+template< class Container >
+gsl_NODISCARD inline gsl_constexpr span<const typename Container::value_type>
+make_span( with_container_t, Container const & cont ) gsl_noexcept
+{
+ return span< const typename Container::value_type >( with_container, cont );
+}
+
+# endif // gsl_FEATURE_TO_STD( WITH_CONTAINER )
+#endif // gsl_FEATURE_TO_STD( MAKE_SPAN )
+
+#if gsl_FEATURE( BYTE ) && gsl_FEATURE_TO_STD( BYTE_SPAN )
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr span<byte>
+byte_span( T & t ) gsl_noexcept
+{
+ return span<byte>( reinterpret_cast<byte *>( &t ), sizeof(T) );
+}
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr span<const byte>
+byte_span( T const & t ) gsl_noexcept
+{
+ return span<const byte>( reinterpret_cast<byte const *>( &t ), sizeof(T) );
+}
+
+#endif // gsl_FEATURE( BYTE ) && gsl_FEATURE_TO_STD( BYTE_SPAN )
+
+#if gsl_FEATURE( STRING_SPAN )
+//
+// basic_string_span:
+//
+
+template< class T >
+class basic_string_span;
+
+namespace detail {
+
+template< class T >
+struct is_basic_string_span_oracle : std11::false_type {};
+
+template< class T >
+struct is_basic_string_span_oracle< basic_string_span<T> > : std11::true_type {};
+
+template< class T >
+struct is_basic_string_span : is_basic_string_span_oracle< typename std11::remove_cv<T>::type > {};
+
+template< class T >
+gsl_api inline gsl_constexpr14 std::size_t string_length( T * ptr, std::size_t max )
+{
+ if ( ptr == gsl_nullptr || max <= 0 )
+ return 0;
+
+ std::size_t len = 0;
+ while ( len < max && ptr[len] ) // NOLINT
+ ++len;
+
+ return len;
+}
+
+} // namespace detail
+
+//
+// basic_string_span<> - A view of contiguous characters, replace (*,len).
+//
+template< class T >
+class basic_string_span
+{
+public:
+ typedef T element_type;
+ typedef span<T> span_type;
+
+ typedef typename span_type::size_type size_type;
+ typedef typename span_type::index_type index_type;
+ typedef typename span_type::difference_type difference_type;
+
+ typedef typename span_type::pointer pointer ;
+ typedef typename span_type::reference reference ;
+
+ typedef typename span_type::iterator iterator ;
+ typedef typename span_type::const_iterator const_iterator ;
+ typedef typename span_type::reverse_iterator reverse_iterator;
+ typedef typename span_type::const_reverse_iterator const_reverse_iterator;
+
+ // construction:
+
+# if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr basic_string_span() gsl_noexcept = default;
+# else
+ gsl_api gsl_constexpr basic_string_span() gsl_noexcept {}
+# endif
+
+# if gsl_HAVE( NULLPTR )
+ gsl_api gsl_constexpr basic_string_span( std::nullptr_t ) gsl_noexcept
+ : span_( nullptr, static_cast<index_type>( 0 ) )
+ {}
+# endif
+
+# ifdef __CUDACC_RELAXED_CONSTEXPR__
+ gsl_api
+# endif // __CUDACC_RELAXED_CONSTEXPR__
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( pointer ptr )
+ : span_( remove_z( ptr, (std::numeric_limits<index_type>::max)() ) )
+ {}
+
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_api gsl_constexpr basic_string_span( pointer ptr, index_type count )
+ : span_( ptr, count )
+ {}
+
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_api gsl_constexpr basic_string_span( pointer firstElem, pointer lastElem )
+ : span_( firstElem, lastElem )
+ {}
+
+ template< std::size_t N >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( element_type (&arr)[N] )
+ : span_( remove_z( gsl_ADDRESSOF( arr[0] ), N ) )
+ {}
+
+# if gsl_HAVE( ARRAY )
+
+ template< std::size_t N >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( std::array< typename std11::remove_const<element_type>::type, N> & arr )
+ : span_( remove_z( arr ) )
+ {}
+
+ template< std::size_t N >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( std::array< typename std11::remove_const<element_type>::type, N> const & arr )
+ : span_( remove_z( arr ) )
+ {}
+
+# endif // gsl_HAVE( ARRAY )
+
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+ // Exclude: array, [basic_string,] basic_string_span
+
+ template< class Container
+ gsl_ENABLE_IF_((
+ ! detail::is_std_array< Container >::value
+ && ! detail::is_basic_string_span< Container >::value
+ && std::is_convertible< typename Container::pointer, pointer >::value
+ && std::is_convertible< typename Container::pointer, decltype(std::declval<Container>().data()) >::value
+ ))
+ >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( Container & cont )
+ : span_( ( cont ) )
+ {}
+
+ // Exclude: array, [basic_string,] basic_string_span
+
+ template< class Container
+ gsl_ENABLE_IF_((
+ ! detail::is_std_array< Container >::value
+ && ! detail::is_basic_string_span< Container >::value
+ && std::is_convertible< typename Container::pointer, pointer >::value
+ && std::is_convertible< typename Container::pointer, decltype(std::declval<Container const &>().data()) >::value
+ ))
+ >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( Container const & cont )
+ : span_( ( cont ) )
+ {}
+
+# elif gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+
+ template< class Container >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( Container & cont )
+ : span_( cont )
+ {}
+
+ template< class Container >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( Container const & cont )
+ : span_( cont )
+ {}
+
+# else
+
+ template< class U, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_api gsl_constexpr basic_string_span( span< U, Extent > const & rhs )
+ : span_( rhs )
+ {}
+
+# endif
+
+# if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+
+ template< class Container >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span( with_container_t, Container & cont )
+ : span_( with_container, cont )
+ {}
+# endif
+
+# if gsl_HAVE( IS_DEFAULT )
+# if gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 440, 600 )
+ gsl_constexpr basic_string_span( basic_string_span const & ) = default;
+
+ gsl_constexpr basic_string_span( basic_string_span && ) = default;
+# else
+ gsl_constexpr basic_string_span( basic_string_span const & ) gsl_noexcept = default;
+
+ gsl_constexpr basic_string_span( basic_string_span && ) gsl_noexcept = default;
+# endif
+# endif
+
+ template< class U
+ gsl_ENABLE_IF_(( std::is_convertible<typename basic_string_span<U>::pointer, pointer>::value ))
+ >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_api gsl_constexpr basic_string_span( basic_string_span<U> const & rhs )
+ : span_( reinterpret_cast<pointer>( rhs.data() ), rhs.length() ) // NOLINT
+ {}
+
+# if gsl_STDLIB_CPP11_120
+ template< class U
+ gsl_ENABLE_IF_(( std::is_convertible<typename basic_string_span<U>::pointer, pointer>::value ))
+ >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_api gsl_constexpr basic_string_span( basic_string_span<U> && rhs )
+ : span_( reinterpret_cast<pointer>( rhs.data() ), rhs.length() ) // NOLINT
+ {}
+# endif // gsl_STDLIB_CPP11_120
+
+ template< class CharTraits, class Allocator >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span(
+ std::basic_string< typename std11::remove_const<element_type>::type, CharTraits, Allocator > & str )
+ : span_( gsl_ADDRESSOF( str[0] ), str.length() )
+ {}
+
+ template< class CharTraits, class Allocator >
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_string_span<> is deprecated; use span<> instead")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_constexpr basic_string_span(
+ std::basic_string< typename std11::remove_const<element_type>::type, CharTraits, Allocator > const & str )
+ : span_( gsl_ADDRESSOF( str[0] ), str.length() )
+ {}
+
+ // assignment:
+
+# if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr14 basic_string_span & operator=( basic_string_span const & ) gsl_noexcept = default;
+
+ gsl_constexpr14 basic_string_span & operator=( basic_string_span && ) gsl_noexcept = default;
+# endif
+
+ // sub span:
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr14 basic_string_span
+ first( index_type count ) const
+ {
+ return span_.first( count );
+ }
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr14 basic_string_span
+ last( index_type count ) const
+ {
+ return span_.last( count );
+ }
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr14 basic_string_span
+ subspan( index_type offset ) const
+ {
+ return span_.subspan( offset );
+ }
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr14 basic_string_span
+ subspan( index_type offset, index_type count ) const
+ {
+ return span_.subspan( offset, count );
+ }
+
+ // observers:
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ length() const gsl_noexcept
+ {
+ return span_.size();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ size() const gsl_noexcept
+ {
+ return span_.size();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ length_bytes() const gsl_noexcept
+ {
+ return span_.size_bytes();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ size_bytes() const gsl_noexcept
+ {
+ return span_.size_bytes();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr bool
+ empty() const gsl_noexcept
+ {
+ return size() == 0;
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ operator[]( index_type idx ) const
+ {
+ return span_[idx];
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ front() const
+ {
+ return span_.front();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ back() const
+ {
+ return span_.back();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr pointer
+ data() const gsl_noexcept
+ {
+ return span_.data();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr iterator
+ begin() const gsl_noexcept
+ {
+ return span_.begin();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr iterator
+ end() const gsl_noexcept
+ {
+ return span_.end();
+ }
+
+ gsl_NODISCARD gsl_constexpr17 reverse_iterator
+ rbegin() const gsl_noexcept
+ {
+ return span_.rbegin();
+ }
+
+ gsl_NODISCARD gsl_constexpr17 reverse_iterator
+ rend() const gsl_noexcept
+ {
+ return span_.rend();
+ }
+
+ // const version not in p0123r2:
+
+ gsl_NODISCARD gsl_api gsl_constexpr const_iterator
+ cbegin() const gsl_noexcept
+ {
+ return span_.cbegin();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr const_iterator
+ cend() const gsl_noexcept
+ {
+ return span_.cend();
+ }
+
+ gsl_NODISCARD gsl_constexpr17 const_reverse_iterator
+ crbegin() const gsl_noexcept
+ {
+ return span_.crbegin();
+ }
+
+ gsl_NODISCARD gsl_constexpr17 const_reverse_iterator
+ crend() const gsl_noexcept
+ {
+ return span_.crend();
+ }
+
+private:
+ gsl_api static gsl_constexpr14 span_type remove_z( pointer sz, std::size_t max )
+ {
+ return span_type( sz, detail::string_length( sz, max ) );
+ }
+
+# if gsl_HAVE( ARRAY )
+ template< size_t N >
+ gsl_NODISCARD static gsl_constexpr14 span_type
+ remove_z( std::array<typename std11::remove_const<element_type>::type, N> & arr )
+ {
+ return remove_z( gsl_ADDRESSOF( arr[0] ), gsl_lite::narrow_cast< std::size_t >( N ) );
+ }
+
+ template< size_t N >
+ gsl_NODISCARD static gsl_constexpr14 span_type
+ remove_z( std::array<typename std11::remove_const<element_type>::type, N> const & arr )
+ {
+ return remove_z( gsl_ADDRESSOF( arr[0] ), gsl_lite::narrow_cast< std::size_t >( N ) );
+ }
+# endif
+
+private:
+ span_type span_;
+};
+
+// basic_string_span comparison functions:
+
+# if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, class U >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator==( basic_string_span<T> const & l, U const & u ) gsl_noexcept
+{
+ const basic_string_span< typename std11::add_const<T>::type > r( u );
+
+ return l.size() == r.size()
+ && detail::equal( l.begin(), l.end(), r.begin() );
+}
+
+template< class T, class U >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<( basic_string_span<T> const & l, U const & u ) gsl_noexcept
+{
+ const basic_string_span< typename std11::add_const<T>::type > r( u );
+
+ return detail::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+
+# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator==( U const & u, basic_string_span<T> const & r ) gsl_noexcept
+{
+ const basic_string_span< typename std11::add_const<T>::type > l( u );
+
+ return l.size() == r.size()
+ && detail::equal( l.begin(), l.end(), r.begin() );
+}
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<( U const & u, basic_string_span<T> const & r ) gsl_noexcept
+{
+ const basic_string_span< typename std11::add_const<T>::type > l( u );
+
+ return detail::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+# endif
+
+# else // ! gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator==( basic_string_span<T> const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return l.size() == r.size()
+ && detail::equal( l.begin(), l.end(), r.begin() );
+}
+
+template< class T >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<( basic_string_span<T> const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return detail::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+
+# endif // gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator!=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
+{
+ return !( l == r );
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
+{
+# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) || ! gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+ return !( r < l );
+# else
+ basic_string_span< typename std11::add_const<T>::type > rr( r );
+ return !( rr < l );
+# endif
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator>( basic_string_span<T> const & l, U const & r ) gsl_noexcept
+{
+# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) || ! gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+ return ( r < l );
+# else
+ basic_string_span< typename std11::add_const<T>::type > rr( r );
+ return ( rr < l );
+# endif
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator>=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
+{
+ return !( l < r );
+}
+
+# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator!=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return !( l == r );
+}
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return !( r < l );
+}
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator>( U const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return ( r < l );
+}
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator>=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return !( l < r );
+}
+
+# endif // gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+# if gsl_FEATURE( BYTE )
+// convert basic_string_span to byte span:
+
+template< class T >
+gsl_NODISCARD gsl_api inline span< const byte >
+as_bytes( basic_string_span<T> spn ) gsl_noexcept
+{
+ return span< const byte >( reinterpret_cast<const byte *>( spn.data() ), spn.size_bytes() ); // NOLINT
+}
+# endif // gsl_FEATURE( BYTE )
+#endif // gsl_FEATURE( STRING_SPAN )
+
+//
+// String types:
+//
+
+typedef char * zstring;
+typedef const char * czstring;
+
+# if gsl_HAVE( WCHAR )
+typedef wchar_t * wzstring;
+typedef const wchar_t * cwzstring;
+# endif
+
+#if gsl_FEATURE( STRING_SPAN )
+
+typedef basic_string_span< char > string_span;
+typedef basic_string_span< char const > cstring_span;
+
+# if gsl_HAVE( WCHAR )
+typedef basic_string_span< wchar_t > wstring_span;
+typedef basic_string_span< wchar_t const > cwstring_span;
+# endif
+
+// to_string() allow (explicit) conversions from string_span to string
+
+# if 0
+
+template< class T >
+inline std::basic_string< typename std::remove_const<T>::type > to_string( basic_string_span<T> spn )
+{
+ std::string( spn.data(), spn.length() );
+}
+
+# else
+
+gsl_NODISCARD inline std::string
+to_string( string_span const & spn )
+{
+ return std::string( spn.data(), static_cast<std::size_t>( spn.length() ) );
+}
+
+gsl_NODISCARD inline std::string
+to_string( cstring_span const & spn )
+{
+ return std::string( spn.data(), static_cast<std::size_t>( spn.length() ) );
+}
+
+# if gsl_HAVE( WCHAR )
+
+gsl_NODISCARD inline std::wstring
+to_string( wstring_span const & spn )
+{
+ return std::wstring( spn.data(), static_cast<std::size_t>( spn.length() ) );
+}
+
+gsl_NODISCARD inline std::wstring
+to_string( cwstring_span const & spn )
+{
+ return std::wstring( spn.data(), static_cast<std::size_t>( spn.length() ) );
+}
+
+# endif // gsl_HAVE( WCHAR )
+# endif // to_string()
+
+//
+// Stream output for string_span types
+//
+
+namespace detail {
+
+template< class Stream >
+void write_padding( Stream & os, std::streamsize n )
+{
+ for ( std::streamsize i = 0; i < n; ++i )
+ os.rdbuf()->sputc( os.fill() );
+}
+
+template< class Stream, class Span >
+Stream & write_to_stream( Stream & os, Span const & spn )
+{
+ typename Stream::sentry sentry( os );
+
+ if ( !os )
+ return os;
+
+ const std::streamsize length = gsl_lite::narrow_failfast<std::streamsize>( spn.length() );
+
+ // Whether, and how, to pad
+ const bool pad = ( length < os.width() );
+ const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right;
+
+ if ( left_pad )
+ detail::write_padding( os, os.width() - length );
+
+ // Write span characters
+ os.rdbuf()->sputn( spn.data(), length );
+
+ if ( pad && !left_pad )
+ detail::write_padding( os, os.width() - length );
+
+ // Reset output stream width
+ os.width(0);
+
+ return os;
+}
+
+} // namespace detail
+
+template< typename Traits >
+std::basic_ostream< char, Traits > & operator<<( std::basic_ostream< char, Traits > & os, string_span const & spn )
+{
+ return detail::write_to_stream( os, spn );
+}
+
+template< typename Traits >
+std::basic_ostream< char, Traits > & operator<<( std::basic_ostream< char, Traits > & os, cstring_span const & spn )
+{
+ return detail::write_to_stream( os, spn );
+}
+
+# if gsl_HAVE( WCHAR )
+
+template< typename Traits >
+std::basic_ostream< wchar_t, Traits > & operator<<( std::basic_ostream< wchar_t, Traits > & os, wstring_span const & spn )
+{
+ return detail::write_to_stream( os, spn );
+}
+
+template< typename Traits >
+std::basic_ostream< wchar_t, Traits > & operator<<( std::basic_ostream< wchar_t, Traits > & os, cwstring_span const & spn )
+{
+ return detail::write_to_stream( os, spn );
+}
+
+# endif // gsl_HAVE( WCHAR )
+
+//
+// ensure_sentinel()
+//
+// Provides a way to obtain a span from a contiguous sequence
+// that ends with a (non-inclusive) sentinel value.
+//
+// Will fail-fast if sentinel cannot be found before max elements are examined.
+//
+namespace detail {
+
+template< class T, class SizeType, const T Sentinel >
+gsl_constexpr14 static span<T> ensure_sentinel( T * seq, SizeType max = (std::numeric_limits<SizeType>::max)() )
+{
+ typedef T * pointer;
+
+ gsl_SUPPRESS_MSVC_WARNING( 26429, "f.23: symbol 'cur' is never tested for nullness, it can be marked as not_null" )
+ pointer cur = seq;
+
+ while ( static_cast<SizeType>( cur - seq ) < max && *cur != Sentinel )
+ ++cur;
+
+ gsl_Expects( *cur == Sentinel );
+
+ return span<T>( seq, gsl_lite::narrow_cast< typename span<T>::index_type >( cur - seq ) );
+}
+} // namespace detail
+
+//
+// ensure_z - creates a string_span for a czstring or cwzstring.
+// Will fail fast if a null-terminator cannot be found before
+// the limit of size_type.
+//
+
+template< class T >
+gsl_NODISCARD inline gsl_constexpr14 span<T>
+ensure_z( T * const & sz, size_t max = (std::numeric_limits<size_t>::max)() )
+{
+ return detail::ensure_sentinel<T, size_t, 0>( sz, max );
+}
+
+template< class T, size_t N >
+gsl_NODISCARD inline gsl_constexpr14 span<T>
+ensure_z( T (&sz)[N] )
+{
+ return ::gsl_lite::ensure_z( gsl_ADDRESSOF( sz[0] ), N );
+}
+
+# if gsl_HAVE( TYPE_TRAITS )
+
+template< class Container >
+gsl_NODISCARD inline gsl_constexpr14 span< typename std::remove_pointer<typename Container::pointer>::type >
+ensure_z( Container & cont )
+{
+ return ::gsl_lite::ensure_z( cont.data(), cont.length() );
+}
+# endif
+
+//
+// basic_zstring_span<> - A view of contiguous null-terminated characters, replace (*,len).
+//
+
+template <typename T>
+class basic_zstring_span
+{
+public:
+ typedef T element_type;
+ typedef span<T> span_type;
+
+ typedef typename span_type::index_type index_type;
+ typedef typename span_type::difference_type difference_type;
+
+ typedef element_type * czstring_type;
+ typedef basic_string_span<element_type> string_span_type;
+
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_zstring_span<> is deprecated")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_api gsl_constexpr14 basic_zstring_span( span_type s )
+ : span_( s )
+ {
+ // expects a zero-terminated span
+ gsl_Expects( s.back() == '\0' );
+ }
+
+# if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr basic_zstring_span( basic_zstring_span const & ) = default;
+ gsl_constexpr basic_zstring_span( basic_zstring_span && ) = default;
+ gsl_constexpr14 basic_zstring_span & operator=( basic_zstring_span const & ) = default;
+ gsl_constexpr14 basic_zstring_span & operator=( basic_zstring_span && ) = default;
+# else
+ gsl_api gsl_constexpr basic_zstring_span( basic_zstring_span const & other) : span_ ( other.span_ ) {}
+ gsl_api gsl_constexpr basic_zstring_span & operator=( basic_zstring_span const & other ) { span_ = other.span_; return *this; }
+# endif
+
+ gsl_NODISCARD gsl_api gsl_constexpr bool
+ empty() const gsl_noexcept
+ {
+ return false;
+ }
+
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_zstring_span<> is deprecated")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_NODISCARD gsl_api gsl_constexpr string_span_type
+ as_string_span() const gsl_noexcept
+ {
+ return string_span_type( span_.data(), span_.size() - 1 );
+ }
+
+# if gsl_DEPRECATE_TO_LEVEL( 7 )
+ gsl_DEPRECATED_MSG("basic_zstring_span<> is deprecated")
+# endif // gsl_DEPRECATE_TO_LEVEL( 7 )
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr string_span_type
+ ensure_z() const
+ {
+ return ::gsl_lite::ensure_z(span_.data(), span_.size());
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr czstring_type
+ assume_z() const gsl_noexcept
+ {
+ return span_.data();
+ }
+
+private:
+ span_type span_;
+};
+
+//
+// zString types:
+//
+
+typedef basic_zstring_span< char > zstring_span;
+typedef basic_zstring_span< char const > czstring_span;
+
+# if gsl_HAVE( WCHAR )
+typedef basic_zstring_span< wchar_t > wzstring_span;
+typedef basic_zstring_span< wchar_t const > cwzstring_span;
+# endif
+#endif // gsl_FEATURE( STRING_SPAN )
+
+} // namespace gsl_lite
+
+#if gsl_HAVE( HASH )
+
+//
+// std::hash specializations for GSL types
+//
+
+namespace gsl_lite {
+
+namespace detail {
+
+//
+// Helper struct for std::hash specializations
+//
+
+template<bool Condition>
+struct conditionally_enabled_hash
+{
+
+};
+
+// disabled as described in [unord.hash]
+template<>
+struct conditionally_enabled_hash< false >
+{
+gsl_is_delete_access:
+ conditionally_enabled_hash() gsl_is_delete;
+ conditionally_enabled_hash( conditionally_enabled_hash const & ) gsl_is_delete;
+ conditionally_enabled_hash( conditionally_enabled_hash && ) gsl_is_delete;
+ conditionally_enabled_hash & operator=( conditionally_enabled_hash const & ) gsl_is_delete;
+ conditionally_enabled_hash & operator=( conditionally_enabled_hash && ) gsl_is_delete;
+};
+
+} // namespace detail
+
+} // namespace gsl_lite
+
+namespace std {
+
+template< class T >
+struct hash< ::gsl_lite::not_null< T > > : public ::gsl_lite::detail::conditionally_enabled_hash< is_default_constructible< hash< T > >::value >
+{
+public:
+ gsl_NODISCARD std::size_t
+ operator()( ::gsl_lite::not_null<T> const & v ) const
+ // hash function is not `noexcept` because `as_nullable()` has preconditions
+ {
+ return hash<T>()( ::gsl_lite::as_nullable( v ) );
+ }
+};
+template< class T >
+struct hash< ::gsl_lite::not_null< T* > >
+{
+public:
+ gsl_NODISCARD std::size_t
+ operator()( ::gsl_lite::not_null< T* > const & v ) const gsl_noexcept
+ {
+ return hash<T*>()( ::gsl_lite::as_nullable( v ) );
+ }
+};
+
+# if gsl_FEATURE( BYTE )
+template<>
+struct hash< ::gsl_lite::byte >
+{
+public:
+ gsl_NODISCARD std::size_t operator()( ::gsl_lite::byte v ) const gsl_noexcept
+ {
+# if gsl_CONFIG_DEFAULTS_VERSION >= 1
+ return std::hash<unsigned char>{ }( ::gsl_lite::to_uchar( v ) );
+# else // gsl_CONFIG_DEFAULTS_VERSION < 1
+ // Keep the old hashing algorithm if legacy defaults are used.
+ return ::gsl_lite::to_integer<std::size_t>( v );
+# endif // gsl_CONFIG_DEFAULTS_VERSION >= 1
+ }
+};
+# endif // gsl_FEATURE( BYTE )
+
+} // namespace std
+
+#endif // gsl_HAVE( HASH )
+
+#if gsl_STDLIB_CPP11_OR_GREATER
+namespace std {
+
+template< class T >
+struct pointer_traits< ::gsl_lite::detail::span_iterator< T > >
+{
+ typedef ::gsl_lite::detail::span_iterator< T > pointer;
+ typedef T element_type;
+ typedef ptrdiff_t difference_type;
+
+ static gsl_constexpr element_type * to_address( pointer const i ) gsl_noexcept { return i.current_; }
+};
+
+} // namespace std
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+
+#if gsl_FEATURE( GSL_COMPATIBILITY_MODE )
+
+// Enable GSL compatibility mode by aliasing all symbols in the `gsl` namespace and defining the unprefixed
+// macros `Expects()` and `Ensures()`.
+//
+// gsl-lite can generally coexist with Microsoft GSL. However, if GSL compatibility mode is enabled,
+// gsl-lite cannot be used in the same translation unit as Microsoft GSL.
+// (Link-time compatibility is unaffected; different translation units that use either Microsoft GSL
+// or gsl-lite may be linked together.)
+
+namespace gsl = ::gsl_lite;
+
+#define Expects( x ) gsl_Expects( x )
+#define Ensures( x ) gsl_Ensures( x )
+
+#endif // gsl_FEATURE( GSL_COMPATIBILITY_MODE )
+
+gsl_RESTORE_MSVC_WARNINGS()
+#if gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+# pragma clang diagnostic pop
+#endif // gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+#if gsl_COMPILER_GNUC_VERSION
+# pragma GCC diagnostic pop
+#endif // gsl_COMPILER_GNUC_VERSION
+
+// #undef internal macros
+#undef gsl_STATIC_ASSERT_
+#undef gsl_ENABLE_IF_R_
+#undef gsl_ENABLE_IF_NTTP_
+#undef gsl_ENABLE_IF_
+#undef gsl_TRAILING_RETURN_TYPE_
+#undef gsl_RETURN_DECLTYPE_
+
+#endif // GSL_LITE_GSL_LITE_HPP_INCLUDED
+
+// end of file
diff --git a/thirdparty/gsl-lite/include/gsl/gsl-lite.hpp b/thirdparty/gsl-lite/include/gsl/gsl-lite.hpp
new file mode 100644
index 000000000..70b5486b5
--- /dev/null
+++ b/thirdparty/gsl-lite/include/gsl/gsl-lite.hpp
@@ -0,0 +1,43 @@
+//
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// gsl-lite is originally based on Microsoft GSL, which is an implementation of the C++ Core Guidelines Support Library:
+// https://github.com/microsoft/GSL
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2025 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef GSL_GSL_LITE_HPP_INCLUDED
+#define GSL_GSL_LITE_HPP_INCLUDED
+
+#include <gsl-lite/gsl-lite.hpp>
+
+#if ! gsl_FEATURE( GSL_COMPATIBILITY_MODE )
+
+# pragma message (__FILE__ "(" gsl_STRINGIFY( __LINE__ ) "): warning: The legacy header file <gsl/gsl-lite.hpp> implicitly enables gsl-lite's GSL compatibility mode, making namespace gsl and the Expects() and Ensures() macros available for backward compatibility. If possible, modernize your code by including the <gsl-lite/gsl-lite.hpp> header file, referring to namespace gsl_lite rather than namespace gsl, and using the prefixed contract checking macros gsl_Expects() and gsl_Ensures() instead of the unprefixed Expects() and Ensures(). If you wish to explicitly retain the GSL compatibility mode, define the macro gsl_FEATURE_GSL_COMPATIBILITY_MODE=1 in the build options.")
+
+// Implicitly enable the GSL compatbility mode.
+# undef gsl_FEATURE_GSL_COMPATIBILITY_MODE
+# define gsl_FEATURE_GSL_COMPATIBILITY_MODE 1
+
+namespace gsl = ::gsl_lite;
+
+# define Expects( x ) gsl_Expects( x )
+# define Ensures( x ) gsl_Ensures( x )
+
+#endif // ! gsl_FEATURE( GSL_COMPATIBILITY_MODE )
+
+#endif // GSL_GSL_LITE_HPP_INCLUDED
+
+// end of file
diff --git a/thirdparty/gsl-lite/src/gsl-lite.natvis b/thirdparty/gsl-lite/src/gsl-lite.natvis
new file mode 100644
index 000000000..b73e9a03c
--- /dev/null
+++ b/thirdparty/gsl-lite/src/gsl-lite.natvis
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+ <Type Name="gsl_lite::fail_fast">
+ <!-- na hides the address, otherwise it would appear as 0x.... "Message" -->
+ <DisplayString>{_Data._What,nasb}</DisplayString>
+ </Type>
+
+ <Type Name="gsl_lite::span&lt;*&gt;">
+ <DisplayString>{{ size={last_ - first_} }}</DisplayString>
+ <Expand>
+ <Item Name="[size]">last_ - first_</Item>
+ <ArrayItems>
+ <Size>last_ - first_</Size>
+ <ValuePointer>first_</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="gsl_lite::not_null&lt;*&gt;">
+ <DisplayString>{data_.ptr_}</DisplayString>
+ <Expand>
+ <ExpandedItem>data_.ptr_</ExpandedItem>
+ </Expand>
+ </Type>
+</AutoVisualizer>
diff --git a/thirdparty/gsl-lite/test/MakeTestTarget.cmake b/thirdparty/gsl-lite/test/MakeTestTarget.cmake
new file mode 100644
index 000000000..8f8bf1be5
--- /dev/null
+++ b/thirdparty/gsl-lite/test/MakeTestTarget.cmake
@@ -0,0 +1,331 @@
+# Copyright 2015-2019 by Martin Moene
+# Copyright 2019-2021 by Moritz Beutel
+#
+# gsl-lite is based on GSL: Guidelines Support Library,
+# https://github.com/microsoft/gsl
+#
+# This code is licensed under the MIT License (MIT).
+
+
+if( DEFINED _makeTestTarget )
+ return() # prevent multiple inclusion
+endif()
+set( _makeTestTarget )
+
+
+
+# Configure gsl-lite for testing:
+
+set( GSL_CONFIG
+ "gsl_TESTING_"
+)
+
+set( CUDA_OPTIONS )
+
+# Preset available C++ language compiler flags:
+
+set( HAS_STD_FLAGS FALSE )
+set( HAS_CPP98_FLAG FALSE )
+set( HAS_CPP11_FLAG FALSE )
+set( HAS_CPP14_FLAG FALSE )
+set( HAS_CPP17_FLAG FALSE )
+set( HAS_CPP20_FLAG FALSE )
+set( HAS_CPPLATEST_FLAG FALSE )
+
+# Preset available CUDA language compiler flags:
+
+set( HAS_CUDA14_FLAG FALSE )
+set( HAS_CUDA17_FLAG FALSE )
+
+set( HOST_COMPILER_PREFIX "" )
+
+# Determine compiler-specifics for MSVC, GNUC, Clang:
+
+if( MSVC )
+ set( HAS_STD_FLAGS TRUE )
+
+ # remove "/EHx" from CMAKE_CXX_FLAGS if present
+ if( CMAKE_CXX_FLAGS MATCHES "/EH[ascr-]+" )
+ string( REGEX REPLACE "/EH[ascr-]+" " " CMAKE_CXX_FLAGS_NEW "${CMAKE_CXX_FLAGS}" )
+ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_NEW}" )
+ endif()
+
+ # remove "/Wx" from CMAKE_CXX_FLAGS if present
+ if( CMAKE_CXX_FLAGS MATCHES "/W[0-4]" )
+ string( REGEX REPLACE "/W[0-4]" " " CMAKE_CXX_FLAGS_NEW "${CMAKE_CXX_FLAGS}" )
+ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_NEW}" )
+ endif()
+
+ # clang-cl: available std flags depends on version
+ if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
+ message( STATUS "Matched: clang-cl ${CMAKE_CXX_COMPILER_VERSION}" )
+
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.3.0 )
+ set( HAS_CPP11_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4.0 )
+ set( HAS_CPP14_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0.0 )
+ set( HAS_CPP17_FLAG TRUE )
+ set( HAS_CPPLATEST_FLAG TRUE )
+ endif()
+ else()
+ message( STATUS "Matched: MSVC ${CMAKE_CXX_COMPILER_VERSION}" )
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.00 )
+ set( HAS_CPP14_FLAG TRUE )
+ set( HAS_CPPLATEST_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.11 )
+ set( HAS_CPP17_FLAG TRUE )
+ endif()
+ endif()
+
+# Older CMake versions identify NVHPC compilers as PGI.
+elseif( CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang|PGI|NVHPC" )
+
+ set( HAS_STD_FLAGS TRUE )
+ set( HAS_CPP98_FLAG TRUE )
+
+ # GNU: available -std flags depends on version
+ if( CMAKE_CXX_COMPILER_ID MATCHES "GNU" )
+ message( STATUS "Matched: GNU ${CMAKE_CXX_COMPILER_VERSION}" )
+
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7.0 )
+ set( HAS_CPP11_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.2 )
+ set( HAS_CPP14_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.1.0 )
+ set( HAS_CPP17_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0.0 )
+ set( HAS_CPP20_FLAG TRUE )
+ endif()
+
+ # AppleClang: available -std flags depends on version
+ elseif( CMAKE_CXX_COMPILER_ID MATCHES "AppleClang" )
+ message( STATUS "Matched: AppleClang ${CMAKE_CXX_COMPILER_VERSION}" )
+
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0.0 )
+ set( HAS_CPP11_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1.0 )
+ set( HAS_CPP14_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.2.0 )
+ set( HAS_CPP17_FLAG TRUE )
+ endif()
+
+ # Clang: available -std flags depends on version
+ elseif( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
+ message( STATUS "Matched: Clang ${CMAKE_CXX_COMPILER_VERSION}" )
+
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.3.0 )
+ set( HAS_CPP11_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4.0 )
+ set( HAS_CPP14_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0.0 )
+ set( HAS_CPP17_FLAG TRUE )
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0.0 )
+ set( HAS_CPP20_FLAG TRUE )
+ endif()
+ # Older CMake versions identify NVHPC compilers as PGI.
+ elseif( CMAKE_CXX_COMPILER_ID MATCHES "PGI|NVHPC" )
+ message( STATUS "Matched: NVHPC/PGI ${CMAKE_CXX_COMPILER_VERSION}" )
+ set( HAS_CPP11_FLAG TRUE )
+ set( HAS_CPP14_FLAG TRUE )
+ set( HAS_CPP17_FLAG TRUE )
+ set( HAS_CPP20_FLAG TRUE )
+ endif()
+elseif( CMAKE_CXX_COMPILER_ID MATCHES "Intel" )
+ message( STATUS "Matched: Intel ${CMAKE_CXX_COMPILER_VERSION}" )
+else()
+ message( STATUS "Matched: nothing (CompilerId: '${CMAKE_CXX_COMPILER_ID}')")
+endif()
+
+# Determine compiler-specifics for NVCC:
+
+get_property( _languages GLOBAL PROPERTY ENABLED_LANGUAGES )
+if( CUDA IN_LIST _languages )
+ if( CMAKE_CUDA_COMPILER_ID MATCHES "NVIDIA" )
+ message( STATUS "Matched: NVCC ${CMAKE_CUDA_COMPILER_VERSION}" )
+
+ # Set NVCC-specific options:
+ set( HOST_COMPILER_PREFIX "-Xcompiler=" )
+ list( APPEND CUDA_OPTIONS "--Werror" "all-warnings" "-G" )
+
+ set( HAS_CUDA14_FLAG TRUE )
+ if( CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0 )
+ set( HAS_CUDA17_FLAG TRUE )
+ endif()
+ endif()
+endif()
+
+# Enable MS C++ Core Guidelines checker if MSVC (but only when using MSBuild because Ninja cannot find the <CppCoreCheck/warnings.h> header):
+
+function( enable_msvs_guideline_checker target )
+ if( MSVC AND CMAKE_GENERATOR MATCHES "Visual Studio" )
+ target_compile_definitions( ${target} PRIVATE gsl_TESTING_CPPCORECHECK_ )
+ set_target_properties( ${target} PROPERTIES
+ VS_GLOBAL_EnableCppCoreCheck true
+ VS_GLOBAL_CodeAnalysisRuleSet CppCoreCheckRules.ruleset
+ VS_GLOBAL_RunCodeAnalysis true )
+ endif()
+endfunction()
+
+# Make target, compile for given standard if specified:
+
+function( make_test_target target )
+
+ set( optionArgs CUDA NO_EXCEPTIONS COMPILE_ONLY NO_PCH )
+ set( oneValueArgs STD DEFAULTS_VERSION CONTRACT_VIOLATION CONTRACT_CHECKING UNENFORCED_CONTRACTS )
+ set( multiValueArgs SOURCES EXTRA_OPTIONS )
+ cmake_parse_arguments( "SCOPE" "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
+ if( SCOPE_UNPARSED_ARGUMENTS )
+ list( JOIN SCOPE_UNPARSED_ARGUMENTS "\", \"" SCOPE_UNPARSED_ARGUMENTS_STR )
+ list( JOIN "${oneValueArgs};${multiValueArgs}" "\", \"" POSSIBLE_ARGUMENTS_STR )
+ message( SEND_ERROR "make_test_target(): Invalid argument keyword(s) \"${SCOPE_UNPARSED_ARGUMENTS_STR}\"; expected one of \"${POSSIBLE_ARGUMENTS_STR}\"" )
+ endif()
+ if( SCOPE_KEYWORDS_MISSING_VALUES )
+ list( JOIN SCOPE_KEYWORDS_MISSING_VALUES "\", \"" SCOPE_KEYWORDS_MISSING_VALUES_STR )
+ message( SEND_ERROR "make_test_target(): argument keyword(s) \"${SCOPE_KEYWORDS_MISSING_VALUES_STR}\" missing values" )
+ endif()
+ if( NOT DEFINED SCOPE_SOURCES )
+ message( SEND_ERROR "make_test_target(): no argument specified for SCOPE_SOURCES" )
+ endif()
+ if( NOT DEFINED SCOPE_DEFAULTS_VERSION )
+ message( SEND_ERROR "make_test_target(): no argument specified for DEFAULTS_VERSION" )
+ endif()
+ if( NOT DEFINED SCOPE_CONTRACT_VIOLATION )
+ set( SCOPE_CONTRACT_VIOLATION "THROWS" )
+ endif()
+ if( NOT DEFINED SCOPE_CONTRACT_CHECKING )
+ set( SCOPE_CONTRACT_CHECKING "ON" )
+ endif()
+ if( NOT DEFINED SCOPE_UNENFORCED_CONTRACTS )
+ set( SCOPE_UNENFORCED_CONTRACTS "ELIDE" )
+ endif()
+
+ message( STATUS "Make target: '${target}'" )
+
+ add_executable( ${target} ${SCOPE_SOURCES} )
+
+ set( localOptions ${OPTIONS} )
+ set( localDefinitions ${GSL_CONFIG} "gsl_CONFIG_CONTRACT_VIOLATION_${SCOPE_CONTRACT_VIOLATION}" "gsl_CONFIG_UNENFORCED_CONTRACTS_${SCOPE_UNENFORCED_CONTRACTS}" )
+
+ if( SCOPE_CONTRACT_CHECKING )
+ list( APPEND localDefinitions "gsl_CONFIG_CONTRACT_CHECKING_AUDIT" )
+ else()
+ list( APPEND localDefinitions "gsl_CONFIG_CONTRACT_CHECKING_OFF" )
+ endif()
+
+ if( MSVC )
+ list( APPEND localOptions "/WX" "/W4" )
+ list( APPEND localOptions "/w44062" ) # enable C4062: enumerator 'identifier' in a switch of enum 'enumeration' is not handled
+ list( APPEND localOptions "/w44242" ) # enable C4242: 'identifier': conversion from 'type1' to 'type2', possible loss of data
+ list( APPEND localOptions "/w44254" ) # enable C4254: 'operator': conversion from 'type1' to 'type2', possible loss of data
+ list( APPEND localOptions "/w44265" ) # enable C4265: 'class': class has virtual functions, but destructor is not virtual
+ list( APPEND localDefinitions "_SCL_SECURE_NO_WARNINGS" )
+ if( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0 ) # VC++ 2010 and earlier
+ list( APPEND localOptions "/wd4127" ) # disable C4127: conditional expression is constant
+ list( APPEND localOptions "/wd4275" ) # disable C4275: non dll-interface class 'stdext::exception' used as base for dll-interface class 'std::bad_cast'
+ endif()
+ if ( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0 ) # VC++ 2012 and earlier
+ list( APPEND localOptions "/wd4345" ) # disable C4345: behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized [actually, value-initialized]
+ endif()
+ if( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.1 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0 ) # VC++ 2015
+ list( APPEND localOptions "/wd4577" ) # disable C4577: 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
+ list( APPEND localOptions "/wd4702" ) # disable C4702: unreachable code
+ endif()
+ elseif( CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang" )
+ list( APPEND localOptions
+ "-Werror"
+ "-Wall"
+ "-Wextra"
+ #"-Wno-missing-braces"
+ "-Wconversion"
+ "-Wsign-conversion"
+ "-fno-elide-constructors"
+ "-fstrict-aliasing" "-Wstrict-aliasing=2"
+ )
+ if( NOT SCOPE_CUDA )
+ list( APPEND localOptions "-pedantic" ) # NVCC and "-pedantic" don't mix (GCC complains that NVCC-generated GCC-specific code is GCC specific)
+ endif()
+ if( CMAKE_CXX_COMPILER_ID MATCHES "GNU" )
+ list( APPEND localOptions
+ "-Wno-long-long" # irrelevant strict-C++98 warning about non-standard type `long long`
+ "-Wuseless-cast" # leads to warnings that need to be suppressed, cf. https://github.com/gsl-lite/gsl-lite/issues/325
+ )
+ if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8 )
+ list( APPEND localOptions "-Wno-type-limits" ) # irrelevant warning about `unsigned value < 0` comparison
+ endif()
+ if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0 )
+ list( APPEND localOptions "-Wno-error=array-bounds" ) # work around compiler bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100137
+ endif()
+ elseif( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang" )
+ list( APPEND localOptions
+ "-Wno-c++11-long-long" # irrelevant strict-C++98 warning about non-standard type `long long`
+ "-Wweak-vtables" # leads to warnings that need to be suppressed, cf. https://github.com/gsl-lite/gsl-lite/issues/322
+ )
+ endif()
+ endif()
+
+ if( SCOPE_NO_EXCEPTIONS )
+ if( MSVC )
+ list( APPEND localOptions "/EHs-" )
+ list( APPEND localDefinitions "_HAS_EXCEPTIONS=0" )
+ elseif( CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang" )
+ list( APPEND localOptions "-fno-exceptions" )
+ endif()
+ else()
+ if( MSVC )
+ list( APPEND localOptions "/EHsc" )
+ endif()
+ endif()
+
+ if( SCOPE_STD )
+ if( MSVC )
+ list( APPEND localOptions "/std:c++${SCOPE_STD}" )
+ else()
+ list( APPEND localOptions "-std=c++${SCOPE_STD}" )
+ endif()
+ endif()
+
+ if( SCOPE_CUDA )
+ list( TRANSFORM localOptions PREPEND "${HOST_COMPILER_PREFIX}" )
+ target_compile_options( ${target} PRIVATE ${CUDA_OPTIONS} )
+ if( SCOPE_STD )
+ set_target_properties( ${target} PROPERTIES CUDA_STANDARD ${SCOPE_STD} )
+ endif()
+ endif()
+
+ target_compile_options( ${target} PRIVATE ${localOptions} ${SCOPE_EXTRA_OPTIONS} )
+ target_compile_definitions( ${target} PRIVATE ${localDefinitions} )
+ target_link_libraries( ${target} PRIVATE gsl-lite-${SCOPE_DEFAULTS_VERSION} )
+
+ if( NOT SCOPE_NO_PCH
+ AND NOT CMAKE_VERSION VERSION_LESS 3.16 # VERSION_GREATER_EQUAL doesn't exist in CMake 3.5
+ AND NOT ( CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_SYSTEM_NAME MATCHES "Darwin" ) ) # and GCC on MacOS has trouble with addresses of some text segments in the PCH
+ target_precompile_headers( ${target}
+ PRIVATE
+ <gsl-lite/gsl-lite.hpp>
+ <ostream>
+ <sstream>
+ <iostream>
+ <cstring>
+ )
+ endif()
+
+ if( NOT SCOPE_COMPILE_ONLY )
+ # We only add tests for targets with exceptions enabled. lest has been modified to permit compilation without exceptions
+ # so we can test compiling gsl-lite without exceptions, but the no-exception tests will not run correctly because lest
+ # relies on exceptions for running tests and therefore cannot function correctly without.
+ add_test( NAME ${target} COMMAND ${target} )
+ endif()
+
+endfunction()
diff --git a/thirdparty/gsl-lite/test/assert.t.cpp b/thirdparty/gsl-lite/test/assert.t.cpp
new file mode 100644
index 000000000..d2957f392
--- /dev/null
+++ b/thirdparty/gsl-lite/test/assert.t.cpp
@@ -0,0 +1,229 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+
+#include <vector>
+
+namespace {
+
+bool expects( bool x ) { gsl_Expects( x ); return x; }
+bool ensures( bool x ) { gsl_Ensures( x ); return x; }
+bool assert_( bool x ) { gsl_Assert( x ); return x; }
+void failFast() { gsl_FailFast(); }
+bool expectsDebug( bool x ) { gsl_ExpectsDebug( x ); return x; }
+bool ensuresDebug( bool x ) { gsl_EnsuresDebug( x ); return x; }
+bool assertDebug( bool x ) { gsl_AssertDebug( x ); return x; }
+bool expectsAudit( bool x ) { gsl_ExpectsAudit( x ); return x; }
+bool ensuresAudit( bool x ) { gsl_EnsuresAudit( x ); return x; }
+bool assertAudit( bool x ) { gsl_AssertAudit( x ); return x; }
+
+enum Color
+#if gsl_CPP11_OR_GREATER
+: int
+#endif
+{ red, green, blue };
+
+#if gsl_COMPILER_NVHPC_VERSION && !gsl_CPP11_OR_GREATER
+# pragma diag_suppress 941 // Suppress: missing return statement at end of non-void function "..."
+#endif
+std::string colorToString( Color color )
+{
+ switch (color)
+ {
+ case red: return "red";
+ case green: return "green";
+ case blue: return "blue";
+ }
+ gsl_FailFast(); // this should keep the compiler from issuing a warning about not returning a value
+}
+#if gsl_COMPILER_NVHPC_VERSION && !gsl_CPP11_OR_GREATER
+# pragma diag_default 941
+#endif
+
+
+struct ConvertibleToBool
+{
+#if gsl_CPP11_OR_GREATER
+ explicit
+#endif
+ operator bool(void) const gsl_noexcept { return true; }
+};
+
+
+} // anonymous namespace
+
+CASE( "gsl_Expects(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( expects( true ) );
+}
+
+CASE( "gsl_Ensures(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( ensures( true ) );
+}
+
+CASE( "gsl_Assert(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( assert_( true ) );
+}
+
+CASE( "gsl_Expects(): Terminates on a false expression" )
+{
+ EXPECT_THROWS( expects( false ) );
+}
+
+CASE( "gsl_Ensures(): Terminates on a false expression" )
+{
+ EXPECT_THROWS( ensures( false ) );
+}
+
+CASE( "gsl_Assert(): Terminates on a false expression" )
+{
+ EXPECT_THROWS( assert_( false ) );
+}
+
+CASE( "gsl_FailFast(): Suppresses compiler warning about missing return value" )
+{
+ EXPECT( colorToString(red) == "red" );
+}
+
+CASE( "gsl_FailFast(): Terminates" )
+{
+ EXPECT_THROWS( failFast() );
+#if gsl_CPP11_OR_GREATER
+ EXPECT_THROWS( colorToString( Color( 42 ) ) );
+#endif
+}
+
+CASE( "gsl_ExpectsDebug(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( expectsDebug( true ) );
+}
+
+CASE( "gsl_EnsuresDebug(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( ensuresDebug( true ) );
+}
+
+CASE( "gsl_AssertDebug(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( assertDebug( true ) );
+}
+
+CASE( "gsl_ExpectsDebug(): Terminates on a false expression in debug build or AUDIT mode" )
+{
+#if !defined( NDEBUG ) || defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+ EXPECT_THROWS( expectsDebug( false ) );
+#else
+ EXPECT_NO_THROW( expectsDebug( false ) );
+#endif
+}
+
+CASE( "gsl_EnsuresAudit(): Terminates on a false expression in debug build or AUDIT mode" )
+{
+#if !defined( NDEBUG ) || defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+ EXPECT_THROWS( ensuresDebug( false ) );
+#else
+ EXPECT_NO_THROW( ensuresDebug( false ) );
+#endif
+}
+
+CASE( "gsl_AssertAudit(): Terminates on a false expression in debug build or AUDIT mode" )
+{
+#if !defined( NDEBUG ) || defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+ EXPECT_THROWS( assertDebug( false ) );
+#else
+ EXPECT_NO_THROW( assertDebug( false ) );
+#endif
+}
+
+CASE( "gsl_ExpectsAudit(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( expectsAudit( true ) );
+}
+
+CASE( "gsl_EnsuresAudit(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( ensuresAudit( true ) );
+}
+
+CASE( "gsl_AssertAudit(): Allows a true expression" )
+{
+ EXPECT_NO_THROW( assertAudit( true ) );
+}
+
+CASE( "gsl_ExpectsAudit(): Terminates on a false expression in AUDIT mode" )
+{
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+ EXPECT_THROWS( expectsAudit( false ) );
+#else
+ EXPECT_NO_THROW( expectsAudit( false ) );
+#endif
+}
+
+CASE( "gsl_EnsuresAudit(): Terminates on a false expression in AUDIT mode" )
+{
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+ EXPECT_THROWS( ensuresAudit( false ) );
+#else
+ EXPECT_NO_THROW( ensuresAudit( false ) );
+#endif
+}
+
+CASE( "gsl_AssertAudit(): Terminates on a false expression in AUDIT mode" )
+{
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+ EXPECT_THROWS( assertAudit( false ) );
+#else
+ EXPECT_NO_THROW( assertAudit( false ) );
+#endif
+}
+
+int myAt( int i, std::vector<int> const& v )
+{
+ // The arguments to `__assume( x )` (MSVC) and `__builtin_assume( x )` (Clang) are never evaluated, so they cannot incur side-effects. We would like to implement
+ // `gsl_ASSUME_()` in terms of these. However, Clang always emits a diagnostic if a potential side-effect is discarded, and every call to a function not annotated
+ // `__attribute__ ((pure))` or `__attribute__ ((const))` is considered a potential side-effect (e.g. the call to `v.size()` below). In many cases Clang is capable
+ // of inlining the expression and find it free of side-effects, cf. https://gcc.godbolt.org/z/ZcKfbp, but the warning is produced anyway.
+ //
+ // To avoid littering user code with warnings, we instead define `gsl_ASSUME_()` in terms of `__builtin_unreachable()`. The following `gsl_ASSUME_()` statement
+ // should thus compile without any warnings.
+
+ gsl_Expects( i >= 0 && static_cast<std::size_t>(i) < v.size() );
+ return v.at( static_cast<std::size_t>(i) );
+}
+
+CASE( "gsl_Expects(): No warnings produced for function calls in precondition checks" )
+{
+ std::vector<int> v;
+ v.push_back( 42 );
+ EXPECT_NO_THROW( myAt( 0, v ) );
+ EXPECT_THROWS( myAt( 1, v ) );
+}
+
+CASE( "gsl_Expects(): Supports explicit conversions to bool" )
+{
+ // `gsl_Expects()` should be compatible with explicit conversions to bool.
+ gsl_Expects( ConvertibleToBool() );
+
+ if ( ConvertibleToBool() ) { } // to get rid of weird NVCC warning about never-referenced conversion operator
+}
+
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/at.t.cpp b/thirdparty/gsl-lite/test/at.t.cpp
new file mode 100644
index 000000000..c011daa75
--- /dev/null
+++ b/thirdparty/gsl-lite/test/at.t.cpp
@@ -0,0 +1,163 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+
+using namespace gsl_lite;
+
+CASE( "at(): Terminates access to non-existing C-array elements" )
+{
+ int a[] = { 1, 2, 3, 4 };
+
+ EXPECT_THROWS( (void) at(a, 4) );
+}
+
+CASE( "at(): Terminates access to non-existing std::array elements (C++11)" )
+{
+#if gsl_HAVE( ARRAY )
+ std::array<int, 4> a = {{ 1, 2, 3, 4 }};
+
+ EXPECT_THROWS( (void) at(a, 4) );
+#else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+#endif
+}
+
+CASE( "at(): Terminates access to non-existing std::vector elements" )
+{
+ std::vector<int> a; // = { 1, 2, 3, 4 };
+
+ for ( int i = 0; i < 4; ++i )
+ {
+ a.push_back( i + 1 );
+ }
+
+ EXPECT_THROWS( (void) at(a, 4) );
+}
+
+CASE( "at(): Terminates access to non-existing std::initializer_list elements (C++11)" )
+{
+// Note: GCC 4.6.3 has std::initializer_list but selects at(Cont & cont,...) overload.
+
+#if gsl_HAVE( INITIALIZER_LIST ) && ( !gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_GNUC_VERSION >= 473 )
+ std::initializer_list<int> a = { 1, 2, 3, 4 };
+
+ EXPECT_THROWS( (void) at(a, 4) );
+#else
+ EXPECT( !!"std::initializer_list<> is not available (no C++11)" );
+#endif
+}
+
+CASE( "at(): Terminates access to non-existing gsl_lite::span elements" )
+{
+ int arr[] = { 1, 2, 3, 4 };
+ span<int> a( arr );
+
+ EXPECT_THROWS( (void) at(a, 4) );
+}
+
+CASE( "at(): Allows to access existing C-array elements" )
+{
+ size_t a[] = { 1, 2, 3, 4 };
+ size_t const b[] = { 1, 2, 3, 4 };
+
+ for ( size_t i = 0; i < 4; ++i )
+ {
+ EXPECT( at(a, i) == i + 1 );
+ EXPECT( at(b, i) == i + 1 );
+ }
+}
+
+CASE( "at(): Allows to access existing std::array elements (C++11)" )
+{
+#if gsl_HAVE( ARRAY )
+ std::array<size_t, 4> a = {{ 1, 2, 3, 4 }};
+ std::array<size_t, 4> const b = {{ 1, 2, 3, 4 }};
+ std::array<size_t const, 4> c = {{ 1, 2, 3, 4 }};
+
+ for ( size_t i = 0; i < 4; ++i )
+ {
+ EXPECT( at(a, i) == i + 1 );
+ EXPECT( at(b, i) == i + 1 );
+ EXPECT( at(c, i) == i + 1 );
+ }
+#else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+#endif
+}
+
+namespace {
+
+std::vector<size_t> make_vector( size_t N )
+{
+ std::vector<size_t> v;
+ for ( size_t i = 0; i < N; ++i )
+ {
+ v.push_back( i + 1 );
+ }
+ return v;
+}
+}
+
+CASE( "at(): Allows to access existing std::vector elements" )
+{
+ std::vector<size_t> a = make_vector( 4 ); // = { 1, 2, 3, 4 };
+ std::vector<size_t> const b = make_vector( 4 ); // = { 1, 2, 3, 4 };
+
+ for ( size_t i = 0; i < 4; ++i )
+ {
+ EXPECT( at(a, i) == i + 1 );
+ EXPECT( at(b, i) == i + 1 );
+ }
+}
+
+CASE( "at(): Allows to access std::initializer_list elements (C++11)" )
+{
+// Note: GCC 4.6.3 has std::initializer_list but selects at(Cont & cont,...) overload.
+
+#if gsl_HAVE( INITIALIZER_LIST ) && ( !gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_GNUC_VERSION >= 473 )
+ std::initializer_list<size_t> a = { 1, 2, 3, 4 };
+ std::initializer_list<size_t> const b = { 1, 2, 3, 4 };
+
+ for ( size_t i = 0; i < 4; ++i )
+ {
+ EXPECT( at(a, i) == i + 1 );
+ EXPECT( at(b, i) == i + 1 );
+ }
+#else
+ EXPECT( !!"std::initializer_list<> is not available (no C++11)" );
+#endif
+}
+
+CASE( "at(): Allows to access gsl_lite::span elements" )
+{
+ size_t arr[] = { 1, 2, 3, 4 };
+ size_t const carr[] = { 1, 2, 3, 4 };
+ span<size_t> a( arr );
+ span<size_t> const b( arr );
+ span<size_t const> c( carr );
+
+ for ( size_t i = 0; i < 4; ++i )
+ {
+ EXPECT( at(a, i) == i + 1 );
+ EXPECT( at(b, i) == i + 1 );
+ EXPECT( at(c, i) == i + 1 );
+ }
+}
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/byte.t.cpp b/thirdparty/gsl-lite/test/byte.t.cpp
new file mode 100644
index 000000000..07cc7169e
--- /dev/null
+++ b/thirdparty/gsl-lite/test/byte.t.cpp
@@ -0,0 +1,216 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+
+using namespace gsl_lite;
+
+#if gsl_FEATURE( BYTE )
+
+// Use gsl_lite::byte instead of plain byte to prevent collisions with
+// other byte declarations, such as in rpcndr.h (Windows kit).
+
+// We have a chicken & egg problem here:
+// verifying operations via to_integer() that has yet to verified itself...
+
+CASE( "byte: Allows to construct from integral via static cast (C++17)" )
+{
+# if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ gsl_lite::byte b = static_cast<gsl_lite::byte>( 4 );
+ EXPECT( static_cast<unsigned char>(b) == 4 );
+ EXPECT( to_integer<int>( b ) == 4 );
+# else
+ EXPECT( !!"enum class is not constructible from underlying type (no C++17)" );
+# endif
+}
+
+CASE( "byte: Allows to construct from integral via byte() (C++17)" )
+{
+# if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ gsl_lite::byte b = gsl_lite::byte( 4 );
+ EXPECT( to_integer<int>( b ) == 4 );
+# else
+ EXPECT( !!"enum class is not constructible from underlying type (no C++17)" );
+# endif
+}
+
+CASE( "byte: Allows to construct from integral via to_byte()" )
+{
+ gsl_lite::byte b = to_byte( 4 );
+ EXPECT( to_integer<int>( b ) == 4 );
+}
+
+CASE( "byte: Allows to convert to integral via to_integer()" )
+{
+ gsl_lite::byte b = to_byte( 4 );
+ EXPECT( to_integer<int>( b ) == 4 );
+}
+
+CASE( "byte: Allows comparison operations" )
+{
+ gsl_lite::byte a = to_byte( 3 );
+ gsl_lite::byte b = to_byte( 7 );
+
+ EXPECT( a == a );
+ EXPECT( a != b );
+
+ EXPECT( a < b );
+ EXPECT( a <= a );
+ EXPECT( a <= b );
+
+ EXPECT( b > a );
+ EXPECT( b >= a );
+ EXPECT( b >= b );
+
+ EXPECT_NOT( a == b );
+ EXPECT_NOT( a != a );
+ EXPECT_NOT( b < a );
+ EXPECT_NOT( a > b );
+}
+
+CASE( "byte: Allows bitwise or operation" )
+{
+ gsl_lite::byte const b = to_byte( 0xa5 );
+
+ EXPECT( ( b | b ) == b );
+ EXPECT( ( b | to_byte( 0x00 ) ) == b );
+ EXPECT( ( b | to_byte( 0xff ) ) == to_byte( 0xff ) );
+}
+
+CASE( "byte: Allows bitwise and operation" )
+{
+ gsl_lite::byte const b = to_byte( 0xa5 );
+
+ EXPECT( ( b & b ) == b );
+ EXPECT( ( b & to_byte( 0xff ) ) == b );
+ EXPECT( ( b & to_byte( 0x00 ) ) == to_byte( 0x00 ) );
+}
+
+CASE( "byte: Allows bitwise x-or operation" )
+{
+ gsl_lite::byte const b = to_byte( 0xa5 );
+
+ EXPECT( ( b ^ b ) == to_byte( 0 ) );
+ EXPECT( ( b ^ to_byte( 0x00 ) ) == b );
+ EXPECT( ( b ^ to_byte( 0xff ) ) == ~b );
+}
+
+CASE( "byte: Allows bitwise or assignment" )
+{
+ SETUP("") {
+
+ gsl_lite::byte const b_org = to_byte( 0xa5 );
+ gsl_lite::byte b = b_org;
+
+ SECTION("Identity") { EXPECT( ( b |= b ) == b_org ); }
+ SECTION("Identity") { EXPECT( ( b |= to_byte( 0x00 ) ) == b_org ); }
+ SECTION("Saturate") { EXPECT( ( b |= to_byte( 0xff ) ) == to_byte( 0xff ) ); }
+ }
+}
+
+CASE( "byte: Allows bitwise and assignment" )
+{
+ SETUP("") {
+
+ gsl_lite::byte const b_org = to_byte( 0xa5 );
+ gsl_lite::byte b = b_org;
+
+ SECTION("Identity") { EXPECT( ( b &= b ) == b_org ); }
+ SECTION("Identity") { EXPECT( ( b &= to_byte( 0xff ) ) == b_org ); }
+ SECTION("Clear" ) { EXPECT( ( b &= to_byte( 0x00 ) ) == to_byte( 0x00 ) ); }
+ }
+}
+
+CASE( "byte: Allows bitwise x-or assignment" )
+{
+ SETUP("") {
+
+ gsl_lite::byte const b_org = to_byte( 0xa5 );
+ gsl_lite::byte b = b_org;
+
+ SECTION("Identity") { EXPECT( ( b ^= b ) == to_byte( 0 ) ); }
+ SECTION("Identity") { EXPECT( ( b ^= to_byte( 0x00 ) ) == b_org ); }
+ SECTION("Invert" ) { EXPECT( ( b ^= to_byte( 0xff ) ) == ~b_org ); }
+ }
+}
+
+CASE( "byte: Allows shift-left operation" )
+{
+ gsl_lite::byte const b = to_byte( 0xa5 );
+
+ EXPECT( ( b << 3 ) == to_byte( to_uchar( b ) << 3 ) );
+}
+
+CASE( "byte: Allows shift-right operation" )
+{
+ gsl_lite::byte const b = to_byte( 0xa5 );
+
+ EXPECT( ( b >> 3 ) == to_byte( to_uchar( b ) >> 3 ) );
+}
+
+CASE( "byte: Allows shift-left assignment" )
+{
+ gsl_lite::byte const b_org = to_byte( 0xa5 );
+ gsl_lite::byte b = b_org;
+
+ EXPECT( ( b <<= 3 ) == to_byte( to_uchar( b_org ) << 3 ) );
+}
+
+CASE( "byte: Allows shift-right assignment" )
+{
+ gsl_lite::byte const b_org = to_byte( 0xa5 );
+ gsl_lite::byte b = b_org;
+
+ EXPECT( ( b >>= 3 ) == to_byte( to_uchar( b_org ) >> 3 ) );
+}
+
+CASE( "byte: Provides constexpr non-assignment operations (C++11)" )
+{
+# if gsl_HAVE( CONSTEXPR_11 )
+ static_assert( to_byte( 0xa5 ) == to_byte( 0xa5 ) , "" );
+ static_assert( 0xa5 == to_integer<int>( to_byte( 0xa5 ) ), "" );
+
+ static_assert( to_byte( 0x02 ) == ( to_byte( 0x01 ) << 1 ), "" );
+ static_assert( to_byte( 0x01 ) == ( to_byte( 0x02 ) >> 1 ), "" );
+
+ static_assert( to_byte( 0x01 ) == ( to_byte( 0x03 ) & to_byte( 0x01 ) ), "" );
+ static_assert( to_byte( 0x01 ) == ( to_byte( 0x00 ) | to_byte( 0x01 ) ), "" );
+ static_assert( to_byte( 0x00 ) == ( to_byte( 0x01 ) ^ to_byte( 0x01 ) ), "" );
+
+ static_assert( to_byte( 0xff ) == ~to_byte( 0x00 ), "" );
+# endif
+}
+
+CASE( "byte: Provides constexpr assignment operations (C++14)" )
+{
+# if gsl_HAVE( CONSTEXPR_14 )
+// ...
+# endif
+}
+
+CASE( "byte: Provides hash support (C++11)" )
+{
+# if gsl_HAVE( HASH )
+ EXPECT_NO_THROW( (void) std::hash<gsl_lite::byte>{}( to_byte( 42 ) ) );
+# else
+ EXPECT( !!"hash support is not available (no C++11)" );
+# endif
+}
+#endif // gsl_FEATURE( BYTE )
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/core_check.t.cpp b/thirdparty/gsl-lite/test/core_check.t.cpp
new file mode 100644
index 000000000..ad0ae00f6
--- /dev/null
+++ b/thirdparty/gsl-lite/test/core_check.t.cpp
@@ -0,0 +1,85 @@
+
+#include <tuple> // for ignore
+#include <vector>
+#include <type_traits>
+#include <string_view>
+
+#include <gsl/gsl-lite.hpp>
+
+
+// Cf. https://docs.microsoft.com/en-us/cpp/code-quality/code-analysis-for-cpp-corecheck for a list of warnings in the MSVC
+// C++ Core Guidelines Checker.
+
+
+namespace {
+
+std::string_view get_string_view() noexcept { return "hi"; }
+gsl::span<int const> get_span() noexcept { return { }; }
+gsl_lite::span<int const> get_span2() noexcept { return { }; }
+void get_span_ref() noexcept
+{
+ auto const & sv_ref = get_string_view(); // expect C26445
+ std::ignore = sv_ref;
+ auto const & span_ref = get_span(); // expect C26445
+ std::ignore = span_ref;
+ auto const & span2_ref = get_span2(); // expect C26445
+ std::ignore = span2_ref;
+}
+
+std::vector<int> get_vector(gsl::span<int const>) noexcept { return { }; }
+void assign_temporary_span() noexcept
+{
+ auto span = get_span();
+ span = get_vector(span); // expect C26449
+}
+
+void test_not_null_for_null()
+{
+ int i = 0;
+ gsl::not_null<int*> const pi(&i);
+ std::ignore = pi;
+ //std::ignore = pi == nullptr; // expect C26431 (does not compile for gsl-lite)
+ gsl_lite::not_null<int*> const pi2(&i);
+ std::ignore = pi2;
+ //std::ignore = pi2 == nullptr; // expect C26431 (does not compile for gsl-lite)
+}
+
+int dereference(int const* pi) noexcept // expect C26429
+{
+ return *pi;
+}
+int dereferenceNotNull(gsl::not_null<int const*> pi)
+{
+ return *pi;
+}
+int dereferenceNotNull2(gsl_lite::not_null<int const*> pi)
+{
+ return *pi;
+}
+int dereferenceNotNull3(int const* pi)
+{
+ Expects(pi != nullptr);
+ return *pi;
+}
+
+int* newInt() noexcept { return nullptr; }
+gsl::owner<int*> newIntOwner() noexcept { return nullptr; }
+gsl_lite::owner<int*> newIntOwner2() noexcept { return nullptr; }
+void newDelete() noexcept
+{
+ int* pi = newInt();
+ [[gsl::suppress(r.11)]] delete pi; // expect C26401
+ gsl::owner<int*> pi2 = newInt(); // expect C26406
+ std::ignore = pi2;
+ gsl::owner<int*> pi3 = newIntOwner();
+ [[gsl::suppress(r.11)]] delete pi3;
+ gsl_lite::owner<int*> pi4 = newIntOwner2();
+ [[gsl::suppress(r.11)]] delete pi4;
+}
+
+} // anonymous namespace
+
+
+int main() noexcept
+{
+}
diff --git a/thirdparty/gsl-lite/test/core_check_lite.t.cpp b/thirdparty/gsl-lite/test/core_check_lite.t.cpp
new file mode 100644
index 000000000..fde522f31
--- /dev/null
+++ b/thirdparty/gsl-lite/test/core_check_lite.t.cpp
@@ -0,0 +1,74 @@
+
+#include <tuple> // for ignore
+#include <vector>
+#include <type_traits>
+#include <string_view>
+
+#include <gsl-lite/gsl-lite.hpp>
+
+
+// Cf. https://docs.microsoft.com/en-us/cpp/code-quality/code-analysis-for-cpp-corecheck for a list of warnings in the MSVC
+// C++ Core Guidelines Checker.
+
+
+namespace {
+
+std::string_view get_string_view() noexcept { return "hi"; }
+gsl_lite::span<int const> get_span() noexcept { return { }; }
+void get_span_ref() noexcept
+{
+ auto const & sv_ref = get_string_view(); // expect C26445
+ std::ignore = sv_ref;
+ auto const & span_ref = get_span(); // expect C26445
+ std::ignore = span_ref;
+}
+
+std::vector<int> get_vector(gsl_lite::span<int const>) noexcept { return { }; }
+void assign_temporary_span() noexcept
+{
+ auto span = get_span();
+ span = get_vector(span); // expect C26449
+}
+
+void test_not_null_for_null()
+{
+ int i = 0;
+ gsl_lite::not_null<int*> const pi(&i);
+ std::ignore = pi;
+ //std::ignore = pi == nullptr; // expect C26431 (does not compile for gsl-lite)
+ gsl_lite::not_null<int*> const pi2(&i);
+ std::ignore = pi2;
+ //std::ignore = pi2 == nullptr; // expect C26431 (does not compile for gsl-lite)
+}
+
+int dereference(int const* pi) noexcept // expect C26429
+{
+ return *pi;
+}
+int dereferenceNotNull(gsl_lite::not_null<int const*> pi)
+{
+ return *pi;
+}
+int dereferenceNotNull2(gsl_lite::not_null<int const*> pi)
+{
+ return *pi;
+}
+int dereferenceNotNull3(int const* pi)
+{
+ Expects(pi != nullptr);
+ return *pi;
+}
+
+int* newInt() noexcept { return nullptr; }
+gsl_lite::owner<int*> newIntOwner() noexcept { return nullptr; }
+void newDelete() noexcept
+{
+ int* pi = newInt();
+ [[gsl::suppress(r.11)]] delete pi; // expect C26401
+ gsl_lite::owner<int*> pi2 = newInt(); // expect C26406
+ std::ignore = pi2;
+ gsl_lite::owner<int*> pi3 = newIntOwner();
+ [[gsl::suppress(r.11)]] delete pi3;
+}
+
+} // anonymous namespace
diff --git a/thirdparty/gsl-lite/test/cuda/cuda.t.cu b/thirdparty/gsl-lite/test/cuda/cuda.t.cu
new file mode 100644
index 000000000..0826a1f01
--- /dev/null
+++ b/thirdparty/gsl-lite/test/cuda/cuda.t.cu
@@ -0,0 +1,176 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/martinmoene/gsl-lite
+//
+// Copyright (c) 2015 Martin Moene
+// Copyright (c) 2019-2025 Moritz Beutel
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "../gsl-lite.t.hpp"
+
+#include <memory>
+#include <sstream>
+
+
+// CUDA error checking macro borrowed from https://stackoverflow.com/a/14038590 and adapted.
+#define myCudaErrchk(ans) ( myCudaErrchkImpl( (ans), #ans, __FILE__, __LINE__ ) )
+inline void myCudaErrchkImpl( cudaError_t code, char const * expr, char const * file, int line )
+{
+ if ( code != cudaSuccess )
+ {
+ std::ostringstream sstr;
+ sstr << "CUDA error in '" << expr << "' at " << file << "(" << line << "): "
+ << cudaGetErrorString( code );
+ throw std::runtime_error( sstr.str() );
+ }
+}
+
+
+struct CudaMallocDeleter
+{
+ template< class T >
+ void operator ()( T* data ) const
+ {
+ cudaFree( data );
+ }
+};
+
+template< class T >
+using CudaUniquePtr = std::unique_ptr<T, CudaMallocDeleter>;
+
+template< class T >
+struct CudaAllocHelper
+{
+ static CudaUniquePtr<T> cudaAllocUnique()
+ {
+ T* ptr;
+ auto ec = cudaMalloc( &ptr, sizeof( T ) );
+ if ( ec != cudaSuccess ) throw std::bad_alloc{ };
+ return CudaUniquePtr<T>( ptr );
+ }
+};
+template< class T >
+struct CudaAllocHelper<T[]>
+{
+ static CudaUniquePtr<T[]> cudaAllocUnique( std::size_t n )
+ {
+ T* ptr;
+ auto ec = cudaMalloc( &ptr, sizeof( T ) * n );
+ if ( ec != cudaSuccess ) throw std::bad_alloc{ };
+ return CudaUniquePtr<T[]>( ptr );
+ }
+};
+template< class T >
+CudaUniquePtr<T> cudaAllocUnique()
+{
+ return CudaAllocHelper<T>::cudaAllocUnique();
+}
+template< class T >
+CudaUniquePtr<T> cudaAllocUnique( std::size_t n )
+{
+ return CudaAllocHelper<T>::cudaAllocUnique(n);
+}
+
+
+__global__ void preconditionAssertionKernel( int i, int j )
+{
+ gsl_Expects( i >= 0 );
+ gsl_ExpectsAudit( i < j );
+ gsl_Ensures( i >= 0 );
+ gsl_EnsuresAudit( i < j );
+ gsl_Assert( i >= 0 );
+ gsl_AssertAudit( i < j );
+}
+
+CASE( "CUDA: Precondition/postcondition checks and assertions can be used in kernel code" )
+{
+ preconditionAssertionKernel<<<1, 1>>>( 0, 1 );
+ myCudaErrchk( cudaPeekAtLastError() ); // check for invalid launch arguments
+ myCudaErrchk( cudaDeviceSynchronize() ); // check for execution errors
+}
+
+
+__global__ void spanKernel( gsl_lite::span< int > span )
+{
+ int* data = span.data();
+ gsl_CONFIG_SPAN_INDEX_TYPE size = span.size();
+ if (size > 0)
+ {
+ span[0] = 42;
+ at( span, 0 ) = 42;
+ }
+}
+
+CASE( "CUDA: span<> can be passed to kernel code" )
+{
+ spanKernel<<<1, 1>>>( gsl_lite::span< int >( ) );
+ myCudaErrchk( cudaPeekAtLastError() ); // check for invalid launch arguments
+ myCudaErrchk( cudaDeviceSynchronize() ); // check for execution errors
+}
+
+CASE( "CUDA: span<> can be used in kernel code" )
+{
+ std::size_t n = 3;
+ auto array = cudaAllocUnique<int[]>(n);
+ auto span = gsl_lite::make_span(array.get(), n);
+ spanKernel<<<1, 1>>>( span );
+ myCudaErrchk( cudaPeekAtLastError() ); // check for invalid launch arguments
+ myCudaErrchk( cudaDeviceSynchronize() ); // check for execution errors
+}
+
+
+__global__ void notNullRawKernel( gsl_lite::not_null< int* > ptr )
+{
+ *ptr = 1;
+ auto ptr2 = ptr;
+ *ptr2 = 2;
+ ptr = ptr2;
+}
+
+// Not supported yet because `std::unique_ptr<>` member functions are neither `constexpr` nor `__host__ __device__`.
+//__global__ void notNullUniqueKernel( gsl_lite::not_null< CudaUniquePtr< int > > ptr )
+//{
+// *ptr = 3;
+// auto ptr2 = std::move( ptr );
+// *ptr2 = 4;
+// ptr = std::move( ptr2 );
+//}
+
+CASE( "CUDA: not_null<> can be passed to and used in kernel code" )
+{
+ auto pi = cudaAllocUnique<int>();
+
+ notNullRawKernel<<<1, 1>>>( gsl_lite::make_not_null( pi.get() ) );
+ myCudaErrchk( cudaPeekAtLastError() ); // check for invalid launch arguments
+ myCudaErrchk( cudaDeviceSynchronize() ); // check for execution errors
+
+ //notNullUniqueKernel<<<1, 1>>>( gsl_lite::make_not_null( std::move( pi ) ) );
+ //myCudaErrchk( cudaPeekAtLastError() ); // check for invalid launch arguments
+ //myCudaErrchk( cudaDeviceSynchronize() ); // check for execution errors
+}
+
+
+__global__ void failFastKernel()
+{
+ gsl_FailFast();
+}
+
+CASE( "CUDA: gsl_FailFast() can be used in kernel code" )
+{
+ failFastKernel<<<1, 1>>>();
+ myCudaErrchk( cudaPeekAtLastError() );
+ EXPECT( cudaDeviceSynchronize() != cudaSuccess );
+ // Note that executing a trap instruction or an assertion in a CUDA kernel destroys the context, so this should be
+ // the last test case we execute.
+}
+
diff --git a/thirdparty/gsl-lite/test/emulation.t.cpp b/thirdparty/gsl-lite/test/emulation.t.cpp
new file mode 100644
index 000000000..8d9ec4445
--- /dev/null
+++ b/thirdparty/gsl-lite/test/emulation.t.cpp
@@ -0,0 +1,121 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#include "gsl-lite.t.hpp"
+
+using namespace gsl_lite;
+
+
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( VARIADIC_TEMPLATE )
+template <int> struct True : std::true_type { };
+template <int> struct False : std::false_type { };
+
+struct Incomplete;
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( VARIADIC_TEMPLATE )
+
+
+#if gsl_FEATURE( STRING_SPAN ) || gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+CASE( "equal()" )
+{
+ char const* arg1 = "foo";
+ char const* arg2 = "fou";
+ EXPECT( detail::equal( arg1, arg1 + std::strlen( arg1 ), arg1 ) );
+ EXPECT( ! detail::equal( arg1, arg1 + std::strlen( arg1 ), arg2 ) );
+ EXPECT( ! detail::equal( arg2, arg2 + std::strlen( arg2 ), arg1 ) );
+
+ std::istringstream sstr1a1( "foo" ), sstr1a2( "foo" ), sstr1b( "foo" ), sstr1c( "foo" );
+ std::istringstream sstr2b( "fou" ), sstr2c( "fou" );
+ EXPECT( detail::equal( std::istreambuf_iterator<char>( sstr1a1 ), std::istreambuf_iterator<char>(), std::istreambuf_iterator<char>( sstr1a2 ) ) );
+ EXPECT( ! detail::equal( std::istreambuf_iterator<char>( sstr1b ), std::istreambuf_iterator<char>(), std::istreambuf_iterator<char>( sstr2b ) ) );
+ EXPECT( ! detail::equal( std::istreambuf_iterator<char>( sstr2c ), std::istreambuf_iterator<char>(), std::istreambuf_iterator<char>( sstr1c ) ) );
+}
+
+template < typename T, std::size_t N >
+std::size_t arraySize( T (&)[N] )
+{
+ return N;
+}
+
+CASE( "lexicographical_compare()" )
+{
+ std::pair<char const*, char const*> less[] = {
+ std::make_pair("", "foo"),
+ std::make_pair("fa", "foo"),
+ std::make_pair("foe", "foo"),
+ std::make_pair("fond", "foo")
+ };
+ for ( std::size_t i = 0, n = arraySize( less ); i != n; ++i )
+ {
+ EXPECT( detail::lexicographical_compare( less[i].first, less[i].first + std::strlen( less[i].first ), less[i].second, less[i].second + std::strlen( less[i].second ) ));
+
+ std::istringstream sstr1( less[i].first );
+ std::istringstream sstr2( less[i].second );
+ std::istreambuf_iterator<char> it1( sstr1 ), it1End;
+ std::istreambuf_iterator<char> it2( sstr2 ), it2End;
+ EXPECT( detail::lexicographical_compare( it1, it1End, it2, it2End ));
+ }
+
+ std::pair<char const*, char const*> notLess[] = {
+ std::make_pair("g", "foo"),
+ std::make_pair("fu", "foo"),
+ std::make_pair("foo", "foo"),
+ std::make_pair("fou", "foo"),
+ std::make_pair("fool", "foo"),
+ std::make_pair("foul", "foo")
+ };
+ for ( std::size_t i = 0, n = arraySize( less ); i != n; ++i )
+ {
+ EXPECT( ! detail::lexicographical_compare( notLess[i].first, notLess[i].first + std::strlen( notLess[i].first ), notLess[i].second, notLess[i].second + std::strlen( notLess[i].second ) ));
+
+ std::istringstream sstr1( notLess[i].first );
+ std::istringstream sstr2( notLess[i].second );
+ std::istreambuf_iterator<char> it1( sstr1 ), it1End;
+ std::istreambuf_iterator<char> it2( sstr2 ), it2End;
+ EXPECT( ! detail::lexicographical_compare( it1, it1End, it2, it2End ));
+ }
+}
+#endif // gsl_FEATURE( STRING_SPAN ) || gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+
+CASE( "conjunction<> and disjunction<>: Short-circuiting is handled correctly" )
+{
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( VARIADIC_TEMPLATE )
+ static_assert(std::is_base_of<True<0>, std17::disjunction<True<0>, Incomplete>>::value, "static assertion failed");
+ static_assert(std::is_base_of<False<0>, std17::conjunction<False<0>, Incomplete>>::value, "static assertion failed");
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( VARIADIC_TEMPLATE )
+}
+
+CASE( "conjunction<> and disjunction<>: First suitable type is chosen as base" )
+{
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( VARIADIC_TEMPLATE )
+ static_assert(std::is_base_of<std::false_type, std17::disjunction<>>::value, "static assertion failed");
+ static_assert(std::is_base_of<True<0>, std17::disjunction<True<0>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<False<0>, std17::disjunction<False<0>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<True<0>, std17::disjunction<True<0>, True<1>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<True<0>, std17::disjunction<True<0>, True<1>, True<2>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<True<1>, std17::disjunction<False<0>, True<1>, True<2>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<False<2>, std17::disjunction<False<0>, False<1>, False<2>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<std::true_type, std17::conjunction<>>::value, "static assertion failed");
+ static_assert(std::is_base_of<True<0>, std17::conjunction<True<0>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<False<0>, std17::conjunction<False<0>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<True<1>, std17::conjunction<True<0>, True<1>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<True<2>, std17::conjunction<True<0>, True<1>, True<2>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<False<1>, std17::conjunction<True<0>, False<1>, False<2>>>::value, "static assertion failed");
+ static_assert(std::is_base_of<False<0>, std17::conjunction<False<0>, False<1>, False<2>>>::value, "static assertion failed");
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( VARIADIC_TEMPLATE )
+}
diff --git a/thirdparty/gsl-lite/test/gsl-lite.t.cpp b/thirdparty/gsl-lite/test/gsl-lite.t.cpp
new file mode 100644
index 000000000..24346989f
--- /dev/null
+++ b/thirdparty/gsl-lite/test/gsl-lite.t.cpp
@@ -0,0 +1,298 @@
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// This code is licensed under the MIT License (MIT).
+//
+
+#include "gsl-lite.t.hpp"
+
+#define gsl_PRINT_NUMERIC( x ) \
+ std::cout << #x << ": " << x << "\n"
+
+#define gsl_PRINT_BOOLEAN( x ) \
+ std::cout << #x << ": " << x << "\n"
+
+#define gsl_PRINT_TOKEN( x ) \
+ std::cout << #x << ": " << gsl_STRINGIFY(x) << "\n"
+
+#define gsl_PRESENT( x ) \
+ std::cout << #x << ": (defined)" << "\n"
+
+#define gsl_ABSENT( x ) \
+ std::cout << #x << ": (undefined)\n"
+
+#define gsl_PRINT_NO_VALUE( x ) \
+ std::cout << #x << ": (no value)\n"
+
+lest::tests & specification()
+{
+ static lest::tests tests;
+ return tests;
+}
+
+CASE( "gsl-lite version" "[.version]" )
+{
+ gsl_PRINT_NUMERIC( gsl_lite_VERSION );
+}
+
+CASE( "C++ compiler: compiler version" "[.compiler]" )
+{
+ gsl_PRINT_NUMERIC( gsl_COMPILER_APPLECLANG_VERSION );
+ gsl_PRINT_NUMERIC( gsl_COMPILER_CLANG_VERSION );
+ gsl_PRINT_NUMERIC( gsl_COMPILER_GNUC_VERSION );
+ gsl_PRINT_NUMERIC( gsl_COMPILER_MSVC_VERSION );
+}
+
+CASE( "__cplusplus" "[.stdc++]" )
+{
+ gsl_PRINT_NUMERIC( __cplusplus );
+ gsl_PRINT_NUMERIC( gsl_CPLUSPLUS );
+}
+
+CASE( "_MSVC_LANG" "[.stdc++]" )
+{
+#ifdef _MSVC_LANG
+ gsl_PRINT_NUMERIC( _MSVC_LANG );
+#else
+ gsl_ABSENT( _MSVC_LANG );
+#endif
+}
+
+CASE( "gsl_CPP11_OR_GREATER" "[.stdc++]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_CPP11_OR_GREATER );
+}
+
+CASE( "gsl_CPP14_OR_GREATER" "[.stdc++]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_CPP14_OR_GREATER );
+}
+
+CASE( "gsl_CPP17_OR_GREATER" "[.stdc++]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_CPP17_OR_GREATER );
+}
+
+CASE( "gsl_CPP20_OR_GREATER" "[.stdc++]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_CPP20_OR_GREATER );
+}
+
+CASE( "gsl_STDLIB_CPP11_OR_GREATER" "[.stdc++]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_STDLIB_CPP11_OR_GREATER );
+}
+
+CASE( "gsl_STDLIB_CPP14_OR_GREATER" "[.stdc++]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_STDLIB_CPP14_OR_GREATER );
+}
+
+CASE( "gsl_STDLIB_CPP17_OR_GREATER" "[.stdc++]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_STDLIB_CPP17_OR_GREATER );
+}
+
+CASE( "gsl_STDLIB_CPP20_OR_GREATER" "[.stdc++]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_STDLIB_CPP20_OR_GREATER );
+}
+
+CASE( "Presence of C++ language features" "[.stdlanguage]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_HAVE( ALIAS_TEMPLATE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( AUTO ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( CONSTEXPR_11 ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( CONSTEXPR_14 ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( CONSTEXPR_17 ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( CONSTEXPR_20 ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( DECLTYPE_AUTO ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( DEDUCTION_GUIDES ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( DEPRECATED ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( ENUM_CLASS ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( EXCEPTIONS ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( EXPLICIT ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( EXPRESSION_SFINAE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( FUNCTION_REF_QUALIFIER ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( INITIALIZER_LIST ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( IS_DEFAULT ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( IS_DELETE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( NODISCARD ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( NOEXCEPT ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( NORETURN ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( NULLPTR ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( RVALUE_REFERENCE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( VARIADIC_TEMPLATE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( WCHAR ) );
+}
+
+CASE( "Presence of C++ library features" "[.stdlibrary]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_HAVE( ADD_CONST ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( ADDRESSOF ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( ARRAY ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( CONTAINER_DATA_METHOD ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( INTEGRAL_CONSTANT ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( HASH ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( MAKE_SHARED ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( MAKE_UNIQUE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( MOVE_FORWARD ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( REMOVE_CONST ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( REMOVE_CVREF ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( REMOVE_REFERENCE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( SHARED_PTR ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( SIZED_TYPES ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( STD_DATA ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( TR1_ADD_CONST ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( TR1_INTEGRAL_CONSTANT ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( TR1_REMOVE_CONST ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( TR1_REMOVE_REFERENCE ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( TR1_TYPE_TRAITS ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( TYPE_TRAITS ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( UNCAUGHT_EXCEPTIONS ) );
+ gsl_PRINT_BOOLEAN( gsl_HAVE( UNIQUE_PTR ) );
+
+#ifdef _HAS_CPP0X
+ gsl_PRINT_BOOLEAN( _HAS_CPP0X );
+#else
+ gsl_ABSENT( _HAS_CPP0X );
+#endif
+}
+
+CASE( "gsl-lite configuration" "[.gsl-configuration]" )
+{
+//#if gsl_CHECK_CFG_NO_VALUE_( gsl_api )
+// gsl_PRINT_NO_VALUE( gsl_api );
+//#else
+// gsl_PRINT_TOKEN( gsl_api );
+//#endif
+
+#ifdef gsl_CONFIG_CONTRACT_CHECKING_AUDIT
+ gsl_PRESENT( gsl_CONFIG_CONTRACT_CHECKING_AUDIT );
+#else
+ gsl_ABSENT( gsl_CONFIG_CONTRACT_CHECKING_AUDIT );
+#endif
+
+#ifdef gsl_CONFIG_CONTRACT_CHECKING_ON
+ gsl_PRESENT( gsl_CONFIG_CONTRACT_CHECKING_ON );
+#else
+ gsl_ABSENT( gsl_CONFIG_CONTRACT_CHECKING_ON );
+#endif
+
+#ifdef gsl_CONFIG_CONTRACT_CHECKING_OFF
+ gsl_PRESENT( gsl_CONFIG_CONTRACT_CHECKING_OFF );
+#else
+ gsl_ABSENT( gsl_CONFIG_CONTRACT_CHECKING_OFF );
+#endif
+
+#ifdef gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF
+ gsl_PRESENT( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF );
+#else
+ gsl_ABSENT( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF );
+#endif
+
+#ifdef gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF
+ gsl_PRESENT( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF );
+#else
+ gsl_ABSENT( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF );
+#endif
+
+#ifdef gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME
+ gsl_PRESENT( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME );
+#else
+ gsl_ABSENT( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME );
+#endif
+
+#ifdef gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE
+ gsl_PRESENT( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE );
+#else
+ gsl_ABSENT( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE );
+#endif
+
+#ifdef gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES
+ gsl_PRESENT( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES );
+#else
+ gsl_ABSENT( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES );
+#endif
+
+#ifdef gsl_CONFIG_CONTRACT_VIOLATION_THROWS
+ gsl_PRESENT( gsl_CONFIG_CONTRACT_VIOLATION_THROWS );
+#else
+ gsl_ABSENT( gsl_CONFIG_CONTRACT_VIOLATION_THROWS );
+#endif
+
+#ifdef gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER
+ gsl_PRESENT( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER );
+#else
+ gsl_ABSENT( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER );
+#endif
+
+ gsl_PRINT_BOOLEAN( gsl_CONFIG( TRANSPARENT_NOT_NULL ) );
+ gsl_PRINT_BOOLEAN( gsl_CONFIG_DEPRECATE_TO_LEVEL );
+ gsl_PRINT_TOKEN( gsl_CONFIG( SPAN_INDEX_TYPE ) );
+ gsl_PRINT_TOKEN( gsl_CONFIG( INDEX_TYPE ) );
+ gsl_PRINT_BOOLEAN( gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR ) );
+ gsl_PRINT_BOOLEAN( gsl_CONFIG( NOT_NULL_GET_BY_CONST_REF ) );
+ gsl_PRINT_BOOLEAN( gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS ) );
+ gsl_PRINT_BOOLEAN( gsl_CONFIG( ALLOWS_SPAN_COMPARISON ) );
+ gsl_PRINT_BOOLEAN( gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON ) );
+ gsl_PRINT_BOOLEAN( gsl_CONFIG( ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR ) );
+ gsl_PRINT_BOOLEAN( gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION ) );
+}
+
+CASE( "gsl-lite features" "[.gsl-features]" )
+{
+ gsl_PRINT_BOOLEAN( gsl_FEATURE( WITH_CONTAINER_TO_STD ) );
+ gsl_PRINT_BOOLEAN( gsl_FEATURE( MAKE_SPAN_TO_STD ) );
+ gsl_PRINT_BOOLEAN( gsl_FEATURE( BYTE_SPAN_TO_STD ) );
+ gsl_PRINT_BOOLEAN( gsl_FEATURE( IMPLICIT_MACRO ) );
+ gsl_PRINT_BOOLEAN( gsl_FEATURE( OWNER_MACRO ) );
+ gsl_PRINT_BOOLEAN( gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD ) );
+ gsl_PRINT_BOOLEAN( gsl_FEATURE( GSL_LITE_NAMESPACE ) );
+}
+
+int main( int argc, char * argv[] )
+{
+ // We only run tests for targets with exceptions enabled. lest has been modified to permit compilation without exceptions
+ // so we can test compiling gsl-lite without exceptions, but the no-exception tests will not run correctly because lest
+ // relies on exceptions for running tests and therefore cannot function correctly without.
+ if ( ! gsl_HAVE( EXCEPTIONS ) )
+ {
+ std::cerr << "Cannot run test suite with exceptions disabled; exiting.\n";
+ return 1;
+ }
+
+ return lest::run( specification(), argc, argv );
+}
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+namespace gsl_lite {
+
+gsl_api void fail_fast_assert_handler( char const * const expression, char const * const message, char const * const file, int line )
+{
+ std::cerr << message << ": " << expression << " at " << file << ":" << line << "\n";
+}
+
+} // namespace gsl_lite
+#endif
+
+#if 0
+g++ -I../include/gsl -Dgsl_CONFIG_CONTRACT_VIOLATION_THROWS -o gsl-lite.t.exe gsl-lite.t.cpp assert.t.cpp at.t.cpp byte.t.cpp issue.t.cpp not_null.t.cpp owner.t.cpp span.t.cpp string_span.t.cpp util.t.cpp && gsl-lite.t.exe --pass
+g++ -std=c++98 -I../include/gsl -Dgsl_CONFIG_CONTRACT_VIOLATION_THROWS -o gsl-lite.t.exe gsl-lite.t.cpp assert.t.cpp at.t.cpp byte.t.cpp issue.t.cpp not_null.t.cpp owner.t.cpp span.t.cpp string_span.t.cpp util.t.cpp && gsl-lite.t.exe --pass
+g++ -std=c++03 -I../include/gsl -Dgsl_CONFIG_CONTRACT_VIOLATION_THROWS -o gsl-lite.t.exe gsl-lite.t.cpp assert.t.cpp at.t.cpp byte.t.cpp issue.t.cpp not_null.t.cpp owner.t.cpp span.t.cpp string_span.t.cpp util.t.cpp && gsl-lite.t.exe --pass
+g++ -std=c++0x -I../include/gsl -Dgsl_CONFIG_CONTRACT_VIOLATION_THROWS -o gsl-lite.t.exe gsl-lite.t.cpp assert.t.cpp at.t.cpp byte.t.cpp issue.t.cpp not_null.t.cpp owner.t.cpp span.t.cpp string_span.t.cpp util.t.cpp && gsl-lite.t.exe --pass
+g++ -std=c++11 -I../include/gsl -Dgsl_CONFIG_CONTRACT_VIOLATION_THROWS -o gsl-lite.t.exe gsl-lite.t.cpp assert.t.cpp at.t.cpp byte.t.cpp issue.t.cpp not_null.t.cpp owner.t.cpp span.t.cpp string_span.t.cpp util.t.cpp && gsl-lite.t.exe --pass
+g++ -std=c++14 -I../include/gsl -Dgsl_CONFIG_CONTRACT_VIOLATION_THROWS -o gsl-lite.t.exe gsl-lite.t.cpp assert.t.cpp at.t.cpp byte.t.cpp issue.t.cpp not_null.t.cpp owner.t.cpp span.t.cpp string_span.t.cpp util.t.cpp && gsl-lite.t.exe --pass
+
+cl -EHsc -I../include/gsl -Dgsl_CONFIG_CONTRACT_VIOLATION_THROWS gsl-lite.t.cpp assert.t.cpp at.t.cpp byte.t.cpp issue.t.cpp not_null.t.cpp owner.t.cpp span.t.cpp string_span.t.cpp util.t.cpp && gsl-lite.t.exe --pass
+
+cl -EHsc -I../include/gsl -Dgsl_CONFIG_CONTRACT_VIOLATION_THROWS -Dgsl_CONFIG_CONFIRMS_COMPILATION_ERRORS gsl-lite.t.cpp assert.t.cpp at.t.cpp byte.t.cpp issue.t.cpp not_null.t.cpp owner.t.cpp span.t.cpp string_span.t.cpp util.t.cpp && gsl-lite.t.exe --pass
+#endif
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/gsl-lite.t.hpp b/thirdparty/gsl-lite/test/gsl-lite.t.hpp
new file mode 100644
index 000000000..aeb2271ef
--- /dev/null
+++ b/thirdparty/gsl-lite/test/gsl-lite.t.hpp
@@ -0,0 +1,149 @@
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// This code is licensed under the MIT License (MIT).
+//
+
+#ifndef GSL_TEST_GSL_LITE_HPP_INCLUDED
+#define GSL_TEST_GSL_LITE_HPP_INCLUDED
+
+
+#include "gsl-lite/gsl-lite.hpp"
+
+
+// gsl-lite only depends on <ios>, but we're instantiating templates using streams, so we need <ostream>.
+#include <ostream>
+
+// Some test cases use stringstreams and other iostream functionality.
+#include <sstream>
+#include <iostream>
+
+// Additional general requirements.
+#include <cstring>
+
+
+// Limit C++ Core Guidelines checking to GSL Lite:
+
+#ifdef gsl_TESTING_CPPCORECHECK_
+# include <CppCoreCheck/warnings.h>
+# pragma warning(disable: ALL_CPPCORECHECK_WARNINGS)
+#endif
+
+// Compiler warning suppression for usage of lest:
+
+#ifdef __clang__
+# pragma clang diagnostic ignored "-Wunknown-pragmas" // don't warn if any of the following warnings are introduced later than the current compiler version
+# pragma clang diagnostic ignored "-Wunknown-warning-option" // see above, but for newer compilers
+# pragma clang diagnostic ignored "-Wstring-conversion"
+# pragma clang diagnostic ignored "-Wunused-parameter"
+# pragma clang diagnostic ignored "-Wunused-template"
+# pragma clang diagnostic ignored "-Wunused-function"
+# pragma clang diagnostic ignored "-Wunused-member-function"
+# pragma clang diagnostic warning "-Wunknown-warning-option" // we want to see warnings about unknown warning options
+# pragma clang diagnostic warning "-Wunknown-pragmas" // we want to see warnings about unknown pragmas
+# pragma GCC diagnostic ignored "-Wweak-vtables"
+#elif defined( __GNUC__ )
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+# pragma GCC diagnostic ignored "-Wunused-function"
+# pragma GCC diagnostic ignored "-Wuseless-cast"
+#elif defined( _MSC_VER )
+# if gsl_BETWEEN(gsl_COMPILER_MSVC_VERSION, 1, 140)
+# pragma warning( disable : 4702 ) // unreachable code
+# pragma warning( disable : 4512 ) // assignment operator could not be generated
+# endif // gsl_BETWEEN(gsl_COMPILER_MSVC_VERSION, 1, 140)
+# if gsl_BETWEEN(gsl_COMPILER_MSVC_VERSION, 1, 142) || !gsl_CPP17_OR_GREATER
+# pragma warning( disable : 4100 ) // unreferenced formal parameter
+# endif // !__has_cpp_attribute(maybe_unused) || !gsl_CPP17_OR_GREATER
+#endif
+
+
+namespace lest {
+
+// These functions cannot be found via ADL, so we have to define them before including lest.
+
+#if gsl_HAVE( ARRAY )
+template< typename T, std::size_t N >
+inline std::ostream & operator<<( std::ostream & os, std::array<T,N> const & )
+{
+ return os << std::hex << "[std::array[" << N << "]";
+}
+#endif
+
+#if gsl_HAVE( WCHAR )
+// We do this with a loop and explicit casts to avoid warnings about implicit narrowing casts (which we don't care about because we don't have to handle non-ASCII strings in the tests).
+inline std::string narrowString( std::wstring const & str )
+{
+ std::string result(str.size(), '\0');
+ for (std::size_t i = 0, n = str.size(); i != n; ++i)
+ {
+ result[i] = static_cast<char>(str[i]);
+ }
+ return result;
+}
+
+inline std::ostream & operator<<( std::ostream & os, std::wstring const & text )
+{
+ return os << narrowString( text );
+}
+#endif // gsl_HAVE( WCHAR )
+
+} // namespace lest
+
+#include "lest_cpp03.hpp"
+
+#define CASE( name ) lest_CASE( specification(), name )
+
+extern lest::tests & specification();
+
+namespace gsl_lite {
+
+inline const void * nullptr_void() { return gsl_nullptr; }
+
+// use operator<< instead of to_string() overload;
+// see http://stackoverflow.com/a/10651752/437272
+
+#if gsl_FEATURE( BYTE )
+inline std::ostream & operator<<( std::ostream & os, byte b )
+{
+ return os << std::hex << "0x" << to_integer<int>(b);
+}
+#endif // gsl_FEATURE( BYTE )
+
+template< typename T, gsl_CONFIG_SPAN_INDEX_TYPE Extent >
+inline std::ostream & operator<<( std::ostream & os, span< T, Extent > s )
+{
+ return os << "[", std::copy( s.begin(), s.end(), std::ostream_iterator<T>(os, ",") ), os << "]";
+}
+
+namespace detail {
+
+template< typename T >
+inline std::ostream & operator<<( std::ostream & os, span_iterator< T > s )
+{
+ return os << s.current_;
+}
+
+template< typename T >
+inline std::ostream & operator<<( std::ostream & os, std::reverse_iterator< span_iterator< T > > s )
+{
+ return os << s.base().current_;
+}
+
+} // namespace detail
+
+} // namespace gsl_lite
+
+# if gsl_FEATURE( STRING_SPAN )
+inline void suppress_warning_unused_template_ensure_sentinel()
+{
+ (void) gsl_lite::ensure_z( "zero-terminated" );
+}
+# endif // gsl_FEATURE( STRING_SPAN )
+
+#endif // GSL_TEST_GSL_LITE_HPP_INCLUDED
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/issue.t.cpp b/thirdparty/gsl-lite/test/issue.t.cpp
new file mode 100644
index 000000000..aa0cd9b7c
--- /dev/null
+++ b/thirdparty/gsl-lite/test/issue.t.cpp
@@ -0,0 +1,140 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+
+using namespace gsl_lite;
+
+CASE( "span<>: free comparation functions fail for different const-ness [issue #32]" )
+{
+#if gsl_FEATURE( STRING_SPAN )
+# if gsl_FEATURE_TO_STD( MAKE_SPAN )
+# if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+ char data[] = { 'a', 'b' };
+ string_span a = make_span( data );
+ cstring_span b = make_span( data ).last( 1 );
+
+ // worked as expected before 0.9.0, in 0.9.[0,1] converts to bool and compares equal!
+
+ EXPECT( a != b );
+# else
+ EXPECT( !!"span<>: cannot compare different types (gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=0)" );
+# endif
+# else
+ EXPECT( !!"span<>: make_span() is not available (gsl_FEATURE_MAKE_SPAN_TO_STD)" );
+# endif
+#endif // gsl_FEATURE( STRING_SPAN )
+}
+
+CASE( "span<>: constrained container constructor suffers hard failure for arguments with reference-returning data() function [issue #242]" )
+{
+#if gsl_FEATURE( BYTE )&& gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && gsl_HAVE( TYPE_TRAITS )
+ struct S
+ {
+ int data_{ };
+
+ explicit S( gsl_lite::span<gsl_lite::byte const> ) { }
+ int const & data() const { return data_; }
+ };
+
+ // S is not a `contiguous_range`, hence the range constructor should not be instantiable, but this needs to be a substitution
+ // failure, not a hard error.
+ EXPECT( !(std::is_constructible< gsl_lite::span< gsl_lite::byte const >, S >::value) );
+#else
+ EXPECT( !!"span<>: constrained container constructor is not available (gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR=0)" );
+#endif
+}
+
+#if gsl_COMPILER_MSVC_VERSION
+# pragma warning( push )
+# pragma warning( disable : 4127 ) // conditional expression is constant
+#endif
+
+CASE( "byte: aliasing rules lead to undefined behaviour when using enum class [issue #34](GSL issue #313, PR #390)" )
+{
+#if gsl_FEATURE( BYTE ) && gsl_HAVE( ENUM_CLASS )
+ struct F {
+ static int f( int & i, gsl_lite::byte & r )
+ {
+ i = 7;
+ r <<= 1;
+ return i;
+ }
+ };
+
+ int i = 0;
+ if ( std20::endian::native == std20::endian::little )
+ {
+ EXPECT( 14 == F::f( i, reinterpret_cast<gsl_lite::byte*>( &i )[0] ) );
+ }
+ else if ( std20::endian::native == std20::endian::big )
+ {
+ EXPECT( 14 == F::f( i, reinterpret_cast<gsl_lite::byte*>( &i )[sizeof i - 1] ) );
+ }
+#endif // gsl_FEATURE( BYTE ) && gsl_HAVE( ENUM_CLASS )
+}
+
+#if gsl_COMPILER_MSVC_VERSION
+# pragma warning( pop )
+#endif
+
+CASE( "string_span<>: must not include terminating '\\0' [issue #53]" )
+{
+#if gsl_FEATURE( STRING_SPAN )
+ char const data[] = "ab";
+ char const * text = "ab";
+ cstring_span span = "ab";
+
+ cstring_span a( data );
+ cstring_span b( ensure_z( text ) );
+
+ // may include terminating '\0'
+ // works differently from M-GSL and basic_string_span proposal:
+
+ EXPECT( span.length() == 2u );
+ EXPECT( a.length() == 2u );
+ EXPECT( b.length() == 2u );
+
+ EXPECT( a == span );
+ EXPECT( a == b );
+#endif // gsl_FEATURE( STRING_SPAN )
+}
+
+CASE( "string_span<>: to_string triggers SFINAE errors on basic_string_span's move & copy constructor with Clang-3.9 (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS) [issue #53a]" )
+{
+# if gsl_FEATURE( STRING_SPAN ) && gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+ cstring_span span = "Hello world";
+ std::string str = to_string( span );
+# endif
+}
+
+CASE( "narrow<>(): Allows narrowing double to float without MSVC level 4 warning C4127: conditional expression is constant [issue #115]" )
+{
+# if gsl_HAVE( EXCEPTIONS )
+ try { (void) narrow<float>( 1.0 ); } catch(...) {}
+# endif // gsl_HAVE( EXCEPTIONS )
+}
+
+CASE( "detail::is_compatible_container<>: Not a proper type trait [PR #238]" )
+{
+#if gsl_HAVE( TYPE_TRAITS ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+ static_assert( std::is_base_of<gsl_lite::std11::false_type, gsl_lite::detail::is_compatible_container< int, int > >::value, "static assertion failed" );
+#endif
+}
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/lest_cpp03.hpp b/thirdparty/gsl-lite/test/lest_cpp03.hpp
new file mode 100644
index 000000000..63167c52c
--- /dev/null
+++ b/thirdparty/gsl-lite/test/lest_cpp03.hpp
@@ -0,0 +1,1646 @@
+// Copyright 2013-2018 by Martin Moene
+//
+// lest is based on ideas by Kevlin Henney, see video at
+// http://skillsmatter.com/podcast/agile-testing/kevlin-henney-rethinking-unit-testing-in-c-plus-plus
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef LEST_LEST_HPP_INCLUDED
+#define LEST_LEST_HPP_INCLUDED
+
+#include <algorithm>
+#include <iomanip>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <sstream>
+#include <stdexcept>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cctype>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <ctime>
+
+#define lest_MAJOR 1
+#define lest_MINOR 35
+#define lest_PATCH 1
+
+#define lest_VERSION lest_STRINGIFY(lest_MAJOR) "." lest_STRINGIFY(lest_MINOR) "." lest_STRINGIFY(lest_PATCH)
+
+#ifndef lest_FEATURE_COLOURISE
+# define lest_FEATURE_COLOURISE 0
+#endif
+
+#ifndef lest_FEATURE_LITERAL_SUFFIX
+# define lest_FEATURE_LITERAL_SUFFIX 0
+#endif
+
+#ifndef lest_FEATURE_REGEX_SEARCH
+# define lest_FEATURE_REGEX_SEARCH 0
+#endif
+
+#ifndef lest_FEATURE_TIME
+# define lest_FEATURE_TIME 1
+#endif
+
+#ifndef lest_FEATURE_TIME_PRECISION
+#define lest_FEATURE_TIME_PRECISION 0
+#endif
+
+#ifdef _WIN32
+# define lest_PLATFORM_IS_WINDOWS 1
+#else
+# define lest_PLATFORM_IS_WINDOWS 0
+#endif
+
+#if lest_FEATURE_REGEX_SEARCH
+# include <regex>
+#endif
+
+#if lest_FEATURE_TIME
+# if lest_PLATFORM_IS_WINDOWS
+# include <iomanip>
+# include <Windows.h>
+# else
+# include <iomanip>
+# include <sys/time.h>
+# endif
+#endif
+
+// Compiler warning suppression:
+
+#if defined (__clang__)
+# pragma clang diagnostic ignored "-Waggregate-return"
+# pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdate-time"
+#elif defined (__GNUC__)
+# pragma GCC diagnostic ignored "-Waggregate-return"
+# pragma GCC diagnostic push
+#endif
+
+// Suppress shadow and unused-value warning for sections:
+
+#if defined (__clang__)
+# define lest_SUPPRESS_WSHADOW _Pragma( "clang diagnostic push" ) \
+ _Pragma( "clang diagnostic ignored \"-Wshadow\"" )
+# define lest_SUPPRESS_WUNUSED _Pragma( "clang diagnostic push" ) \
+ _Pragma( "clang diagnostic ignored \"-Wunused-value\"" )
+# define lest_SUPPRESS_WUNREACHABLE _Pragma( "clang diagnostic push" )
+# define lest_SUPPRESS_WNORETVAL _Pragma( "clang diagnostic push" )
+# define lest_RESTORE_WARNINGS _Pragma( "clang diagnostic pop" )
+
+#elif defined (__GNUC__)
+# define lest_SUPPRESS_WSHADOW _Pragma( "GCC diagnostic push" ) \
+ _Pragma( "GCC diagnostic ignored \"-Wshadow\"" )
+# define lest_SUPPRESS_WUNUSED _Pragma( "GCC diagnostic push" ) \
+ _Pragma( "GCC diagnostic ignored \"-Wunused-value\"" )
+# define lest_SUPPRESS_WUNREACHABLE _Pragma( "GCC diagnostic push" )
+# define lest_SUPPRESS_WNORETVAL _Pragma( "GCC diagnostic push" )
+# define lest_RESTORE_WARNINGS _Pragma( "GCC diagnostic pop" )
+#elif defined( _MSC_VER)
+# define lest_SUPPRESS_WSHADOW __pragma(warning(push)) __pragma(warning(disable: 4456))
+# define lest_SUPPRESS_WUNUSED __pragma(warning(push)) __pragma(warning(disable: 4100))
+# define lest_SUPPRESS_WUNREACHABLE __pragma(warning(push)) __pragma(warning(disable: 4702))
+# define lest_SUPPRESS_WNORETVAL __pragma(warning(push)) __pragma(warning(disable: 4715))
+# define lest_RESTORE_WARNINGS __pragma(warning(pop ))
+#else
+# define lest_SUPPRESS_WSHADOW /*empty*/
+# define lest_SUPPRESS_WUNUSED /*empty*/
+# define lest_SUPPRESS_WUNREACHABLE /*empty*/
+# define lest_SUPPRESS_WNORETVAL /*empty*/
+# define lest_RESTORE_WARNINGS /*empty*/
+#endif
+
+#if defined(__NVCOMPILER)
+# define lest_SUPPRESS_CONTROLLING_EXPRESSION_IS_CONSTANT _Pragma("diag_suppress 236")
+# define lest_RESTORE_CONTROLLING_EXPRESSION_IS_CONSTANT _Pragma("diag_default 236")
+#else
+# define lest_SUPPRESS_CONTROLLING_EXPRESSION_IS_CONSTANT
+# define lest_RESTORE_CONTROLLING_EXPRESSION_IS_CONSTANT
+#endif
+
+// Stringify:
+
+#define lest_STRINGIFY( x ) lest_STRINGIFY_( x )
+#define lest_STRINGIFY_( x ) #x
+
+// Compiler versions:
+
+#if defined( _MSC_VER ) && !defined( __clang__ )
+# define lest_COMPILER_MSVC_VERSION ( _MSC_VER / 10 - 10 * ( 5 + ( _MSC_VER < 1900 ) ) )
+#else
+# define lest_COMPILER_MSVC_VERSION 0
+#endif
+
+#define lest_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * major + minor ) + patch )
+
+#if defined (__clang__)
+# define lest_COMPILER_CLANG_VERSION lest_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
+#else
+# define lest_COMPILER_CLANG_VERSION 0
+#endif
+
+#if defined (__GNUC__)
+# define lest_COMPILER_GNUC_VERSION lest_COMPILER_VERSION( __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ )
+#else
+# define lest_COMPILER_GNUC_VERSION 0
+#endif
+
+// C++ language version detection (C++20 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef lest_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+# define lest_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+# define lest_CPLUSPLUS __cplusplus
+# endif
+#endif
+
+#define lest_CPP98_OR_GREATER ( lest_CPLUSPLUS >= 199711L )
+#define lest_CPP11_OR_GREATER ( lest_CPLUSPLUS >= 201103L || lest_COMPILER_MSVC_VERSION >= 120 )
+#define lest_CPP14_OR_GREATER ( lest_CPLUSPLUS >= 201402L )
+#define lest_CPP17_OR_GREATER ( lest_CPLUSPLUS >= 201703L )
+#define lest_CPP20_OR_GREATER ( lest_CPLUSPLUS >= 202000L )
+
+#define lest_CPP11_100 (lest_CPP11_OR_GREATER || lest_COMPILER_MSVC_VERSION >= 100)
+
+#ifndef __has_cpp_attribute
+# define __has_cpp_attribute(name) 0
+#endif
+
+// Indicate argument as possibly unused, if possible:
+
+#if __has_cpp_attribute(maybe_unused) && lest_CPP17_OR_GREATER
+# define lest_MAYBE_UNUSED(ARG) [[maybe_unused]] ARG
+#elif defined (__GNUC__)
+# define lest_MAYBE_UNUSED(ARG) ARG __attribute((unused))
+#else
+# define lest_MAYBE_UNUSED(ARG) ARG
+#endif
+
+// Presence of language and library features:
+
+#define lest_HAVE(FEATURE) ( lest_HAVE_##FEATURE )
+
+#if lest_COMPILER_CLANG_VERSION
+# ifdef __OBJC__
+ // There are a bunch of inconsistencies about __EXCEPTIONS and __has_feature(cxx_exceptions) in Clang 3.4/3.5/3.6.
+ // We're interested in C++ exceptions, which can be checked by __has_feature(cxx_exceptions) in 3.5+.
+ // In pre-3.5, __has_feature(cxx_exceptions) can be true if ObjC exceptions are enabled, but C++ exceptions are disabled.
+ // The recommended way to check is `__EXCEPTIONS && __has_feature(cxx_exceptions)`.
+ // See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
+ // Note: this is only relevant in Objective-C++, thus the ifdef.
+# if __EXCEPTIONS && __has_feature(cxx_exceptions)
+# define lest_HAVE_EXCEPTIONS 1
+# else
+# define lest_HAVE_EXCEPTIONS 0
+# endif // __EXCEPTIONS && __has_feature(cxx_exceptions)
+# else
+ // clang-cl doesn't define __EXCEPTIONS for MSVC compatibility (see https://reviews.llvm.org/D4065).
+ // Neither does Clang in MS-compatiblity mode.
+ // Let's hope no one tries to build Objective-C++ code using MS-compatibility mode or clang-cl.
+# if __has_feature(cxx_exceptions)
+# define lest_HAVE_EXCEPTIONS 1
+# else
+# define lest_HAVE_EXCEPTIONS 0
+# endif
+# endif
+#elif lest_COMPILER_GNUC_VERSION
+# if lest_COMPILER_GNUC_VERSION >= 1 && lest_COMPILER_GNUC_VERSION < 500
+# ifdef __EXCEPTIONS
+# define lest_HAVE_EXCEPTIONS 1
+# else
+# define lest_HAVE_EXCEPTIONS 0
+# endif // __EXCEPTIONS
+# else
+# ifdef __cpp_exceptions
+# define lest_HAVE_EXCEPTIONS 1
+# else
+# define lest_HAVE_EXCEPTIONS 0
+# endif // __cpp_exceptions
+# endif // lest_COMPILER_GNUC_VERSION >= 1 && lest_COMPILER_GNUC_VERSION < 500
+#elif lest_COMPILER_MSVC_VERSION
+# ifdef _CPPUNWIND
+# define lest_HAVE_EXCEPTIONS 1
+# else
+# define lest_HAVE_EXCEPTIONS 0
+# endif // _CPPUNWIND
+#else
+// For all other compilers, assume exceptions are always enabled.
+# define lest_HAVE_EXCEPTIONS 1
+#endif
+
+// Exception handling helpers:
+
+#if lest_HAVE( EXCEPTIONS )
+# define lest_TRY try
+# define lest_CATCH(x) catch (x)
+# define lest_CATCH_ALL catch (...)
+# define lest_THROW(x) throw x
+# define lest_RETHROW throw
+#else // ! lest_HAVE( EXCEPTIONS )
+# define lest_TRY if (1)
+# define lest_CATCH(x) else if (0)
+# define lest_CATCH_ALL else if (0)
+# define lest_THROW(x) std::terminate()
+# define lest_RETHROW
+#endif // lest_HAVE( EXCEPTIONS )
+
+
+// Presence of C++11 language features:
+
+#define lest_HAVE_NOEXCEPT ( lest_CPP11_100 )
+#define lest_HAVE_NULLPTR ( lest_CPP11_100 )
+
+// C++ feature usage:
+
+#if lest_HAVE( NULLPTR )
+# define lest_nullptr nullptr
+#else
+# define lest_nullptr NULL
+#endif
+
+// Additional includes and tie:
+
+#if lest_CPP11_100
+
+# include <cstdint>
+# include <random>
+# include <tuple>
+
+namespace lest
+{
+ using std::tie;
+}
+
+#else
+
+# if !defined(__clang__) && defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Weffc++"
+# endif
+
+namespace lest
+{
+ // tie:
+
+ template< typename T1, typename T2 >
+ struct Tie
+ {
+ Tie( T1 & first_, T2 & second_)
+ : first( first_), second( second_) {}
+
+ std::pair<T1, T2> const &
+ operator=( std::pair<T1, T2> const & rhs )
+ {
+ first = rhs.first;
+ second = rhs.second;
+ return rhs;
+ }
+
+ private:
+ void operator=( Tie const & );
+
+ T1 & first;
+ T2 & second;
+ };
+
+ template< typename T1, typename T2 >
+ inline Tie<T1,T2> tie( T1 & first, T2 & second )
+ {
+ return Tie<T1, T2>( first, second );
+ }
+}
+
+# if !defined(__clang__) && defined(__GNUC__)
+# pragma GCC diagnostic pop
+# endif
+
+#endif // lest_CPP11_100
+
+namespace lest
+{
+ using std::abs;
+ using std::min;
+ using std::strtol;
+ using std::rand;
+ using std::srand;
+}
+
+#if ! defined( lest_NO_SHORT_MACRO_NAMES ) && ! defined( lest_NO_SHORT_ASSERTION_NAMES )
+# define SETUP lest_SETUP
+# define SECTION lest_SECTION
+
+# define EXPECT lest_EXPECT
+# define EXPECT_NOT lest_EXPECT_NOT
+# define EXPECT_NO_THROW lest_EXPECT_NO_THROW
+# define EXPECT_THROWS lest_EXPECT_THROWS
+# define EXPECT_THROWS_AS lest_EXPECT_THROWS_AS
+
+# define SCENARIO lest_SCENARIO
+# define GIVEN lest_GIVEN
+# define WHEN lest_WHEN
+# define THEN lest_THEN
+# define AND_WHEN lest_AND_WHEN
+# define AND_THEN lest_AND_THEN
+#endif
+
+#define lest_SCENARIO( specification, sketch ) \
+ lest_CASE( specification, lest::text("Scenario: ") + sketch )
+#define lest_GIVEN( context ) lest_SETUP( lest::text(" Given: ") + context )
+#define lest_WHEN( story ) lest_SECTION( lest::text(" When: ") + story )
+#define lest_THEN( story ) lest_SECTION( lest::text(" Then: ") + story )
+#define lest_AND_WHEN( story ) lest_SECTION( lest::text("And then: ") + story )
+#define lest_AND_THEN( story ) lest_SECTION( lest::text("And then: ") + story )
+
+#define lest_CASE( specification, proposition ) \
+ static void lest_FUNCTION( lest::env & ); \
+ static lest::add_test lest_REGISTRAR( specification, lest::test( proposition, lest_FUNCTION ) ); \
+ static void lest_FUNCTION( lest_MAYBE_UNUSED( lest::env & lest_env ) )
+
+#define lest_ADD_TEST( specification, test ) \
+ specification.push_back( test )
+
+#define lest_SETUP( context ) \
+ for ( int lest__section = 0, lest__count = 1; lest__section < lest__count; lest__count -= 0==lest__section++ ) \
+ for ( lest::ctx lest__ctx_setup( lest_env, context ); lest__ctx_setup; )
+
+#define lest_SECTION( proposition ) \
+ lest_SUPPRESS_WSHADOW \
+ static int lest_UNIQUE( id ) = 0; \
+ if ( lest::guard( lest_UNIQUE( id ), lest__section, lest__count ) ) \
+ for ( int lest__section = 0, lest__count = 1; lest__section < lest__count; lest__count -= 0==lest__section++ ) \
+ for ( lest::ctx lest__ctx_section( lest_env, proposition ); lest__ctx_section; ) \
+ lest_RESTORE_WARNINGS
+
+#define lest_EXPECT( expr ) \
+ do { \
+ lest_TRY \
+ { \
+ lest_SUPPRESS_CONTROLLING_EXPRESSION_IS_CONSTANT \
+ if ( lest::result score = lest_DECOMPOSE( expr ) ) \
+ lest_THROW( lest::failure( lest_LOCATION, #expr, score.decomposition ) ); \
+ else if ( lest_env.pass() ) \
+ lest::report( lest_env.os, lest::passing( lest_LOCATION, #expr, score.decomposition, lest_env.zen() ), lest_env.context() ); \
+ lest_RESTORE_CONTROLLING_EXPRESSION_IS_CONSTANT \
+ } \
+ lest_CATCH_ALL \
+ { \
+ lest::inform( lest_LOCATION, #expr ); \
+ } \
+ } while ( false )
+
+#define lest_EXPECT_NOT( expr ) \
+ do { \
+ lest_TRY \
+ { \
+ lest_SUPPRESS_CONTROLLING_EXPRESSION_IS_CONSTANT \
+ if ( lest::result score = lest_DECOMPOSE( expr ) ) \
+ { \
+ if ( lest_env.pass() ) \
+ lest::report( lest_env.os, lest::passing( lest_LOCATION, lest::not_expr( #expr ), lest::not_expr( score.decomposition ), lest_env.zen() ), lest_env.context() ); \
+ } \
+ else \
+ lest_THROW( lest::failure( lest_LOCATION, lest::not_expr( #expr ), lest::not_expr( score.decomposition ) ) ); \
+ lest_RESTORE_CONTROLLING_EXPRESSION_IS_CONSTANT \
+ } \
+ lest_CATCH_ALL \
+ { \
+ lest::inform( lest_LOCATION, lest::not_expr( #expr ) ); \
+ } \
+ } while ( false )
+
+#define lest_EXPECT_NO_THROW( expr ) \
+ do \
+ { \
+ lest_TRY \
+ { \
+ lest_SUPPRESS_WUNUSED \
+ expr; \
+ lest_RESTORE_WARNINGS \
+ } \
+ lest_CATCH_ALL { lest::inform( lest_LOCATION, #expr ); } \
+ if ( lest_env.pass() ) \
+ lest::report( lest_env.os, lest::got_none( lest_LOCATION, #expr ), lest_env.context() ); \
+ } while ( false )
+
+#define lest_EXPECT_THROWS( expr ) \
+ do \
+ { \
+ lest_TRY \
+ { \
+ lest_SUPPRESS_WUNUSED \
+ expr; \
+ lest_RESTORE_WARNINGS \
+ } \
+ lest_CATCH_ALL \
+ { \
+ if ( lest_env.pass() ) \
+ lest::report( lest_env.os, lest::got( lest_LOCATION, #expr ), lest_env.context() ); \
+ break; \
+ } \
+ lest_THROW( lest::expected( lest_LOCATION, #expr ) ); \
+ } \
+ while ( false )
+
+#define lest_EXPECT_THROWS_AS( expr, excpt ) \
+ do \
+ { \
+ lest_TRY \
+ { \
+ lest_SUPPRESS_WUNUSED \
+ expr; \
+ lest_RESTORE_WARNINGS \
+ } \
+ lest_CATCH( excpt & ) \
+ { \
+ if ( lest_env.pass() ) \
+ lest::report( lest_env.os, lest::got( lest_LOCATION, #expr, lest::of_type( #excpt ) ), lest_env.context() ); \
+ break; \
+ } \
+ lest_CATCH_ALL {} \
+ lest_THROW( lest::expected( lest_LOCATION, #expr, lest::of_type( #excpt ) ) ); \
+ } \
+ while ( false )
+
+#define lest_DECOMPOSE( expr ) ( lest::expression_decomposer() << expr )
+
+#define lest_STRING( name ) lest_STRING2( name )
+#define lest_STRING2( name ) #name
+
+#define lest_UNIQUE( name ) lest_UNIQUE2( name, __LINE__ )
+#define lest_UNIQUE2( name, line ) lest_UNIQUE3( name, line )
+#define lest_UNIQUE3( name, line ) name ## line
+
+#define lest_LOCATION lest::location(__FILE__, __LINE__)
+
+#define lest_FUNCTION lest_UNIQUE(__lest_function__ )
+#define lest_REGISTRAR lest_UNIQUE(__lest_registrar__ )
+
+#define lest_DIMENSION_OF( a ) ( sizeof(a) / sizeof(0[a]) )
+
+namespace lest {
+
+const int exit_max_value = 255;
+
+typedef std::string text;
+typedef std::vector<text> texts;
+
+struct env;
+
+struct test
+{
+ text name;
+ void (* behaviour)( env & );
+
+ test( text name_, void (* behaviour_)( env & ) )
+ : name( name_), behaviour( behaviour_) {}
+};
+
+typedef std::vector<test> tests;
+typedef tests test_specification;
+
+struct add_test
+{
+ add_test( tests & specification, test const & test_case )
+ {
+ specification.push_back( test_case );
+ }
+};
+
+struct result
+{
+ const bool passed;
+ const text decomposition;
+
+ template< typename T >
+ result( T const & passed_, text decomposition_)
+ : passed( !!passed_), decomposition( decomposition_) {}
+
+ operator bool() { return ! passed; }
+};
+
+struct location
+{
+ const text file;
+ const int line;
+
+ location( text file_, int line_)
+ : file( file_), line( line_) {}
+};
+
+struct comment
+{
+ const text info;
+
+ comment( text info_) : info( info_) {}
+ operator bool() { return ! info.empty(); }
+};
+
+struct message : std::runtime_error
+{
+ const text kind;
+ const location where;
+ const comment note;
+
+#if ! lest_CPP11_OR_GREATER
+ ~message() throw() {}
+#endif
+
+ message( text kind_, location where_, text expr_, text note_ = "" )
+ : std::runtime_error( expr_), kind( kind_), where( where_), note( note_) {}
+};
+
+struct failure : message
+{
+ failure( location where_, text expr_, text decomposition_)
+ : message( "failed", where_, expr_ + " for " + decomposition_) {}
+};
+
+struct success : message
+{
+ success( text kind_, location where_, text expr_, text note_ = "" )
+ : message( kind_, where_, expr_, note_) {}
+};
+
+struct passing : success
+{
+ passing( location where_, text expr_, text decomposition_, bool zen )
+ : success( "passed", where_, expr_ + (zen ? "":" for " + decomposition_) ) {}
+};
+
+struct got_none : success
+{
+ got_none( location where_, text expr_)
+ : success( "passed: got no exception", where_, expr_) {}
+};
+
+struct got : success
+{
+ got( location where_, text expr_)
+ : success( "passed: got exception", where_, expr_) {}
+
+ got( location where_, text expr_, text excpt_)
+ : success( "passed: got exception " + excpt_, where_, expr_) {}
+};
+
+struct expected : message
+{
+ expected( location where_, text expr_, text excpt_ = "" )
+ : message( "failed: didn't get exception", where_, expr_, excpt_) {}
+};
+
+struct unexpected : message
+{
+ unexpected( location where_, text expr_, text note_ = "" )
+ : message( "failed: got unexpected exception", where_, expr_, note_) {}
+};
+
+struct guard
+{
+ int & id;
+ int const & section;
+
+ guard( int & id_, int const & section_, int & count )
+ : id( id_ ), section( section_ )
+ {
+ if ( section == 0 )
+ id = count++ - 1;
+ }
+ operator bool() { return id == section; }
+};
+
+class approx
+{
+public:
+ explicit approx ( double magnitude )
+ : epsilon_ ( 100.0 * static_cast<double>( std::numeric_limits<float>::epsilon() ) )
+ , scale_ ( 1.0 )
+ , magnitude_( magnitude ) {}
+
+ static approx custom() { return approx( 0 ); }
+
+ approx operator()( double new_magnitude )
+ {
+ approx appr( new_magnitude );
+ appr.epsilon( epsilon_ );
+ appr.scale ( scale_ );
+ return appr;
+ }
+
+ double magnitude() const { return magnitude_; }
+
+ approx & epsilon( double epsilon ) { epsilon_ = epsilon; return *this; }
+ approx & scale ( double scale ) { scale_ = scale; return *this; }
+
+ friend bool operator == ( double lhs, approx const & rhs )
+ {
+ // Thanks to Richard Harris for his help refining this formula.
+ return lest::abs( lhs - rhs.magnitude_ ) < rhs.epsilon_ * ( rhs.scale_ + (lest::min)( lest::abs( lhs ), lest::abs( rhs.magnitude_ ) ) );
+ }
+
+ friend bool operator == ( approx const & lhs, double rhs ) { return operator==( rhs, lhs ); }
+ friend bool operator != ( double lhs, approx const & rhs ) { return !operator==( lhs, rhs ); }
+ friend bool operator != ( approx const & lhs, double rhs ) { return !operator==( rhs, lhs ); }
+
+ friend bool operator <= ( double lhs, approx const & rhs ) { return lhs < rhs.magnitude_ || lhs == rhs; }
+ friend bool operator <= ( approx const & lhs, double rhs ) { return lhs.magnitude_ < rhs || lhs == rhs; }
+ friend bool operator >= ( double lhs, approx const & rhs ) { return lhs > rhs.magnitude_ || lhs == rhs; }
+ friend bool operator >= ( approx const & lhs, double rhs ) { return lhs.magnitude_ > rhs || lhs == rhs; }
+
+private:
+ double epsilon_;
+ double scale_;
+ double magnitude_;
+};
+
+inline bool is_false( ) { return false; }
+inline bool is_true ( bool flag ) { return flag; }
+
+inline text not_expr( text message )
+{
+ return "! ( " + message + " )";
+}
+
+inline text with_message( text message )
+{
+ return "with message \"" + message + "\"";
+}
+
+inline text of_type( text type )
+{
+ return "of type " + type;
+}
+
+inline void inform( location where, text expr )
+{
+ lest_TRY
+ {
+ lest_RETHROW;
+ }
+ lest_CATCH( failure const & )
+ {
+ lest_RETHROW;
+ }
+ lest_CATCH( std::exception const & e )
+ {
+#if lest_HAVE( EXCEPTIONS )
+ lest_THROW( unexpected( where, expr, with_message( e.what() ) ) );
+#endif // lest_HAVE( EXCEPTIONS )
+ }
+ lest_CATCH_ALL
+ {
+ lest_THROW( unexpected( where, expr, "of unknown type" ) );
+ }
+}
+
+// Expression decomposition:
+
+inline bool unprintable( char c )
+{
+ // The cast helps suppress warnings ("-Wtype-limits" on GCC) on architectures where `char` is unsigned.
+ return 0 <= static_cast<signed char>(c) && c < ' ';
+}
+
+inline std::string to_hex_string(char c)
+{
+ std::ostringstream os;
+ os << "\\x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>( static_cast<unsigned char>(c) );
+ return os.str();
+}
+
+inline std::string transformed( char chr )
+{
+ struct Tr { char chr; char const * str; } table[] =
+ {
+ {'\\', "\\\\" },
+ {'\r', "\\r" }, {'\f', "\\f" },
+ {'\n', "\\n" }, {'\t', "\\t" },
+ };
+
+ for ( Tr * pos = table; pos != table + lest_DIMENSION_OF( table ); ++pos )
+ {
+ if ( chr == pos->chr )
+ return pos->str;
+ }
+
+ return unprintable( chr ) ? to_hex_string( chr ) : std::string( 1, chr );
+}
+
+template< typename C >
+inline std::string make_tran_string( std::basic_string< C > const & txt )
+{
+ std::ostringstream os;
+ for( typename std::basic_string< C >::const_iterator pos = txt.begin(); pos != txt.end(); ++pos )
+ os << transformed( static_cast<char>( *pos ) );
+ return os.str();
+}
+
+template< typename T >
+inline std::string to_string( T const & value );
+
+#if lest_CPP11_OR_GREATER || lest_COMPILER_MSVC_VERSION >= 100
+inline std::string to_string( std::nullptr_t const & ) { return "nullptr"; }
+#endif
+inline std::string to_string( std::string const & txt ) { return "\"" + make_tran_string( txt ) + "\""; }
+inline std::string to_string( wchar_t const * const & txt ) { return "\"" + make_tran_string( std::wstring( txt ) ) + "\""; }
+inline std::string to_string( char const * const & txt ) { return "\"" + make_tran_string( std::string( txt ) ) + "\""; }
+inline std::string to_string( char const & chr ) { return "'" + make_tran_string( std::string( 1, chr ) ) + "'"; }
+
+inline std::string to_string( signed char const & chr ) { return to_string( static_cast<char>( chr ) ); }
+inline std::string to_string( unsigned char const & chr ) { return to_string( static_cast<char>( chr ) ); }
+
+inline std::ostream & operator<<( std::ostream & os, approx const & appr )
+{
+ return os << appr.magnitude();
+}
+
+template< typename T >
+inline std::string make_string( T const * ptr )
+{
+ // Note showbase affects the behavior of /integer/ output;
+ std::ostringstream os;
+ os << std::internal << std::hex << std::showbase << std::setw( 2 + 2 * sizeof(T*) ) << std::setfill('0') << reinterpret_cast<std::ptrdiff_t>( ptr );
+ return os.str();
+}
+
+template< typename C, typename R >
+inline std::string make_string( R C::* ptr )
+{
+ std::ostringstream os;
+ os << std::internal << std::hex << std::showbase << std::setw( 2 + 2 * sizeof(R C::* ) ) << std::setfill('0') << ptr;
+ return os.str();
+}
+
+template< typename T >
+struct string_maker
+{
+ static std::string to_string( T const & value )
+ {
+ std::ostringstream os; os << std::boolalpha << value;
+ return os.str();
+ }
+};
+
+template< >
+struct string_maker< wchar_t >
+{
+ static std::string to_string( wchar_t value )
+ {
+ std::ostringstream os; os << std::boolalpha << static_cast<char>( value );
+ return os.str();
+ }
+};
+
+template< typename T >
+struct string_maker< T* >
+{
+ static std::string to_string( T const * ptr )
+ {
+ return ! ptr ? lest_STRING( lest_nullptr ) : make_string( ptr );
+ }
+};
+
+template< typename C, typename R >
+struct string_maker< R C::* >
+{
+ static std::string to_string( R C::* ptr )
+ {
+ return ! ptr ? lest_STRING( lest_nullptr ) : make_string( ptr );
+ }
+};
+
+template< typename T >
+inline std::string to_string( T const & value )
+{
+ return string_maker<T>::to_string( value );
+}
+
+template< typename T1, typename T2 >
+std::string to_string( std::pair<T1,T2> const & pair )
+{
+ std::ostringstream oss;
+ oss << "{ " << to_string( pair.first ) << ", " << to_string( pair.second ) << " }";
+ return oss.str();
+}
+
+#if lest_CPP11_OR_GREATER
+
+template< typename TU, std::size_t N >
+struct make_tuple_string
+{
+ static std::string make( TU const & tuple )
+ {
+ std::ostringstream os;
+ os << to_string( std::get<N - 1>( tuple ) ) << ( N < std::tuple_size<TU>::value ? ", ": " ");
+ return make_tuple_string<TU, N - 1>::make( tuple ) + os.str();
+ }
+};
+
+template< typename TU >
+struct make_tuple_string<TU, 0>
+{
+ static std::string make( TU const & ) { return ""; }
+};
+
+template< typename ...TS >
+auto to_string( std::tuple<TS...> const & tuple ) -> std::string
+{
+ return "{ " + make_tuple_string<std::tuple<TS...>, sizeof...(TS)>::make( tuple ) + "}";
+}
+
+#endif // lest_CPP11_OR_GREATER
+
+template< typename L, typename R >
+std::string to_string( L const & lhs, std::string op, R const & rhs )
+{
+ std::ostringstream os; os << to_string( lhs ) << " " << op << " " << to_string( rhs ); return os.str();
+}
+
+template< typename L >
+struct expression_lhs
+{
+ L lhs;
+
+ expression_lhs( L lhs_) : lhs( lhs_) {}
+
+ operator result() { return result( !!lhs, to_string( lhs ) ); }
+
+ template< typename R > result operator==( R const & rhs ) { return result( lhs == rhs, to_string( lhs, "==", rhs ) ); }
+ template< typename R > result operator!=( R const & rhs ) { return result( lhs != rhs, to_string( lhs, "!=", rhs ) ); }
+ template< typename R > result operator< ( R const & rhs ) { return result( lhs < rhs, to_string( lhs, "<" , rhs ) ); }
+ template< typename R > result operator<=( R const & rhs ) { return result( lhs <= rhs, to_string( lhs, "<=", rhs ) ); }
+ template< typename R > result operator> ( R const & rhs ) { return result( lhs > rhs, to_string( lhs, ">" , rhs ) ); }
+ template< typename R > result operator>=( R const & rhs ) { return result( lhs >= rhs, to_string( lhs, ">=", rhs ) ); }
+};
+
+struct expression_decomposer
+{
+ template< typename L >
+ expression_lhs<L const &> operator<< ( L const & operand )
+ {
+ return expression_lhs<L const &>( operand );
+ }
+};
+
+// Reporter:
+
+#if lest_FEATURE_COLOURISE
+
+inline text red ( text words ) { return "\033[1;31m" + words + "\033[0m"; }
+inline text green( text words ) { return "\033[1;32m" + words + "\033[0m"; }
+inline text gray ( text words ) { return "\033[1;30m" + words + "\033[0m"; }
+
+inline bool starts_with( text words, text with )
+{
+ return 0 == words.find( with );
+}
+
+inline text replace( text words, text from, text to )
+{
+ size_t pos = words.find( from );
+ return pos == std::string::npos ? words : words.replace( pos, from.length(), to );
+}
+
+inline text colour( text words )
+{
+ if ( starts_with( words, "failed" ) ) return replace( words, "failed", red ( "failed" ) );
+ else if ( starts_with( words, "passed" ) ) return replace( words, "passed", green( "passed" ) );
+
+ return replace( words, "for", gray( "for" ) );
+}
+
+inline bool is_cout( std::ostream & os ) { return &os == &std::cout; }
+
+struct colourise
+{
+ const text words;
+
+ colourise( text words )
+ : words( words ) {}
+
+ // only colourise for std::cout, not for a stringstream as used in tests:
+
+ std::ostream & operator()( std::ostream & os ) const
+ {
+ return is_cout( os ) ? os << colour( words ) : os << words;
+ }
+};
+
+inline std::ostream & operator<<( std::ostream & os, colourise words ) { return words( os ); }
+#else
+inline text colourise( text words ) { return words; }
+#endif
+
+inline text pluralise( text word,int n )
+{
+ return n == 1 ? word : word + "s";
+}
+
+inline std::ostream & operator<<( std::ostream & os, comment note )
+{
+ return os << (note ? " " + note.info : "" );
+}
+
+inline std::ostream & operator<<( std::ostream & os, location where )
+{
+#ifdef __GNUG__
+ return os << where.file << ":" << where.line;
+#else
+ return os << where.file << "(" << where.line << ")";
+#endif
+}
+
+inline void report( std::ostream & os, message const & e, text test )
+{
+ os << e.where << ": " << colourise( e.kind ) << e.note << ": " << test << ": " << colourise( e.what() ) << std::endl;
+}
+
+// Test runner:
+
+#if lest_FEATURE_REGEX_SEARCH
+ inline bool search( text re, text line )
+ {
+ return std::regex_search( line, std::regex( re ) );
+ }
+#else
+ inline bool case_insensitive_equal( char a, char b )
+ {
+ return tolower( a ) == tolower( b );
+ }
+
+ inline bool search( text part, text line )
+ {
+ return std::search(
+ line.begin(), line.end(),
+ part.begin(), part.end(), case_insensitive_equal ) != line.end();
+ }
+#endif
+
+inline bool match( texts whats, text line )
+{
+ for ( texts::iterator what = whats.begin(); what != whats.end() ; ++what )
+ {
+ if ( search( *what, line ) )
+ return true;
+ }
+ return false;
+}
+
+inline bool hidden( text name )
+{
+#if lest_FEATURE_REGEX_SEARCH
+ texts skipped; skipped.push_back( "\\[\\.\\]" ); skipped.push_back( "\\[hide\\]" );
+#else
+ texts skipped; skipped.push_back( "[." ); skipped.push_back( "[hide]" );
+#endif
+ return match( skipped, name );
+}
+
+inline bool none( texts args )
+{
+ return args.size() == 0;
+}
+
+inline bool select( text name, texts include )
+{
+ if ( none( include ) )
+ {
+ return ! hidden( name );
+ }
+
+ bool any = false;
+ for ( texts::reverse_iterator pos = include.rbegin(); pos != include.rend(); ++pos )
+ {
+ text & part = *pos;
+
+ if ( part == "@" || part == "*" )
+ return true;
+
+ if ( search( part, name ) )
+ return true;
+
+ if ( '!' == part[0] )
+ {
+ any = true;
+ if ( search( part.substr(1), name ) )
+ return false;
+ }
+ else
+ {
+ any = false;
+ }
+ }
+ return any && ! hidden( name );
+}
+
+inline int indefinite( int repeat ) { return repeat == -1; }
+
+#if lest_CPP11_OR_GREATER
+typedef std::mt19937::result_type seed_t;
+#else
+typedef unsigned int seed_t;
+#endif
+
+struct options
+{
+ options()
+ : help(false), abort(false), count(false), list(false), tags(false), time(false)
+ , pass(false), zen(false), lexical(false), random(false), verbose(false), version(false), repeat(1), seed(0) {}
+
+ bool help;
+ bool abort;
+ bool count;
+ bool list;
+ bool tags;
+ bool time;
+ bool pass;
+ bool zen;
+ bool lexical;
+ bool random;
+ bool verbose;
+ bool version;
+ int repeat;
+ seed_t seed;
+};
+
+struct env
+{
+ std::ostream & os;
+ options opt;
+ text testing;
+ std::vector< text > ctx;
+
+ env( std::ostream & out, options option )
+ : os( out ), opt( option ), testing(), ctx() {}
+
+ env & operator()( text test )
+ {
+ clear(); testing = test; return *this;
+ }
+
+ bool abort() { return opt.abort; }
+ bool pass() { return opt.pass; }
+ bool zen() { return opt.zen; }
+
+ void clear() { ctx.clear(); }
+ void pop() { ctx.pop_back(); }
+ void push( text proposition ) { ctx.push_back( proposition ); }
+
+ text context() { return testing + sections(); }
+
+ text sections()
+ {
+ if ( ! opt.verbose )
+ return "";
+
+ text msg;
+ for( size_t i = 0; i != ctx.size(); ++i )
+ {
+ msg += "\n " + ctx[i];
+ }
+ return msg;
+ }
+};
+
+struct ctx
+{
+ env & environment;
+ bool once;
+
+ ctx( env & environment_, text proposition_ )
+ : environment( environment_), once( true )
+ {
+ environment.push( proposition_);
+ }
+
+ ~ctx()
+ {
+#if lest_CPP17_OR_GREATER
+ if ( std::uncaught_exceptions() == 0 )
+#else
+ if ( ! std::uncaught_exception() )
+#endif
+ {
+ environment.pop();
+ }
+ }
+
+ operator bool() { bool result = once; once = false; return result; }
+};
+
+struct action
+{
+ std::ostream & os;
+
+ action( std::ostream & out ) : os( out ) {}
+
+ operator int() { return 0; }
+ bool abort() { return false; }
+ action & operator()( test ) { return *this; }
+
+private:
+ action( action const & );
+ void operator=( action const & );
+};
+
+struct print : action
+{
+ print( std::ostream & out ) : action( out ) {}
+
+ print & operator()( test testing )
+ {
+ os << testing.name << "\n"; return *this;
+ }
+};
+
+inline texts tags( text name, texts result = texts() )
+{
+ size_t none = std::string::npos;
+ size_t lb = name.find_first_of( "[" );
+ size_t rb = name.find_first_of( "]" );
+
+ if ( lb == none || rb == none )
+ return result;
+
+ result.push_back( name.substr( lb, rb - lb + 1 ) );
+
+ return tags( name.substr( rb + 1 ), result );
+}
+
+struct ptags : action
+{
+ std::set<text> result;
+
+ ptags( std::ostream & out ) : action( out ), result() {}
+
+ ptags & operator()( test testing )
+ {
+ texts tags_( tags( testing.name ) );
+ for ( texts::iterator pos = tags_.begin(); pos != tags_.end() ; ++pos )
+ result.insert( *pos );
+
+ return *this;
+ }
+
+ ~ptags()
+ {
+ std::copy( result.begin(), result.end(), std::ostream_iterator<text>( os, "\n" ) );
+ }
+};
+
+struct count : action
+{
+ int n;
+
+ count( std::ostream & out ) : action( out ), n( 0 ) {}
+
+ count & operator()( test ) { ++n; return *this; }
+
+ ~count()
+ {
+ os << n << " selected " << pluralise("test", n) << "\n";
+ }
+};
+
+#if lest_FEATURE_TIME
+
+#if lest_PLATFORM_IS_WINDOWS
+# if ! lest_CPP11_OR_GREATER && ! lest_COMPILER_MSVC_VERSION
+ typedef unsigned long uint64_t;
+# elif lest_COMPILER_MSVC_VERSION >= 60 && lest_COMPILER_MSVC_VERSION < 100
+ typedef /*un*/signed __int64 uint64_t;
+# else
+ using ::uint64_t;
+# endif
+#else
+# if ! lest_CPP11_OR_GREATER
+ typedef unsigned long long uint64_t;
+# endif
+#endif
+
+#if lest_PLATFORM_IS_WINDOWS
+ inline uint64_t current_ticks()
+ {
+ static LARGE_INTEGER hz = {{ 0,0 }}, hzo = {{ 0,0 }};
+ if ( ! hz.QuadPart )
+ {
+ QueryPerformanceFrequency( &hz );
+ QueryPerformanceCounter ( &hzo );
+ }
+ LARGE_INTEGER t = {{ 0,0 }}; QueryPerformanceCounter( &t );
+
+ return uint64_t( ( ( t.QuadPart - hzo.QuadPart ) * 1000000 ) / hz.QuadPart );
+ }
+#else
+ inline uint64_t current_ticks()
+ {
+ timeval t; gettimeofday( &t, lest_nullptr );
+ return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
+ }
+#endif
+
+struct timer
+{
+ const uint64_t start_ticks;
+
+ timer() : start_ticks( current_ticks() ) {}
+
+ double elapsed_seconds() const
+ {
+ return static_cast<double>( current_ticks() - start_ticks ) / 1e6;
+ }
+};
+
+struct times : action
+{
+ env output;
+ int selected;
+ int failures;
+
+ timer total;
+
+ times( std::ostream & out, options option )
+ : action( out ), output( out, option ), selected( 0 ), failures( 0 ), total()
+ {
+ os << std::setfill(' ') << std::fixed << std::setprecision( lest_FEATURE_TIME_PRECISION );
+ }
+
+ operator int() { return failures; }
+
+ bool abort() { return output.abort() && failures > 0; }
+
+ times & operator()( test testing )
+ {
+ timer t;
+
+ lest_TRY
+ {
+ testing.behaviour( output( testing.name ) );
+ }
+ lest_CATCH( message const & )
+ {
+ ++failures;
+ }
+
+ os << std::setw(5) << ( 1000 * t.elapsed_seconds() ) << " ms: " << testing.name << "\n";
+
+ return *this;
+ }
+
+ ~times()
+ {
+ os << "Elapsed time: " << std::setprecision(1) << total.elapsed_seconds() << " s\n";
+ }
+};
+#else
+struct times : action { times( std::ostream & out, options ) : action( out ) {} };
+#endif
+
+struct confirm : action
+{
+ env output;
+ int selected;
+ int failures;
+
+ confirm( std::ostream & out, options option )
+ : action( out ), output( out, option ), selected( 0 ), failures( 0 ) {}
+
+ operator int() { return failures; }
+
+ bool abort() { return output.abort() && failures > 0; }
+
+ confirm & operator()( test testing )
+ {
+ lest_TRY
+ {
+ ++selected; testing.behaviour( output( testing.name ) );
+ }
+ lest_CATCH( message const & e )
+ {
+ ++failures;
+#if lest_HAVE( EXCEPTIONS )
+ report( os, e, output.context() );
+#endif // lest_HAVE( EXCEPTIONS )
+ }
+ return *this;
+ }
+
+ ~confirm()
+ {
+ if ( failures > 0 )
+ {
+ os << failures << " out of " << selected << " selected " << pluralise("test", selected) << " " << colourise( "failed.\n" );
+ }
+ else if ( output.pass() )
+ {
+ os << "All " << selected << " selected " << pluralise("test", selected) << " " << colourise( "passed.\n" );
+ }
+ }
+};
+
+template< typename Action >
+bool abort( Action & perform )
+{
+ return perform.abort();
+}
+
+template< typename Action >
+Action & for_test( tests specification, texts in, Action & perform, int n = 1 )
+{
+ for ( int i = 0; indefinite( n ) || i < n; ++i )
+ {
+ for ( tests::iterator pos = specification.begin(); pos != specification.end() ; ++pos )
+ {
+ test & testing = *pos;
+
+ if ( select( testing.name, in ) )
+ if ( abort( perform( testing ) ) )
+ return perform;
+ }
+ }
+ return perform;
+}
+
+inline bool test_less( test const & a, test const & b ) { return a.name < b.name; }
+
+inline void sort( tests & specification )
+{
+ std::sort( specification.begin(), specification.end(), test_less );
+}
+
+// Use struct to avoid VC6 error C2664 when using free function:
+
+struct rng { int operator()( int n ) { return lest::rand() % n; } };
+
+inline void shuffle( tests & specification, options option )
+{
+#if lest_CPP11_OR_GREATER
+ std::shuffle( specification.begin(), specification.end(), std::mt19937( option.seed ) );
+#else
+ lest::srand( option.seed );
+
+ rng generator;
+ std::random_shuffle( specification.begin(), specification.end(), generator );
+#endif
+}
+
+inline int stoi( text num )
+{
+ return static_cast<int>( lest::strtol( num.c_str(), lest_nullptr, 10 ) );
+}
+
+inline bool is_number( text arg )
+{
+ const text digits = "0123456789";
+ return text::npos != arg.find_first_of ( digits )
+ && text::npos == arg.find_first_not_of( digits );
+}
+
+lest_SUPPRESS_WNORETVAL
+inline seed_t seed( text opt, text arg )
+{
+ // std::time_t: implementation dependent
+
+ if ( arg == "time" )
+ return static_cast<seed_t>( time( lest_nullptr ) );
+
+ if ( is_number( arg ) )
+ return static_cast<seed_t>( lest::stoi( arg ) );
+
+ lest_THROW( std::runtime_error( "expecting 'time' or positive number with option '" + opt + "', got '" + arg + "' (try option --help)" ) );
+}
+
+inline int repeat( text opt, text arg )
+{
+ const int num = lest::stoi( arg );
+
+ if ( indefinite( num ) || num >= 0 )
+ return num;
+
+ lest_THROW( std::runtime_error( "expecting '-1' or positive number with option '" + opt + "', got '" + arg + "' (try option --help)" ) );
+}
+lest_RESTORE_WARNINGS
+
+inline std::pair<text, text>
+split_option( text arg )
+{
+ text::size_type pos = arg.rfind( '=' );
+
+ return pos == text::npos
+ ? std::make_pair( arg, text() )
+ : std::make_pair( arg.substr( 0, pos ), arg.substr( pos + 1 ) );
+}
+
+inline std::pair<options, texts>
+split_arguments( texts args )
+{
+ options option; texts in;
+
+ bool in_options = true;
+
+ for ( texts::iterator pos = args.begin(); pos != args.end() ; ++pos )
+ {
+ text opt, val, arg = *pos;
+ tie( opt, val ) = split_option( arg );
+
+ if ( in_options )
+ {
+ if ( opt[0] != '-' ) { in_options = false; }
+ else if ( opt == "--" ) { in_options = false; continue; }
+ else if ( opt == "-h" || "--help" == opt ) { option.help = true; continue; }
+ else if ( opt == "-a" || "--abort" == opt ) { option.abort = true; continue; }
+ else if ( opt == "-c" || "--count" == opt ) { option.count = true; continue; }
+ else if ( opt == "-g" || "--list-tags" == opt ) { option.tags = true; continue; }
+ else if ( opt == "-l" || "--list-tests" == opt ) { option.list = true; continue; }
+ else if ( opt == "-t" || "--time" == opt ) { option.time = true; continue; }
+ else if ( opt == "-p" || "--pass" == opt ) { option.pass = true; continue; }
+ else if ( opt == "-z" || "--pass-zen" == opt ) { option.zen = true; continue; }
+ else if ( opt == "-v" || "--verbose" == opt ) { option.verbose = true; continue; }
+ else if ( "--version" == opt ) { option.version = true; continue; }
+ else if ( opt == "--order" && "declared" == val ) { /* by definition */ ; continue; }
+ else if ( opt == "--order" && "lexical" == val ) { option.lexical = true; continue; }
+ else if ( opt == "--order" && "random" == val ) { option.random = true; continue; }
+ else if ( opt == "--random-seed" ) { option.seed = seed ( "--random-seed", val ); continue; }
+ else if ( opt == "--repeat" ) { option.repeat = repeat( "--repeat" , val ); continue; }
+ else lest_THROW( std::runtime_error( "unrecognised option '" + opt + "' (try option --help)" ) );
+ }
+ in.push_back( arg );
+ }
+ option.pass = option.pass || option.zen;
+
+ return std::make_pair( option, in );
+}
+
+inline int usage( std::ostream & os )
+{
+ os <<
+ "\nUsage: test [options] [test-spec ...]\n"
+ "\n"
+ "Options:\n"
+ " -h, --help this help message\n"
+ " -a, --abort abort at first failure\n"
+ " -c, --count count selected tests\n"
+ " -g, --list-tags list tags of selected tests\n"
+ " -l, --list-tests list selected tests\n"
+ " -p, --pass also report passing tests\n"
+ " -z, --pass-zen ... without expansion\n"
+#if lest_FEATURE_TIME
+ " -t, --time list duration of selected tests\n"
+#endif
+ " -v, --verbose also report passing or failing sections\n"
+ " --order=declared use source code test order (default)\n"
+ " --order=lexical use lexical sort test order\n"
+ " --order=random use random test order\n"
+ " --random-seed=n use n for random generator seed\n"
+ " --random-seed=time use time for random generator seed\n"
+ " --repeat=n repeat selected tests n times (-1: indefinite)\n"
+ " --version report lest version and compiler used\n"
+ " -- end options\n"
+ "\n"
+ "Test specification:\n"
+ " \"@\", \"*\" all tests, unless excluded\n"
+ " empty all tests, unless tagged [hide] or [.optional-name]\n"
+#if lest_FEATURE_REGEX_SEARCH
+ " \"re\" select tests that match regular expression\n"
+ " \"!re\" omit tests that match regular expression\n"
+#else
+ " \"text\" select tests that contain text (case insensitive)\n"
+ " \"!text\" omit tests that contain text (case insensitive)\n"
+#endif
+ ;
+ return 0;
+}
+
+inline text compiler()
+{
+ std::ostringstream os;
+#if defined (__clang__ )
+ os << "clang " << __clang_version__;
+#elif defined (__GNUC__ )
+ os << "gcc " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__;
+#elif defined ( _MSC_VER )
+ os << "MSVC " << lest_COMPILER_MSVC_VERSION << " (" << _MSC_VER << ")";
+#else
+ os << "[compiler]";
+#endif
+ return os.str();
+}
+
+inline int version( std::ostream & os )
+{
+ os << "lest version " << lest_VERSION << "\n"
+// Disabled because __DATE__ and __TIME__ are PCH-unfriendly
+// << "Compiled with " << compiler() << " on " << __DATE__ << " at " << __TIME__ << ".\n"
+ << "For more information, see https://github.com/martinmoene/lest.\n";
+ return 0;
+}
+
+inline int run( tests specification, texts arguments, std::ostream & os = std::cout )
+{
+ lest_TRY
+ {
+ options option; texts in;
+ tie( option, in ) = split_arguments( arguments );
+
+ if ( option.lexical ) { sort( specification ); }
+ if ( option.random ) { shuffle( specification, option ); }
+
+ if ( option.help ) { return usage ( os ); }
+ if ( option.version ) { return version( os ); }
+ if ( option.count ) { count count_( os ); return for_test( specification, in, count_ ); }
+ if ( option.list ) { print print_( os ); return for_test( specification, in, print_ ); }
+ if ( option.tags ) { ptags ptags_( os ); return for_test( specification, in, ptags_ ); }
+ if ( option.time ) { times times_( os, option ); return for_test( specification, in, times_ ); }
+
+ { confirm confirm_( os, option ); return for_test( specification, in, confirm_, option.repeat ); }
+ }
+ lest_CATCH( std::exception const & e )
+ {
+#if lest_HAVE( EXCEPTIONS )
+ os << "Error: " << e.what() << "\n";
+#endif // lest_HAVE( EXCEPTIONS )
+ return 1;
+ }
+}
+
+// VC6: make<cont>(first,last) replaces cont(first,last)
+
+template< typename C, typename T >
+C make( T const * first, T const * const last )
+{
+ C result;
+ for ( ; first != last; ++first )
+ {
+ result.push_back( *first );
+ }
+ return result;
+}
+
+inline tests make_tests( test const * first, test const * const last )
+{
+ return make<tests>( first, last );
+}
+
+inline texts make_texts( char const * const * first, char const * const * last )
+{
+ return make<texts>( first, last );
+}
+
+// Traversal of test[N] (test_specification[N]) set up to also work with MSVC6:
+
+template< typename C > test const * test_begin( C const & c ) { return &*c; }
+template< typename C > test const * test_end( C const & c ) { return test_begin( c ) + lest_DIMENSION_OF( c ); }
+
+template< typename C > char const * const * text_begin( C const & c ) { return &*c; }
+template< typename C > char const * const * text_end( C const & c ) { return text_begin( c ) + lest_DIMENSION_OF( c ); }
+
+template< typename C > tests make_tests( C const & c ) { return make_tests( test_begin( c ), test_end( c ) ); }
+template< typename C > texts make_texts( C const & c ) { return make_texts( text_begin( c ), text_end( c ) ); }
+
+inline int run( tests const & specification, int argc, char ** argv, std::ostream & os = std::cout )
+{
+ return run( specification, make_texts( argv + 1, argv + argc ), os );
+}
+
+inline int run( tests const & specification, std::ostream & os = std::cout )
+{
+ std::cout.sync_with_stdio( false );
+ return (min)( run( specification, texts(), os ), exit_max_value );
+}
+
+template< typename C >
+int run( C const & specification, texts args, std::ostream & os = std::cout )
+{
+ return run( make_tests( specification ), args, os );
+}
+
+template< typename C >
+int run( C const & specification, int argc, char ** argv, std::ostream & os = std::cout )
+{
+ return run( make_tests( specification ), argv, argc, os );
+}
+
+template< typename C >
+int run( C const & specification, std::ostream & os = std::cout )
+{
+ return run( make_tests( specification ), os );
+}
+
+} // namespace lest
+
+#if defined (__clang__)
+# pragma clang diagnostic pop
+#elif defined (__GNUC__)
+# pragma GCC diagnostic pop
+#endif
+
+#endif // LEST_LEST_HPP_INCLUDED
diff --git a/thirdparty/gsl-lite/test/not_null.t.cpp b/thirdparty/gsl-lite/test/not_null.t.cpp
new file mode 100644
index 000000000..32430c346
--- /dev/null
+++ b/thirdparty/gsl-lite/test/not_null.t.cpp
@@ -0,0 +1,1956 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+#include <vector>
+#include <functional>
+
+using namespace gsl_lite;
+
+namespace {
+
+struct MyBase {};
+struct MyDerived : public MyBase {};
+struct Unrelated {};
+
+// Stand-in for a user-defined ref-counted class.
+template<typename T>
+struct RefCounted
+{
+ RefCounted( T * p ) : p_( p ) {}
+ operator T *() const { return p_; }
+ T * p_;
+};
+
+template< class T >
+void take_raw( T* )
+{
+}
+#if gsl_HAVE( UNIQUE_PTR )
+template< class T >
+void take_unique_by_val( std::unique_ptr<T> )
+{
+}
+template< class T >
+void take_unique_by_ref( std::unique_ptr<T> const & )
+{
+}
+#endif
+#if gsl_HAVE( SHARED_PTR )
+template< class T >
+void take_shared_by_val( std::shared_ptr<T> )
+{
+}
+template< class T >
+void take_shared_by_ref( std::shared_ptr<T> const & )
+{
+}
+template< class T >
+struct ExplicitFromShared
+{
+ explicit ExplicitFromShared( std::shared_ptr<T> const & )
+ {
+ }
+};
+#endif
+
+} // anonymous namespace
+
+namespace nonlocal
+{
+ struct S { char c; int i; };
+}
+
+CASE( "not_null<>: Disallows default construction (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+#if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+ not_null< int* > p;
+#endif
+}
+
+CASE( "not_null<>: Disallows construction from nullptr_t, NULL or 0 (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+#if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+# if gsl_HAVE( NULLPTR )
+ not_null< int* > p( nullptr );
+# endif
+ not_null< int* > q( NULL );
+ not_null< std::vector<char>* > r( 0 );
+#endif
+}
+
+CASE( "not_null<>: Disallows construction from a unique pointer to underlying type (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+#if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+# if gsl_HAVE( UNIQUE_PTR )
+ std::unique_ptr< int > up( new int(120) );
+ not_null< int* > p4( up );
+# endif
+#endif
+}
+
+CASE( "not_null<>: Layout is compatible to underlying type" )
+{
+#if gsl_HAVE( TYPE_TRAITS )
+ static_assert( sizeof( not_null< int* > ) == sizeof( int* ), "static assertion failed" );
+# if gsl_HAVE( UNIQUE_PTR )
+ static_assert( sizeof( not_null< unique_ptr< int > > ) == sizeof( unique_ptr< int > ), "static assertion failed" );
+# endif // gsl_HAVE( UNIQUE_PTR )
+# if gsl_HAVE( SHARED_PTR )
+ static_assert( sizeof( not_null< shared_ptr< int > > ) == sizeof( shared_ptr< int > ), "static assertion failed" );
+# endif // gsl_HAVE( SHARED_PTR )
+#endif
+}
+
+CASE( "not_null<>: Convertibility is correctly reported by type traits" )
+{
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( UNIQUE_PTR ) && !gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 120 )
+
+ // Permit conversion to underlying type.
+ static_assert( std::is_convertible< not_null< int* >, int* >::value, "static assertion failed" );
+ static_assert( std::is_convertible< not_null< int* >, not_null< int* > >::value, "static assertion failed" );
+# if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+ static_assert( !std::is_convertible< int*, not_null< int* > >::value, "static assertion failed" );
+# endif
+
+ // Permit conversion to underlying type with implicit upcasts.
+ static_assert( std::is_convertible< not_null< MyDerived* >, MyBase* >::value, "static assertion failed" );
+ static_assert( std::is_convertible< not_null< MyDerived* >, not_null< MyBase* > >::value, "static assertion failed" );
+# if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+ static_assert( !std::is_convertible< MyDerived*, not_null< MyBase* > >::value, "static assertion failed" );
+# endif
+
+ // Permit conversion to underlying type with implicit upcasts for move-only types.
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ static_assert( std::is_convertible< not_null< std::unique_ptr< MyDerived > >, std::unique_ptr< MyBase > >::value, "static assertion failed" );
+ static_assert( !std::is_convertible< not_null< std::unique_ptr< MyBase > >, std::unique_ptr< MyDerived > >::value, "static assertion failed" );
+# endif
+
+ // Permit implicit upcasts for move-only types.
+ static_assert( std::is_convertible< not_null< std::unique_ptr< MyDerived > >, not_null< std::unique_ptr< MyBase > > >::value, "static assertion failed" );
+# if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+ static_assert( !std::is_convertible< std::unique_ptr< MyDerived >, not_null< std::unique_ptr< MyBase > > >::value, "static assertion failed" );
+# endif
+
+ // `unique_ptr<T>` and `shared_ptr<T>` have explicit constructors for `T*` arguments; do not allow implicit conversion.
+# if !gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ static_assert( !std::is_convertible< int*, not_null< std::unique_ptr< int > > >::value, "static assertion failed" );
+ static_assert( !std::is_convertible< int*, not_null< std::shared_ptr< int > > >::value, "static assertion failed" );
+# endif
+
+ // Do not permit implicit downcasts for move-only types, with or without conversion.
+# if !gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ static_assert( !std::is_convertible< not_null< std::unique_ptr< MyBase > >, not_null< std::unique_ptr< MyDerived > > >::value, "static assertion failed" );
+ static_assert( !std::is_convertible< std::unique_ptr< MyBase >, not_null< std::unique_ptr< MyDerived > > >::value, "static assertion failed" );
+# endif
+
+ static_assert( !std::is_convertible< not_null < int* >, bool >::value, "static assertion failed" );
+ static_assert( !std::is_convertible< not_null < std::unique_ptr< int > >, bool >::value, "static assertion failed" );
+ static_assert( !std::is_convertible< not_null < std::shared_ptr< int > >, bool >::value, "static assertion failed" );
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( UNIQUE_PTR ) && !gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 120 )
+}
+
+CASE( "not_null<>: Copyability and assignability are correctly reported by type traits" )
+{
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( UNIQUE_PTR ) && !gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+ // Permit copy construction and assignment for raw pointers.
+ static_assert( std::is_copy_constructible< not_null< int* > >::value, "static assertion failed" );
+ static_assert( std::is_copy_assignable< not_null< int* > >::value, "static assertion failed" );
+
+ // Do not permit copy construction and assignment for move-only types.
+ static_assert( !std::is_copy_constructible< not_null< std::unique_ptr< int > > >::value, "static assertion failed" );
+# if !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 900 )
+ static_assert( !std::is_copy_assignable< not_null< std::unique_ptr< int > > >::value, "static assertion failed" );
+# endif
+
+ // Permit explicit construction of underlying smart pointer from raw pointer type, using the smart pointer's explicit constructor.
+ static_assert( std::is_constructible< not_null< std::unique_ptr< int > >, int* >::value, "static assertion failed" );
+ static_assert( std::is_constructible< not_null< std::shared_ptr< int > >, int* >::value, "static assertion failed" );
+
+ // Permit explicit construction from underlying pointer.
+ static_assert( std::is_constructible< not_null< MyBase* >, MyDerived* >::value, "static assertion failed" );
+# if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+ static_assert( !std::is_assignable< not_null< MyBase* >&, MyDerived* >::value, "static assertion failed" );
+# endif
+
+ // Do not permit conversion to subclass pointer.
+ static_assert( !std::is_constructible< MyDerived*, not_null< MyBase* > >::value, "static assertion failed" );
+# if !( defined( __NVCC__ ) && gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 800, 900 ) ) // oddly specific bug workaround
+ static_assert( !std::is_assignable< MyDerived*&, not_null< MyBase* > >::value, "static assertion failed" );
+# endif
+
+ // Permit construction and assignment from subclass pointer.
+ static_assert( std::is_constructible< not_null< std::unique_ptr< MyBase > >, std::unique_ptr< MyDerived > >::value, "static assertion failed" );
+# if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR ) && !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 900 )
+ static_assert( !std::is_assignable< not_null< std::unique_ptr< MyBase > >&, std::unique_ptr< MyDerived > >::value, "static assertion failed" );
+# endif
+
+ // Do not permit copy construction and assignment from move-only subclass pointer.
+ static_assert( !std::is_constructible< not_null< std::unique_ptr< MyBase > >, std::unique_ptr< MyDerived > const & >::value, "static assertion failed" );
+# if !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 900 )
+ static_assert( !std::is_assignable< not_null< std::unique_ptr< MyBase > >&, std::unique_ptr< MyDerived > const & >::value, "static assertion failed" );
+# endif
+
+ // Permit construction and assignment from `not_null<>` with subclass pointer.
+ static_assert( std::is_constructible< not_null< std::unique_ptr< MyBase > >, not_null< std::unique_ptr< MyDerived > > >::value, "static assertion failed" );
+ static_assert( std::is_assignable< not_null< std::unique_ptr< MyBase > >&, not_null< std::unique_ptr< MyDerived > > >::value, "static assertion failed" );
+
+ // Do not permit copy construction and assignment from move-only `not_null<>` with subclass pointer.
+ static_assert( !std::is_constructible< not_null< std::unique_ptr< MyBase > >, not_null< std::unique_ptr< MyDerived > > const & >::value, "static assertion failed" );
+# if !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 900 )
+ static_assert( !std::is_assignable< not_null< std::unique_ptr< MyBase > >&, not_null< std::unique_ptr< MyDerived > > const & >::value, "static assertion failed" );
+# endif
+
+ // Permit conversion to superclass pointer.
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ static_assert( std::is_constructible< std::unique_ptr< MyBase >, not_null< std::unique_ptr< MyDerived > > >::value, "static assertion failed" );
+ static_assert( std::is_assignable< std::unique_ptr< MyBase >&, not_null< std::unique_ptr< MyDerived > > >::value, "static assertion failed" );
+# endif
+
+ // Do not permit conversion with copy to move-only superclass pointer.
+ static_assert( !std::is_constructible< std::unique_ptr< MyBase >, not_null< std::unique_ptr< MyDerived > > const & >::value, "static assertion failed" );
+# if !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 900 )
+ static_assert( !std::is_assignable< std::unique_ptr< MyBase >&, not_null< std::unique_ptr< MyDerived > > const & >::value, "static assertion failed" );
+# endif
+
+ // Do not permit construction and assignment from superclass pointer.
+# if !gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ static_assert( !std::is_constructible< not_null< std::unique_ptr< MyDerived > >, std::unique_ptr< MyBase > >::value, "static assertion failed" );
+ static_assert( !std::is_assignable< not_null< std::unique_ptr< MyDerived > >&, std::unique_ptr< MyBase > >::value, "static assertion failed" );
+
+ static_assert( !std::is_constructible< not_null< std::unique_ptr< MyDerived > >, not_null< std::unique_ptr< MyBase > > >::value, "static assertion failed" );
+ static_assert( !std::is_assignable< not_null< std::unique_ptr< MyDerived > >&, not_null< std::unique_ptr< MyBase > > >::value, "static assertion failed" );
+# endif
+
+ // Do not permit conversion to subclass pointer.
+ static_assert( !std::is_constructible< std::unique_ptr< MyDerived >, not_null< std::unique_ptr< MyBase > > >::value, "static assertion failed" );
+ static_assert( !std::is_assignable< std::unique_ptr< MyDerived >&, not_null< std::unique_ptr< MyBase > > >::value, "static assertion failed" );
+
+ // Do not permit conversion to bool
+ static_assert( !std::is_constructible< bool, not_null < int* > >::value, "static assertion failed");
+ static_assert( !std::is_assignable< bool&, not_null < int* > >::value, "static assertion failed");
+
+ static_assert( !std::is_constructible< bool, not_null < std::unique_ptr< int > > >::value, "static assertion failed");
+ static_assert( !std::is_assignable< bool&, not_null < std::unique_ptr< int > > >::value, "static assertion failed");
+
+ static_assert( !std::is_constructible< bool, not_null < std::shared_ptr< int > > >::value, "static assertion failed");
+ static_assert( !std::is_assignable< bool&, not_null < std::shared_ptr< int > > >::value, "static assertion failed");
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( UNIQUE_PTR ) && !gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+}
+
+CASE( "not_null<>: Disallows assignment from unrelated pointers (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+#if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+ MyDerived derived;
+ not_null< MyDerived* > p( &derived );
+
+ not_null< Unrelated* > r( p );
+ not_null< Unrelated* > s( reinterpret_cast< Unrelated* >( p ) );
+#endif
+}
+
+CASE( "not_null<>: Terminates construction from a null pointer value (raw pointer)" )
+{
+ struct F { static void blow() { int * z = gsl_nullptr; not_null<int*> p(z); } };
+
+ EXPECT_THROWS( F::blow() );
+}
+
+CASE( "not_null<>: Terminates construction from related pointer types for null pointer value (raw pointer)" )
+{
+ struct F { static void blow() { MyDerived * z = gsl_nullptr; not_null<MyBase*> p(z); } };
+
+ EXPECT_THROWS( F::blow() );
+}
+
+CASE( "not_null<>: Terminates assignment from a null pointer value (raw pointer)" )
+{
+ int i = 12;
+ not_null<int*> p( &i );
+ int * z = gsl_nullptr;
+
+ EXPECT_THROWS( p = not_null<int*>( z ) );
+}
+
+CASE( "not_null<>: Terminates assignment from related pointer types for null pointer value (raw pointer)" )
+{
+ MyDerived * z = gsl_nullptr;
+ MyDerived derived;
+ not_null< MyBase* > p( &derived );
+
+ EXPECT_THROWS( p = not_null<MyDerived*>( z ) );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (raw pointer)" )
+{
+ int i = 12;
+
+ not_null< int* > p( &i );
+
+ EXPECT( p == &i );
+}
+
+CASE( "not_null<>: Returns underlying pointer with get() (raw pointer)" )
+{
+#if !gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ int i = 12;
+ not_null< int* > p( &i );
+
+ int* pg = p.get();
+ EXPECT( pg == &i );
+#endif
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (raw pointer) with make_not_null()" )
+{
+ int i = 12;
+
+ not_null< int* > p = make_not_null( &i );
+
+ EXPECT( p == &i );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (raw pointer) with deduction guide" )
+{
+#if gsl_HAVE( DEDUCTION_GUIDES )
+ int i = 12;
+
+ not_null p( &i );
+
+ EXPECT( p == &i );
+#endif
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a non-null underlying pointer (raw pointer)" )
+{
+ int i = 12;
+
+ not_null< const int* > p( &i );
+
+ EXPECT( p == &i );
+}
+
+CASE( "not_null<>: Converts to underlying pointer (raw pointer)" )
+{
+ int i = 12;
+ not_null< int* > p( &i );
+
+ take_raw<int>( p );
+}
+
+CASE( "as_nullable: Converts to underlying pointer (raw pointer)" )
+{
+ int i = 12;
+ not_null< int* > p( &i );
+
+ take_raw<int>( as_nullable( p ) );
+#if gsl_HAVE( MOVE_FORWARD )
+ take_raw<int>( as_nullable( std::move( p ) ) );
+#endif
+}
+
+CASE( "not_null<>: Allows to construct from a non-null related pointer (raw pointer)" )
+{
+ MyDerived derived;
+ not_null< MyBase* > p( &derived );
+
+ EXPECT( p == &derived );
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a non-null related pointer (raw pointer)" )
+{
+ MyDerived derived;
+ not_null< const MyBase* > p( &derived );
+
+ EXPECT( p == &derived );
+}
+
+CASE( "not_null<>: Allows to construct from a not_null related pointer type (raw pointer)" )
+{
+ MyDerived derived;
+ not_null< MyDerived* > p( &derived );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< MyBase* > q = p;
+#else
+ not_null< MyBase* > q(p); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( q == p );
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a not_null related pointer type (raw pointer)" )
+{
+ MyDerived derived;
+ not_null< MyDerived* > p( &derived );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< const MyBase* > q = p;
+#else
+ not_null< const MyBase* > q(p); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( q == p );
+}
+
+CASE( "not_null<>: Converts to a related pointer (raw pointer)" )
+{
+ MyDerived derived;
+ not_null< MyDerived* > p( &derived );
+
+ take_raw<MyBase>( p );
+}
+
+CASE( "as_nullable: Converts to a related pointer (raw pointer)" )
+{
+ MyDerived derived;
+ not_null< MyDerived* > p( &derived );
+
+ take_raw<MyBase>( as_nullable( p ) );
+}
+
+CASE( "not_null<>: Allows assignment from a not_null related pointer type (raw pointer)" )
+{
+ MyDerived derived;
+ not_null< MyDerived* > p( &derived );
+ not_null< MyBase* > q( p );
+
+ q = p;
+
+ EXPECT( q == p );
+}
+
+CASE( "not_null<>: Allows assignment to a const pointer from a not_null related pointer type (raw pointer)" )
+{
+ MyDerived derived;
+ not_null< MyDerived* > p( &derived );
+ not_null< const MyBase* > q( p );
+
+ q = p;
+
+ EXPECT( q == p );
+}
+
+CASE( "not_null<>: Allows indirect member access (raw pointer)" )
+{
+ using namespace nonlocal;
+ S s = { 'a', 7 };
+ not_null< S* > p( &s );
+
+ EXPECT( p->c == 'a' );
+ EXPECT( p->i == 7 );
+}
+
+CASE( "not_null<>: Allows dereferencing (raw pointer)" )
+{
+ int i = 12;
+ not_null< int* > p( &i );
+
+ EXPECT( *p == i );
+}
+
+CASE( "not_null<>: Allows to check whether object is valid (raw pointer)" )
+{
+ int i = 12;
+ not_null< int* > p( &i );
+
+ EXPECT( gsl_lite::is_valid( p ) );
+
+#if gsl_HAVE( MOVE_FORWARD )
+ not_null< int* > q( std::move( p ) );
+
+ EXPECT( gsl_lite::is_valid( p ) ); // for raw pointers, moving `not_null<>` just makes a copy
+ EXPECT( gsl_lite::is_valid( q ) );
+#endif
+}
+
+#if gsl_HAVE( MOVE_FORWARD )
+template< class T >
+void move_to( T& dest, T& src )
+{
+ dest = std::move( src );
+}
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+#if gsl_HAVE( SHARED_PTR )
+CASE( "not_null<>: Terminates swap of a moved-from value (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >( 12 );
+ not_null< shared_ptr< int > > p1( pi );
+ not_null< shared_ptr< int > > p2( std::move( p1 ) );
+
+ EXPECT_THROWS( swap( p1, p2 ) );
+ EXPECT_THROWS( swap( p2, p1 ) );
+}
+
+CASE( "not_null<>: Tolerates self-move-assignment of a moved-from value (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >( 12 );
+ not_null< shared_ptr< int > > p1( pi );
+ not_null< shared_ptr< int > > p2( std::move( p1 ) );
+
+ EXPECT_NO_THROW( move_to(p1, p1 ) ); // use extra indirection to suppress compiler warning about explicit self-move
+}
+
+CASE( "not_null<>: Terminates self-swap of a moved-from value (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >( 12 );
+ not_null< shared_ptr< int > > p1( pi );
+ not_null< shared_ptr< int > > p2( std::move( p1 ) );
+
+ EXPECT_THROWS( swap( p1, p1 ) );
+}
+
+CASE( "not_null<>: Terminates construction from a null pointer value (shared_ptr)" )
+{
+ struct F { static void blow() { shared_ptr< int > z = gsl_nullptr; not_null< shared_ptr< int > > p(z); } };
+
+ EXPECT_THROWS( F::blow() );
+}
+
+CASE( "not_null<>: Terminates construction from related pointer types for null pointer value (shared_ptr)" )
+{
+ struct F { static void blow() { shared_ptr< MyDerived > z = gsl_nullptr; not_null< shared_ptr< MyBase > > p(z); } };
+
+ EXPECT_THROWS( F::blow() );
+}
+
+CASE( "not_null<>: Terminates assignment from a null pointer value (shared_ptr)" )
+{
+ not_null< shared_ptr< int > > p( std::make_shared< int >(12) );
+ shared_ptr< int > z = gsl_nullptr;
+
+ EXPECT_THROWS( p = not_null< shared_ptr< int > >( z ) );
+}
+
+CASE( "not_null<>: Terminates assignment from related pointer types for null pointer value (shared_ptr)" )
+{
+ shared_ptr< MyDerived > z = gsl_nullptr;
+ not_null< shared_ptr< MyBase > > p( std::make_shared< MyDerived >() );
+
+ EXPECT_THROWS( p = not_null< shared_ptr< MyDerived > >( z ) );
+}
+
+CASE( "not_null<>: Terminates propagation of a moved-from value (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ not_null< shared_ptr< int > > p( std::move( pi ) );
+ not_null< shared_ptr< int > > q( std::move( p ) );
+
+ EXPECT_THROWS( not_null< shared_ptr< int > > v( p ) );
+ EXPECT_THROWS( not_null< shared_ptr< int > > v( std::move( p ) ) );
+ EXPECT_THROWS( q = p );
+ EXPECT_THROWS( q = std::move( p ) );
+}
+
+CASE( "not_null<>: Allows self-swap (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >( 12 );
+ not_null< shared_ptr< int > > p( pi );
+
+ EXPECT_NO_THROW( swap( p, p ) );
+ EXPECT( p == pi );
+}
+
+CASE( "not_null<>: Allows swap (shared_ptr)" )
+{
+ shared_ptr< int > pi1 = std::make_shared< int >( 12 );
+ shared_ptr< int > pi2 = std::make_shared< int >( 34 );
+ not_null< shared_ptr< int > > p1( pi1 );
+ not_null< shared_ptr< int > > p2( pi2 );
+
+ EXPECT_NO_THROW( swap( p1, p2 ) );
+ EXPECT( p1 == pi2 );
+ EXPECT( p2 == pi1 );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ not_null< shared_ptr< int > > p( pi );
+
+ EXPECT( p == pi );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null raw pointer with explicit conversion (shared_ptr)" )
+{
+ int* i = new int(12);
+ not_null< shared_ptr< int > > p( i );
+}
+
+CASE( "not_null<>: Returns underlying pointer or raw pointer with get() (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ not_null< shared_ptr< int > > p( pi );
+
+#if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ int* pg = p.get();
+ EXPECT( pg == pi.get() );
+#else
+ shared_ptr< int > const & pg = p.get();
+ EXPECT( pg == pi );
+#endif
+}
+
+CASE( "not_null<>: Allows to move from a not_null pointer to an underlying pointer (shared_ptr)" )
+{
+#if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ int* raw(pi.get());
+
+ not_null< shared_ptr< int > > p ( std::move(pi) ); // There...
+ pi = std::move(p); // ...and back again.
+
+ EXPECT_THROWS( (void) *p );
+ EXPECT( pi.get() == raw );
+#endif
+}
+
+CASE( "as_nullable: Allows to move from a not_null pointer to an underlying pointer (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ int* raw(pi.get());
+
+ not_null< shared_ptr< int > > p ( std::move(pi) ); // There...
+ pi = as_nullable( std::move(p) ); // ...and back again.
+
+ EXPECT_THROWS( (void) *p );
+ EXPECT( pi.get() == raw );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (shared_ptr) with make_not_null()" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+
+ not_null< shared_ptr< int > > p = make_not_null( pi );
+
+ EXPECT( p == pi );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (shared_ptr) with deduction guide" )
+{
+#if gsl_HAVE( DEDUCTION_GUIDES )
+ shared_ptr< int > pi = std::make_shared< int >(12);
+
+ not_null p( pi );
+
+ EXPECT( p == pi );
+#endif
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a non-null underlying pointer (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ not_null< shared_ptr< const int > > p( pi );
+
+ EXPECT( p == pi );
+}
+
+CASE( "not_null<>: Converts to underlying pointer (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >();
+ not_null< shared_ptr< int > > p( pi );
+
+ take_shared_by_val<int>( p );
+ take_shared_by_ref<int>( p );
+}
+
+CASE( "as_nullable: Converts to underlying pointer (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >();
+ not_null< shared_ptr< int > > p( pi );
+
+ take_shared_by_val<int>( as_nullable( p ) );
+ take_shared_by_ref<int>( as_nullable( p ) );
+}
+
+CASE( "as_nullable: Terminates for moved-from pointer (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >();
+ not_null< shared_ptr< int > > p( pi );
+ not_null< shared_ptr< int > > p2( std::move( p ) );
+
+ EXPECT_THROWS( (void) as_nullable( p ) );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null related pointer (shared_ptr)" )
+{
+ shared_ptr< MyDerived > pderived = std::make_shared< MyDerived >();
+ not_null< shared_ptr< MyBase > > p( pderived );
+
+ EXPECT( p == pderived );
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a non-null related pointer (shared_ptr)" )
+{
+ shared_ptr< MyDerived > pderived = std::make_shared< MyDerived >();
+ not_null< shared_ptr< const MyBase > > p( pderived );
+
+ EXPECT( p == pderived );
+}
+
+CASE( "not_null<>: Allows to construct from a not_null related pointer type (shared_ptr)" )
+{
+ shared_ptr< MyDerived > pderived = std::make_shared< MyDerived >();
+ not_null< shared_ptr< MyDerived > > p( pderived );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< shared_ptr< MyBase > > q = p;
+#else
+ not_null< shared_ptr< MyBase > > q(p); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( q == p );
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a not_null related pointer type (shared_ptr)" )
+{
+ shared_ptr< MyDerived > pderived = std::make_shared< MyDerived >();
+ not_null< shared_ptr< MyDerived > > p( pderived );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< shared_ptr< const MyBase > > q = p;
+#else
+ not_null< shared_ptr< const MyBase > > q(p); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( q == p );
+}
+
+CASE( "not_null<>: Converts to a related pointer (shared_ptr)" )
+{
+ shared_ptr< MyDerived > pderived = std::make_shared< MyDerived >();
+ not_null< shared_ptr< MyDerived > > p( pderived );
+
+ take_shared_by_val<MyBase>( p );
+ take_shared_by_ref<MyBase>( p );
+}
+
+CASE( "as_nullable: Converts to a related pointer (shared_ptr)" )
+{
+ shared_ptr< MyDerived > pderived = std::make_shared< MyDerived >();
+ not_null< shared_ptr< MyDerived > > p( pderived );
+
+ take_shared_by_val<MyBase>( as_nullable(p) );
+ take_shared_by_ref<MyBase>( as_nullable(p) );
+}
+
+CASE( "not_null<>: Allows assignment from a not_null related pointer type (shared_ptr)" )
+{
+ shared_ptr< MyDerived > pderived = std::make_shared< MyDerived >();
+ not_null< shared_ptr< MyDerived > > p( pderived );
+ not_null< shared_ptr< MyBase > > q( p );
+
+ q = p;
+
+ EXPECT( q == p );
+}
+
+CASE( "not_null<>: Allows assignment to a const pointer from a not_null related pointer type (shared_ptr)" )
+{
+ shared_ptr< MyDerived > pderived = std::make_shared< MyDerived >();
+ not_null< shared_ptr< MyDerived > > p( pderived );
+ not_null< shared_ptr< const MyBase > > q( p );
+
+ q = p;
+
+ EXPECT( q == p );
+}
+
+CASE( "not_null<>: Allows indirect member access (shared_ptr)" )
+{
+ using namespace nonlocal;
+ S s = { 'a', 7 };
+ not_null< shared_ptr< S > > p( std::make_shared< S >(s) );
+
+ EXPECT( p->c == 'a' );
+ EXPECT( p->i == 7 );
+}
+
+CASE( "not_null<>: Allows dereferencing (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ not_null< shared_ptr< int > > p( pi );
+
+ EXPECT( *p == *pi );
+}
+
+CASE( "not_null<>: Allows to check whether object is valid (shared_ptr)" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ not_null< shared_ptr< int > > p( pi );
+
+ EXPECT( gsl_lite::is_valid( p ) );
+
+ not_null< shared_ptr< int > > q( std::move( p ) );
+
+ EXPECT_NOT( gsl_lite::is_valid( p ) );
+ EXPECT( gsl_lite::is_valid( q ) );
+}
+
+#endif // gsl_HAVE( SHARED_PTR )
+
+#if gsl_HAVE( UNIQUE_PTR )
+
+template<typename T>
+unique_ptr<T> my_make_unique()
+{
+ return unique_ptr<T>(new T());
+}
+
+template<typename T, typename Arg>
+unique_ptr<T> my_make_unique(Arg&& arg)
+{
+ return unique_ptr<T>(new T(std::forward<Arg>(arg)));
+}
+
+CASE( "not_null<>: Terminates swap of a moved-from value (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >( 12 );
+ not_null< unique_ptr< int > > p1( std::move( pi ) );
+ not_null< unique_ptr< int > > p2( std::move( p1 ) );
+
+ EXPECT_THROWS( swap( p1, p2 ) );
+ EXPECT_THROWS( swap( p2, p1 ) );
+}
+
+CASE( "not_null<>: Tolerates self-move-assignment of a moved-from value (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >( 12 );
+ not_null< unique_ptr< int > > p1( std::move( pi ) );
+ not_null< unique_ptr< int > > p2( std::move( p1 ) );
+
+ EXPECT_NO_THROW( move_to(p1, p1 ) ); // use extra indirection to suppress compiler warning about explicit self-move
+}
+
+CASE( "not_null<>: Terminates self-swap of a moved-from value (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >( 12 );
+ not_null< unique_ptr< int > > p1( std::move( pi ) );
+ not_null< unique_ptr< int > > p2( std::move( p1 ) );
+
+ EXPECT_THROWS( swap(p1, p1) );
+}
+
+CASE( "not_null<>: Terminates construction from a null pointer value (unique_ptr)" )
+{
+ struct F { static void blow() { unique_ptr< int > z = gsl_nullptr; not_null< unique_ptr< int > > p(std::move(z)); } };
+
+ EXPECT_THROWS( F::blow() );
+}
+
+CASE( "not_null<>: Terminates construction from related pointer types for null pointer value (unique_ptr)" )
+{
+ struct F { static void blow() { unique_ptr< MyDerived > z = gsl_nullptr; not_null< unique_ptr< MyBase > > p(std::move(z)); } };
+
+ EXPECT_THROWS( F::blow() );
+}
+
+CASE( "not_null<>: Terminates assignment from a null pointer value (unique_ptr)" )
+{
+ not_null< unique_ptr< int > > p( my_make_unique< int >(12) );
+ unique_ptr< int > z = gsl_nullptr;
+
+ EXPECT_THROWS( p = not_null< unique_ptr< int > >( std::move(z) ) );
+}
+
+CASE( "not_null<>: Terminates assignment from related pointer types for null pointer value (unique_ptr)" )
+{
+ unique_ptr< MyDerived > z = gsl_nullptr;
+ not_null< unique_ptr< MyBase > > p( my_make_unique< MyDerived >() );
+
+ EXPECT_THROWS( p = not_null< unique_ptr< MyDerived > >( std::move(z) ) );
+}
+
+CASE( "not_null<>: Terminates propagation of a moved-from value (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ not_null< unique_ptr< int > > p( std::move( pi ) );
+ not_null< unique_ptr< int > > q( std::move( p ) );
+
+ EXPECT_THROWS( not_null< unique_ptr< int > >( std::move( p ) ) );
+ EXPECT_THROWS( q = std::move( p ) );
+}
+
+CASE( "not_null<>: Allows self-swap (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >( 12 );
+ int* raw( pi.get() );
+ not_null< unique_ptr< int > > p( std::move( pi ) );
+
+ EXPECT_NO_THROW( swap( p, p ) );
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows swap (unique_ptr)" )
+{
+ unique_ptr< int > pi1 = my_make_unique< int >( 12 );
+ unique_ptr< int > pi2 = my_make_unique< int >( 34 );
+ int* raw1( pi1.get() );
+ int* raw2( pi2.get() );
+ not_null< unique_ptr< int > > p1( std::move( pi1 ) );
+ not_null< unique_ptr< int > > p2( std::move( pi2 ) );
+
+ EXPECT_NO_THROW( swap( p1, p2 ) );
+ EXPECT( &*p1 == raw2 );
+ EXPECT( &*p2 == raw1 );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+ not_null< unique_ptr< int > > p( std::move(pi) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null raw pointer with explicit conversion (unique_ptr)" )
+{
+ int* i = new int(12);
+ not_null< unique_ptr< int > > p( i );
+}
+
+CASE( "not_null<>: Returns underlying pointer or raw pointer with get() (unique_ptr)" )
+{
+#if gsl_CONFIG( TRANSPARENT_NOT_NULL ) || gsl_CONFIG( NOT_NULL_GET_BY_CONST_REF )
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+ not_null< unique_ptr< int > > p( std::move(pi) );
+
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ int* pg = p.get();
+ EXPECT( pg == raw );
+# else // gsl_CONFIG( NOT_NULL_GET_BY_CONST_REF )
+ int* pg = p.get().get();
+ EXPECT( pg == raw );
+# endif
+#endif
+}
+
+CASE( "not_null<>: Allows to move from a not_null pointer to an underlying pointer (unique_ptr)" )
+{
+#if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+
+ not_null< unique_ptr< int > > p ( std::move(pi) ); // There...
+ pi = std::move(p); // ...and back again.
+
+ EXPECT_THROWS( (void) *p );
+ EXPECT( pi.get() == raw );
+#endif
+}
+
+CASE( "as_nullable: Allows to move from a not_null pointer to an underlying pointer (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+
+ not_null< unique_ptr< int > > p ( std::move(pi) ); // There...
+ pi = as_nullable( std::move(p) ); // ...and back again.
+
+ EXPECT_THROWS( (void) *p );
+ EXPECT( pi.get() == raw );
+}
+
+CASE( "not_null<>: Allows to move to a related pointer from a not_null pointer (unique_ptr)" )
+{
+#if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p ( std::move(pderived) );
+ unique_ptr< MyBase > pbase = std::move(p);
+
+ EXPECT_THROWS( (void) *p );
+ EXPECT( pbase.get() == raw );
+#endif
+}
+
+CASE( "as_nullable: Allows to move to a related pointer from a not_null pointer (unique_ptr)" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p ( std::move(pderived) );
+ unique_ptr< MyBase > pbase = as_nullable( std::move(p) );
+
+ EXPECT_THROWS( (void) *p );
+ EXPECT( pbase.get() == raw );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (unique_ptr) with make_not_null()" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+
+ not_null< unique_ptr< int > > p = make_not_null( std::move(pi) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null underlying pointer (unique_ptr) with deduction guide" )
+{
+#if gsl_HAVE( DEDUCTION_GUIDES )
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+
+ not_null p( std::move(pi) );
+
+ EXPECT( &*p == raw );
+#endif
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a non-null underlying pointer (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+ not_null< unique_ptr< const int > > p( std::move(pi) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Converts to underlying pointer (unique_ptr)" )
+{
+#if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ unique_ptr< int > pi = my_make_unique< int >();
+ not_null< unique_ptr< int > > p( std::move(pi) );
+
+ take_unique_by_val<int>( std::move(p) );
+ //take_unique_by_ref<int>( p ); // We sacrifice the ability to convert to `unique_ptr<> const &`, cf. comment regarding conversion operators in gsl-lite.hpp.
+#endif
+}
+
+CASE( "as_nullable: Converts to underlying pointer (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >();
+ not_null< unique_ptr< int > > p( std::move(pi) );
+
+ take_unique_by_ref<int>( as_nullable( p ) );
+ take_unique_by_val<int>( as_nullable( std::move( p ) ) );
+}
+
+CASE( "as_nullable: Terminates for moved-from pointer (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >();
+ not_null< unique_ptr< int > > p( std::move( pi ) );
+ not_null< unique_ptr< int > > p2( std::move( p ) );
+
+ EXPECT_THROWS( (void) as_nullable( p ) );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null related pointer (unique_ptr)" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyBase > > p( std::move(pderived) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a non-null related pointer (unique_ptr)" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< const MyBase > > p( std::move(pderived) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows to construct from a not_null related pointer type (unique_ptr)" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< unique_ptr< MyBase > > q = std::move(p);
+#else
+ not_null< unique_ptr< MyBase > > q(std::move(p)); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Allows to construct a const pointer from a not_null related pointer type (unique_ptr)" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< unique_ptr< const MyBase > > q = std::move(p);
+#else
+ not_null< unique_ptr< const MyBase > > q(std::move(p)); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Converts to a related pointer (unique_ptr)" )
+{
+#if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+
+ take_unique_by_val<MyBase>( std::move(p) );
+ //take_unique_by_ref<MyBase>( p ); // We sacrifice the ability to convert to `unique_ptr<> const &`, cf. comment regarding conversion operators in gsl-lite.hpp.
+#endif
+}
+
+CASE( "as_nullable: Converts to a related pointer (unique_ptr)" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+
+ take_unique_by_val<MyBase>( as_nullable( std::move(p) ) );
+}
+
+CASE( "not_null<>: Allows assignment from a not_null related pointer type (unique_ptr)" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+ not_null< unique_ptr< MyBase > > q( my_make_unique< MyBase >() );
+
+ q = std::move(p);
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Allows assignment to a const pointer from a not_null related pointer type (unique_ptr)" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+ not_null< unique_ptr< const MyBase > > q( my_make_unique< MyBase >() );
+
+ q = std::move(p);
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Allows indirect member access (unique_ptr)" )
+{
+ using namespace nonlocal;
+ S s = { 'a', 7 };
+ not_null< unique_ptr< S > > p( my_make_unique< S >(s) );
+
+ EXPECT( p->c == 'a' );
+ EXPECT( p->i == 7 );
+}
+
+CASE( "not_null<>: Allows dereferencing (unique_ptr)" )
+{
+ int i = 12;
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ not_null< unique_ptr< int > > p( std::move(pi) );
+
+ EXPECT( *p == i );
+}
+
+CASE( "not_null<>: Allows to check whether object is valid (unique_ptr)" )
+{
+ unique_ptr< int > pi = my_make_unique< int >( 12 );
+ not_null< unique_ptr< int > > p( std::move(pi) );
+
+ EXPECT( gsl_lite::is_valid( p ) );
+
+ not_null< unique_ptr< int > > q( std::move( p ) );
+
+ EXPECT_NOT( gsl_lite::is_valid( p ) );
+ EXPECT( gsl_lite::is_valid( q ) );
+}
+
+#endif // gsl_HAVE( UNIQUE_PTR )
+
+#if gsl_HAVE( UNIQUE_PTR ) && gsl_HAVE( SHARED_PTR )
+
+CASE( "not_null<>: Allows to construct a not_null<shared_ptr<T>> from a non-null unique_ptr<T>" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+ not_null< shared_ptr< int > > p( std::move(pi) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows to construct a not_null<shared_ptr<const T>> from a non-null unique_ptr<T>" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+ not_null< shared_ptr< const int > > p( std::move(pi) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows to construct a not_null<shared_ptr<T>> from a related non-null unique_ptr<U>" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< shared_ptr< MyBase > > p( std::move(pderived) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows to construct a not_null<shared_ptr<const T>> from a related non-null unique_ptr<U>" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< shared_ptr< const MyBase > > p( std::move(pderived) );
+
+ EXPECT( &*p == raw );
+}
+
+CASE( "not_null<>: Allows to construct a not_null<shared_ptr<T>> from a not_null<unique_ptr<T>>" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+ not_null< unique_ptr< int > > p( std::move(pi) );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< shared_ptr< int > > q = std::move(p);
+#else
+ not_null< shared_ptr< int > > q(std::move(p)); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Allows to convert to weak_ptr<T> from a not_null<shared_ptr<T>>" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ int* raw(pi.get());
+ not_null< shared_ptr< int > > p( std::move(pi) );
+
+#if gsl_CPP11_OR_GREATER
+ std::weak_ptr< int > q = p;
+ std::vector< std::weak_ptr< int > > v;
+ v.emplace_back( p );
+#else
+ std::weak_ptr< int > q(p); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT_NOT( q.expired() );
+ EXPECT( q.lock().get() == raw );
+}
+
+// C++14 has ambiguity issues with constructors and conversion operators that were fixed in C++17,
+// cf. https://github.com/gsl-lite/gsl-lite/issues/275#issuecomment-678640600.
+// Also, Clang ≤ 5 may pretend to support C++17 but it still suffers from the conversion ambiguity.
+#if gsl_CPP17_OR_GREATER && ! ( gsl_BETWEEN(gsl_COMPILER_CLANG_VERSION, 1, 600) || gsl_BETWEEN(gsl_COMPILER_APPLECLANG_VERSION, 1, 1000) )
+CASE( "not_null<>: Allows to convert from a not_null<shared_ptr<T>> to a user-defined type with explicit conversion constructor" )
+{
+ shared_ptr< int > pi = std::make_shared< int >(12);
+ not_null< shared_ptr< int > > p( std::move(pi) );
+
+ ExplicitFromShared< int > q(p);
+ (void) q;
+}
+#endif // gsl_CPP17_OR_GREATER
+
+CASE( "not_null<>: Allows to construct a not_null<shared_ptr<const T>> from a not_null<unique_ptr<T>>" )
+{
+ unique_ptr< int > pi = my_make_unique< int >(12);
+ int* raw(pi.get());
+ not_null< unique_ptr< int > > p( std::move(pi) );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< shared_ptr< const int > > q = std::move(p);
+#else
+ not_null< shared_ptr< const int > > q(std::move(p)); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Allows to construct a not_null<shared_ptr<T>> from a related not_null<unique_ptr<U>>" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< shared_ptr< MyBase > > q = std::move(p);
+#else
+ not_null< shared_ptr< MyBase > > q(std::move(p)); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Allows to construct a not_null<shared_ptr<const T>> from a related not_null<unique_ptr<U>>" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+
+#if gsl_CPP11_OR_GREATER
+ not_null< shared_ptr< const MyBase > > q = std::move(p);
+#else
+ not_null< shared_ptr< const MyBase > > q(std::move(p)); // in C++98, we cannot differentiate between implicit and explicit cases, so conversion is always explicit
+#endif
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Allows assignment to a not_null<shared_ptr<T>> from a related not_null<unique_ptr<U>>" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+ not_null< shared_ptr< MyBase > > q( std::make_shared< MyBase >() );
+
+ q = std::move(p);
+
+ EXPECT( &*q == raw );
+}
+
+CASE( "not_null<>: Allows assignment to a not_null<shared_ptr<const T>> from a related not_null<unique_ptr<U>>" )
+{
+ unique_ptr< MyDerived > pderived = my_make_unique< MyDerived >();
+ MyDerived* raw(pderived.get());
+ not_null< unique_ptr< MyDerived > > p( std::move(pderived) );
+ not_null< shared_ptr< const MyBase > > q( std::make_shared< MyBase >() );
+
+ q = std::move(p);
+
+ EXPECT( &*q == raw );
+}
+
+# if gsl_HAVE( VARIADIC_TEMPLATE )
+# if !gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 120, 130 ) // VS 2013
+CASE( "not_null<>: make_unique<T>() returns not_null<unique_ptr<T>>" )
+{
+ not_null< unique_ptr< int > > p = make_unique< int >();
+ unique_ptr< int > q = std::move( p );
+ (void) q;
+
+ EXPECT( q.get() != nullptr );
+
+}
+# endif // !gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 120, 130 )
+CASE( "not_null<>: make_shared<T>() returns not_null<shared_ptr<T>>" )
+{
+ not_null< shared_ptr< int > > p = make_shared< int >();
+ shared_ptr< int > q = std::move( p );
+ (void) q;
+
+ EXPECT( q.get() != nullptr );
+}
+# endif // gsl_HAVE( VARIADIC_TEMPLATE )
+
+#endif // gsl_HAVE( UNIQUE_PTR ) && gsl_HAVE( SHARED_PTR )
+
+CASE( "not_null<>: Allows assignment from a non-null bare recast pointer" )
+{
+ MyDerived derived;
+ not_null< MyDerived* > p( &derived );
+
+ not_null< Unrelated* > t( reinterpret_cast< Unrelated* >( &*p ) );
+
+ EXPECT( &*p == reinterpret_cast< MyDerived* >( &*t ) );
+}
+
+CASE( "not_null<>: Allows implicit conversion to underlying type" )
+{
+ struct F { static bool helper( not_null< int* > p ) { return *p == 12; } };
+
+ int i = 12;
+ not_null< int* > p( &i );
+
+ EXPECT( F::helper( p ) );
+}
+
+CASE( "not_null<>: Allows to construct from a non-null user-defined ref-counted type" )
+{
+ int i = 12;
+ RefCounted< int > rp = RefCounted<int>( &i );
+
+ not_null< int*> p( rp );
+
+ EXPECT( p == &i );
+}
+
+namespace {
+
+// provide not_null pointers to compare:
+
+struct NotNull
+{
+ int vs[2];
+ int * pv1; int const * pv2;
+
+ NotNull()
+ : pv1( &vs[ 0 ] ), pv2( &vs[ 1 ] )
+ {
+ vs[0] = 7;
+ vs[1] = 42;
+ }
+
+ not_null< int * > p1() const { return not_null< int * >( pv1 ); }
+ not_null< int const * > p2() const { return not_null< int const * >( pv2 ); }
+};
+}
+
+CASE( "not_null<>: Allows to compare equal to another not_null of the same type" )
+{
+ NotNull _;
+
+ EXPECT( _.p1() == _.p1() );
+ EXPECT_NOT( _.p1() == _.p2() );
+}
+
+CASE( "not_null<>: Allows to compare unequal to another not_null of the same type" )
+{
+ NotNull _;
+
+ EXPECT( _.p1() != _.p2() );
+ EXPECT_NOT( _.p1() != _.p1() );
+}
+
+CASE( "not_null<>: Allows to compare less than another not_null of the same type" )
+{
+ NotNull _;
+
+ EXPECT_NOT( _.p1() < _.p1() );
+ EXPECT( ( _.p1() < _.p2() ) == ( _.pv1 < _.pv2 ) );
+ EXPECT( ( _.p2() < _.p1() ) == ( _.pv2 < _.pv1 ) );
+}
+
+CASE( "not_null<>: Allows to compare less than or equal to another not_null of the same type" )
+{
+ NotNull _;
+
+ EXPECT( ( _.p1() <= _.p1() ) );
+ EXPECT( ( _.p1() <= _.p2() ) == ( _.pv1 <= _.pv2 ) );
+ EXPECT( ( _.p2() <= _.p1() ) == ( _.pv2 <= _.pv1 ) );
+}
+
+CASE( "not_null<>: Allows to compare greater than another not_null of the same type" )
+{
+ NotNull _;
+
+ EXPECT_NOT( _.p1() > _.p1() );
+ EXPECT( ( _.p1() > _.p2() ) == ( _.pv1 > _.pv2 ) );
+ EXPECT( ( _.p2() > _.p1() ) == ( _.pv2 > _.pv1 ) );
+}
+
+CASE( "not_null<>: Allows to compare greater than or equal to another not_null of the same type" )
+{
+ NotNull _;
+
+ EXPECT( _.p1() >= _.p1() );
+ EXPECT( ( _.p1() >= _.p2() ) == ( _.pv1 >= _.pv2 ) );
+ EXPECT( ( _.p2() >= _.p1() ) == ( _.pv2 >= _.pv1 ) );
+}
+
+#if gsl_STDLIB_CPP20_OR_GREATER
+CASE( "not_null<>: Allows to 3-way compare with another not_null of the same type" )
+{
+ NotNull _;
+
+ EXPECT( ( _.p1() <=> _.p1() == 0 ) );
+ EXPECT( ( ( _.p1() <=> _.p2() ) == ( _.pv1 <=> _.pv2 ) ) );
+ EXPECT( ( ( _.p2() <=> _.p1() ) == ( _.pv2 <=> _.pv1 ) ) );
+}
+#endif // gsl_STDLIB_CPP20_OR_GREATER
+
+// raw pointer
+
+CASE( "not_null<>: Allows to compare equal to a raw pointer of the same type" )
+{
+ NotNull _;
+
+ EXPECT( _.p1() == _.pv1 );
+ EXPECT_NOT( _.p1() == _.pv2 );
+}
+
+CASE( "not_null<>: Allows to compare unequal to a raw pointer of the same type" )
+{
+ NotNull _;
+
+ EXPECT( _.p1() != _.pv2 );
+ EXPECT_NOT( _.p1() != _.pv1 );
+}
+
+CASE( "not_null<>: Allows to compare less than a raw pointer of the same type" )
+{
+ NotNull _;
+
+ EXPECT_NOT( _.p1() < _.pv1 );
+ EXPECT( ( _.p1() < _.pv2 ) == ( _.pv1 < _.pv2 ) );
+ EXPECT( ( _.p2() < _.pv1 ) == ( _.pv2 < _.pv1 ) );
+}
+
+CASE( "not_null<>: Allows to compare less than or equal to a raw pointer of the same type" )
+{
+ NotNull _;
+
+ EXPECT( ( _.p1() <= _.pv1 ) );
+ EXPECT( ( _.p1() <= _.pv2 ) == ( _.pv1 <= _.pv2 ) );
+ EXPECT( ( _.p2() <= _.pv1 ) == ( _.pv2 <= _.pv1 ) );
+}
+
+CASE( "not_null<>: Allows to compare greater than a raw pointer of the same type" )
+{
+ NotNull _;
+
+ EXPECT_NOT( _.p1() > _.pv1 );
+ EXPECT( ( _.p1() > _.pv2 ) == ( _.pv1 > _.pv2 ) );
+ EXPECT( ( _.p2() > _.pv1 ) == ( _.pv2 > _.pv1 ) );
+}
+
+CASE( "not_null<>: Allows to compare greater than or equal to a raw pointer of the same type" )
+{
+ NotNull _;
+
+ EXPECT( _.p1() >= _.pv1 );
+ EXPECT( ( _.p1() >= _.pv2 ) == ( _.pv1 >= _.pv2 ) );
+ EXPECT( ( _.p2() >= _.pv1 ) == ( _.pv2 >= _.pv1 ) );
+}
+
+#if gsl_STDLIB_CPP20_OR_GREATER
+CASE( "not_null<>: Allows to 3-way compare with a raw pointer of the same type" )
+{
+ NotNull _;
+
+ EXPECT( ( _.p1() <=> _.pv1 == 0 ) );
+ EXPECT( ( ( _.p1() <=> _.pv2 ) == ( _.pv1 <=> _.pv2 ) ) );
+ EXPECT( ( ( _.p2() <=> _.pv1 ) == ( _.pv2 <=> _.pv1 ) ) );
+}
+#endif // gsl_STDLIB_CPP20_OR_GREATER
+
+// user-defined types to check element_type deduction
+
+template<class T>
+struct NormalPtr
+{
+ typedef T element_type;
+ T* ptr;
+ T& operator*() { return *ptr; }
+ NormalPtr(T* ptr) : ptr(ptr) {}
+};
+
+template<class T>
+struct ETLessNormalPtr
+{
+ // no element_type typedef
+ T* ptr;
+ T& operator*() { return *ptr; }
+ ETLessNormalPtr(T* ptr) : ptr(ptr) {}
+};
+
+template<class T>
+struct WeirdPtr // element_type and *p's type differ
+{
+ typedef T element_type;
+ T* ptr;
+ double operator*() { return *ptr; }
+ WeirdPtr(T* ptr) : ptr(ptr) {}
+};
+
+template<class T>
+struct ETLessWeirdPtr // // element_type and type T differ
+{
+ // no element_type typedef
+ T* ptr;
+ double operator*() { return *ptr; }
+ ETLessWeirdPtr(T* ptr) : ptr(ptr) {}
+};
+
+#if gsl_HAVE( TYPE_TRAITS )
+using std::is_same;
+#else
+template<class T, class U>
+struct is_same { enum dummy { value = false }; };
+
+template<class T>
+struct is_same<T, T> { enum dummy { value = true }; };
+#endif
+
+CASE( "not_null<>: Able to deduce element_type of raw pointers" )
+{
+ EXPECT(( is_same< gsl_lite::not_null< int* >::element_type, int >::value ));
+ EXPECT(( is_same< gsl_lite::not_null< const int* >::element_type, const int >::value ));
+}
+
+CASE( "not_null<>: Able to deduce element_type of unique_ptr" )
+{
+#if gsl_HAVE( UNIQUE_PTR )
+ EXPECT(( is_same< gsl_lite::not_null< std::unique_ptr< int > >::element_type, int >::value ));
+ EXPECT(( is_same< gsl_lite::not_null< std::unique_ptr< const int > >::element_type, const int >::value ));
+#endif
+}
+
+CASE( "not_null<>: Able to deduce element_type of shared_ptr" )
+{
+#if gsl_HAVE( SHARED_PTR )
+ EXPECT(( is_same< gsl_lite::not_null< std::shared_ptr< int > >::element_type, int >::value ));
+ EXPECT(( is_same< gsl_lite::not_null< std::shared_ptr< const int > >::element_type, const int >::value ));
+#endif
+}
+
+CASE( "not_null<>: Able to deduce element_type of normal user-defined smart pointers" )
+{
+ EXPECT(( is_same< gsl_lite::not_null< NormalPtr< int > >::element_type, int >::value ));
+ EXPECT(( is_same< gsl_lite::not_null< NormalPtr< const int > >::element_type, const int >::value ));
+}
+
+CASE( "not_null<>: Able to correctly deduce element_type of user-defined smart pointers even if typedef and result of dereferencing differs" )
+{
+ EXPECT(( is_same< gsl_lite::not_null< WeirdPtr< int > >::element_type, int >::value ));
+ EXPECT(( is_same< gsl_lite::not_null< WeirdPtr< const int > >::element_type, const int >::value ));
+}
+
+CASE( "not_null<>: Able to deduce element_type of user-defined smart pointers even if they do not have an element_type typedef" )
+{
+#if gsl_CPP11_OR_GREATER
+ EXPECT(( is_same< gsl_lite::not_null< ETLessNormalPtr< int > >::element_type, int >::value ));
+ EXPECT(( is_same< gsl_lite::not_null< ETLessNormalPtr< const int > >::element_type, const int >::value ));
+#endif
+}
+
+CASE( "not_null<>: Able to deduce element_type of user-defined smart pointers even if they do not have an element_type typedef, and element_type differs from T" )
+{
+#if gsl_CPP11_OR_GREATER
+ EXPECT(( is_same< gsl_lite::not_null< ETLessWeirdPtr< int > >::element_type, double >::value ));
+ EXPECT(( is_same< gsl_lite::not_null< ETLessWeirdPtr< const int > >::element_type, double >::value ));
+#endif
+}
+
+CASE( "not_null<>: Can handle void*" )
+{
+ int i = 42;
+ void * vp = &i;
+
+ // Direct construction
+ gsl_lite::not_null< void * > nvp( vp );
+ EXPECT( nvp == vp );
+
+ // Indirect construction
+ nvp = gsl_lite::make_not_null( vp );
+ EXPECT( nvp == vp );
+
+ // Implicit conversion from `not_null<>` with typed pointer argument
+ gsl_lite::not_null< int * > nip( &i );
+ EXPECT( nvp == nip );
+ gsl_lite::not_null< void * > nvp2( nip );
+ EXPECT( nvp2 == nip );
+
+ // Implicit conversion from typed pointer
+ EXPECT( nvp == &i );
+ gsl_lite::not_null< void * > nvp3( &i );
+ EXPECT( nvp3 == nip );
+
+ // Extract underlying value
+ void * vp2 = gsl_lite::as_nullable( nvp );
+ EXPECT( vp2 == vp );
+
+ // Explicit conversion to typed pointer argument is not supported!
+ //gsl_lite::not_null< int * > nip2 = static_cast< gsl_lite::not_null< int * > >( nvp );
+ //gsl_lite::not_null< int * > nip2 = gsl_lite::not_null< int * >( nvp );
+ //int * ip = static_cast< int * >( nvp );
+}
+
+void int_const_deleter( void const * p )
+{
+ int const * pi = static_cast< int const * >( p );
+ delete pi;
+}
+
+CASE( "not_null<>: Can handle unique_ptr<void, DeleterT>" )
+{
+#if gsl_CPP11_OR_GREATER
+ std::unique_ptr< void, void ( * )( void const * ) > vp( new int( 42 ), int_const_deleter );
+ void * p = vp.get();
+ ( void ) p;
+
+ // Direct construction
+ gsl_lite::not_null< std::unique_ptr< void, void ( * )( void const * ) > > nvp( std::move( vp ) );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( nvp.get() == p );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ vp = std::move( nvp );
+
+ // Indirect construction
+ nvp = gsl_lite::make_not_null( std::move( vp ) );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( nvp.get() == p );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+
+ // Implicit conversion from `not_null<>` with typed pointer argument
+ std::unique_ptr< int, void ( * )( void const * ) > tp2( new int( 42 ), int_const_deleter );
+ int * pi2 = tp2.get();
+ ( void ) pi2;
+ gsl_lite::not_null< std::unique_ptr< int, void ( * )( void const * ) > > ntp2( std::move( tp2 ) );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( ntp2.get() == pi2 );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ gsl_lite::not_null< std::unique_ptr< void, void ( * )( void const * ) > > nvp2( std::move( ntp2 ) );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( nvp2.get() == pi2 );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+
+ // Implicit conversion from typed pointer
+ std::unique_ptr< int, void ( * )( void const * ) > tp3( new int( 42 ), int_const_deleter );
+ int * pi3 = tp3.get();
+ gsl_lite::not_null< std::unique_ptr< void, void ( * )( void const * ) > > nvp3( std::move( tp3 ) );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( nvp3.get() == pi3 );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+
+ // Extract underlying value
+ std::unique_ptr< void, void ( * )( void const * ) > vp3 = gsl_lite::as_nullable( std::move( nvp3 ) );
+ EXPECT( vp3.get() == pi3 );
+
+ // Explicit conversion to typed pointer argument is not supported!
+#endif
+}
+
+CASE( "not_null<>: Can handle shared_ptr<void>" )
+{
+#if gsl_CPP11_OR_GREATER
+ std::shared_ptr< void > vp = std::make_shared<int>( 42 );
+ void * p = vp.get();
+ ( void ) p;
+
+ // Direct construction
+ gsl_lite::not_null< std::shared_ptr< void > > nvp( vp );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( nvp.get() == p );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ vp = std::move( nvp );
+
+ // Indirect construction
+ nvp = gsl_lite::make_not_null( vp );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( nvp.get() == p );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+
+ // Implicit conversion from `not_null<>` with typed pointer argument
+ std::shared_ptr< int > tp2 = std::make_shared<int>( 42 );
+ int * pi2 = tp2.get();
+ gsl_lite::not_null< std::shared_ptr< int > > ntp2( tp2 );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( ntp2.get() == pi2 );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ gsl_lite::not_null< std::shared_ptr< void > > nvp2( ntp2 );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( nvp2.get() == pi2 );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+
+ // Implicit conversion from typed pointer
+ gsl_lite::not_null< std::shared_ptr< void > > nvp2b( tp2 );
+# if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ EXPECT( nvp2b.get() == pi2 );
+# endif // gsl_CONFIG( TRANSPARENT_NOT_NULL )
+
+ // Extract underlying value
+ std::shared_ptr< void > vp2 = gsl_lite::as_nullable( nvp2 );
+ EXPECT( vp2.get() == pi2 );
+
+ // Explicit conversion to typed pointer argument is not supported!
+#endif
+}
+
+#if gsl_HAVE( HASH )
+
+CASE( "not_null<>: Hashes match the hashes of the wrapped pointer" )
+{
+ int i = 42;
+ not_null< const int* > raw_pointer = make_not_null( &i );
+ EXPECT( std::hash< not_null< const int* > >()(raw_pointer) == std::hash< const int* >()( as_nullable( raw_pointer ) ) );
+# if gsl_HAVE( UNIQUE_PTR )
+ not_null< std::unique_ptr< int > > unique_pointer = make_not_null( my_make_unique< int >(43) );
+ EXPECT( std::hash< not_null< std::unique_ptr< int > > >()(unique_pointer) == std::hash< std::unique_ptr< int > >()( as_nullable( unique_pointer) ) );
+# endif // gsl_HAVE( UNIQUE_PTR )
+# if gsl_HAVE( SHARED_PTR )
+ not_null< std::shared_ptr< int > > shared_pointer = make_not_null( std::make_shared< int >(43) );
+ EXPECT( std::hash< not_null< std::shared_ptr< int > > >()(shared_pointer) == std::hash< std::shared_ptr< int > >()( as_nullable( shared_pointer) ) );
+# endif // gsl_HAVE( SHARED_PTR )
+}
+
+CASE( "not_null<>: Hash functor disabled for non-hashable pointers and enabled for hashable pointers" )
+{
+ EXPECT(( std::is_default_constructible< std::hash< not_null< int* > > >::value ));
+ EXPECT(( std::is_default_constructible< std::hash< not_null< std::unique_ptr< int > > > >::value ));
+ EXPECT(( std::is_default_constructible< std::hash< not_null< std::shared_ptr< int > > > >::value ));
+# if gsl_STDLIB_CPP14_OR_GREATER && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 141 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 900 )
+ // std::hash< NormalPtr< int > > isn't guaranteed to exist at all in C++11
+ EXPECT_NOT( ( std::is_default_constructible< std::hash< not_null< NormalPtr< int > > > >::value ) );
+# endif
+}
+
+#endif // gsl_HAVE( HASH )
+
+#if gsl_STDLIB_CPP11_140 && ( gsl_CPP14_OR_GREATER || ! gsl_COMPILER_NVCC_VERSION )
+
+int inspector( int const& p )
+{
+ return p;
+}
+int mutator( int & p )
+{
+ p = 42;
+ return p;
+}
+int extractor( std::unique_ptr< int > value )
+{
+ return *value;
+}
+
+CASE( "not_null<>: Supports function pointer type for construction, assignment, and invocation" )
+{
+# if ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ not_null< int (*)( int const& ) > insp = inspector;
+ int i = 41;
+ EXPECT( insp( i ) == 41 );
+
+ not_null< int (*)( int & ) > mut = mutator;
+ mut( i );
+ EXPECT( i == 42 );
+
+ not_null< int (*)( std::unique_ptr< int > ) > xtr = extractor;
+ EXPECT( xtr( my_make_unique< int >( 1 ) ) == 1 );
+# endif // ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+}
+
+CASE( "not_null<>: Supports std::function<> for construction, assignment, and invocation" )
+{
+ not_null< std::function< int( int ) > > insp = make_not_null( std::function< int( int ) >( inspector ) );
+ int i = 41;
+ EXPECT( insp( i ) == 41 );
+ auto insp2 = std::move( insp );
+ EXPECT( insp2( i ) == 41 );
+ if ( ! gsl_lite::is_valid( insp ) ) // a moved-from `std::function<>` object is in a valid but unspecified state, and may thus still be holding the old value
+ {
+ EXPECT_THROWS( insp( i ) );
+ }
+
+ not_null< std::function< int( int & ) > > mut = make_not_null( std::function< int( int & ) >( mutator ) );
+ mut( i );
+ EXPECT( i == 42 );
+ mut = std::move( insp2 );
+ i = 41;
+ mut( i );
+ EXPECT( i == 41 );
+
+ not_null< std::function< int( std::unique_ptr< int > ) > > xtr = make_not_null( std::function< int( std::unique_ptr< int > ) >( extractor ) );
+ EXPECT( xtr( my_make_unique< int >( 1 ) ) == 1 );
+}
+
+CASE( "not_null<>: Supports converting to std::function<> from function reference" )
+{
+# if ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ not_null< std::function< int( int ) > > insp = inspector;
+ int i = 41;
+ EXPECT( insp( i ) == 41 );
+ auto insp2 = std::move( insp );
+ EXPECT( insp2( i ) == 41 );
+ if ( ! gsl_lite::is_valid( insp ) ) // a moved-from `std::function<>` object is in a valid but unspecified state, and may thus still be holding the old value
+ {
+ EXPECT_THROWS( insp( i ) );
+ }
+
+ not_null< std::function< int( int & ) > > mut = mutator;
+ mut( i );
+ EXPECT( i == 42 );
+ mut = inspector;
+ i = 41;
+ mut( i );
+ EXPECT( i == 41 );
+# endif // ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+}
+
+struct Mutator
+{
+ template < typename T >
+ T
+ operator ()( T& arg )
+ {
+ arg = { };
+ return arg;
+ }
+};
+struct Inspector
+{
+ template < typename T >
+ T
+ operator ()( T arg )
+ {
+ return arg;
+ }
+};
+
+CASE( "not_null<>: Supports constructing and assigning std::function<> from non-nullable function object" )
+{
+# if ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ not_null< std::function< int( int& ) > > insp = Inspector{ };
+ int i = 41;
+ EXPECT( insp( i ) == 41 );
+
+ not_null< std::function< int( int & ) > > mut = Mutator{ };
+ mut( i );
+ EXPECT( i == 0 );
+ mut = Inspector{ };
+ i = 41;
+ mut( i );
+ EXPECT( i == 41 );
+# endif // ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+}
+#endif // gsl_STDLIB_CPP11_140 && ( gsl_CPP14_OR_GREATER || ! gsl_COMPILER_NVCC_VERSION )
+
+CASE( "not_null<>: Invocability is correctly reported by type traits" )
+{
+#if gsl_STDLIB_CPP17_OR_GREATER
+
+ // No invocability for raw pointers.
+ static_assert( !std::is_invocable< not_null< int* > >::value );
+ static_assert( !std::is_invocable< not_null< int* >, int >::value );
+
+ // No invocability for `unique_ptr<>`.
+ static_assert( !std::is_invocable< not_null< unique_ptr< int > > >::value );
+ static_assert( !std::is_invocable< not_null< unique_ptr< int > >, int >::value );
+
+ // Invocability for function pointers with suitable argument list.
+ static_assert( std::is_invocable< not_null< int (*)( ) > >::value );
+ static_assert( std::is_invocable< not_null< int (*)( int const& ) >, int & >::value );
+ static_assert( std::is_invocable< not_null< int (*)( int & ) >, int & >::value );
+ static_assert( !std::is_invocable< not_null< int (*)( int & ) >, int >::value );
+
+ // Invocability for `std::function<>` with suitable argument list.
+ static_assert( std::is_invocable< not_null< std::function< int( ) > > >::value );
+ static_assert( std::is_invocable< not_null< std::function< int( int const& ) > >, int & >::value );
+ static_assert( std::is_invocable< not_null< std::function< int( int & ) > >, int & >::value );
+ static_assert( !std::is_invocable< not_null< std::function< int( int & ) > >, int >::value );
+
+ // Correct return type is inferred for function pointers.
+ static_assert( std::is_invocable_r< void, not_null< int & (*)( int const& ) >, int >::value );
+ static_assert( std::is_invocable_r< int &, not_null< int & (*)( int const& ) >, int >::value );
+ static_assert( !std::is_invocable_r< int &, not_null< int (*)( int const& ) >, int >::value );
+
+ // Correct return type is inferred for `std::function<>`.
+ static_assert( std::is_invocable_r< void, not_null< std::function<int &( int const& ) > >, int >::value );
+ static_assert( std::is_invocable_r< int &, not_null< std::function<int &( int const& ) > >, int >::value );
+ static_assert( !std::is_invocable_r< int &, not_null< std::function<int ( int const& ) > >, int >::value );
+
+#endif // gsl_STDLIB_CPP20_OR_GREATER
+}
+
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/owner.t.cpp b/thirdparty/gsl-lite/test/owner.t.cpp
new file mode 100644
index 000000000..d576a706b
--- /dev/null
+++ b/thirdparty/gsl-lite/test/owner.t.cpp
@@ -0,0 +1,67 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+
+using namespace gsl_lite;
+
+CASE( "owner<>: Disallows construction from a non-pointer type (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+#if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+# if gsl_HAVE( TYPE_TRAITS )
+ owner<int> p = gsl_nullptr;
+# else
+ EXPECT( !!"owner<> alias template restricted to pointer type is not available." );
+# endif
+#endif
+}
+
+CASE( "owner<>: Allows its use as the (pointer) type it stands for" )
+{
+#if gsl_HAVE( OWNER_TEMPLATE )
+ struct F { static void incr( int * i ) { *i += 1; } };
+
+ owner<int*> p = new int( 120 );
+
+ EXPECT( (p != NULL) );
+ EXPECT( p != nullptr_void() );
+# if gsl_HAVE( NULLPTR )
+ EXPECT( p != nullptr );
+# endif
+ EXPECT( *p == 120 );
+
+ F::incr( p );
+
+ EXPECT( *p == 121 );
+ delete p;
+
+#if gsl_FEATURE( GSL_LITE_NAMESPACE )
+ // Also try to consume `owner<>` from the `gsl_lite` namespace
+ gsl_lite::owner<int*> p2 = new int( 120 );
+ EXPECT( ( p2 != NULL ) );
+ EXPECT( *p2 == 120 );
+ F::incr( p2 );
+ EXPECT( *p2 == 121 );
+ delete p2;
+#endif
+#else
+ EXPECT( !!"owner<> alias template is not available." );
+#endif
+}
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/span.t.cpp b/thirdparty/gsl-lite/test/span.t.cpp
new file mode 100644
index 000000000..86dd05607
--- /dev/null
+++ b/thirdparty/gsl-lite/test/span.t.cpp
@@ -0,0 +1,2199 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+
+using namespace gsl_lite;
+
+typedef span<int>::size_type size_type;
+typedef std::ptrdiff_t difference_type;
+
+
+static std::vector<int> vector_iota( int n )
+{
+ std::vector<int> result;
+
+ for ( int i = 0; i < n; ++i )
+ result.push_back( i );
+
+ return result;
+}
+
+CASE( "span<>: Disallows construction from a temporary value (C++11) (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+#if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+# if gsl_HAVE( IS_DELETE )
+ span<int> v = 42;
+# endif
+#endif
+}
+
+CASE( "span<>: Disallows construction from a C-array of incompatible type (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+#if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+ short arr[] = { 1, 2, 3, };
+ span<int> v = arr;
+#endif
+}
+
+CASE( "span<>: Disallows construction from a std::array of incompatible type (C++11) (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+#if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+# if gsl_HAVE( ARRAY )
+ std::array<long,3> arr = {{ 1L, 2L, 3L, }};
+ span<int> v( arr);
+# endif
+#endif
+}
+
+CASE( "span<>: Terminates construction from pointer with a mismatching size" )
+{
+ struct F { static void blow() { int a[2]; span<int, 3> v( a, 2 ); (void) v.size(); } };
+ struct G { static void blow() { int a[2]; span<int, 3> v( a, a + 2 ); (void) v.size(); } };
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+}
+
+CASE( "span<>: Terminates construction from iterator with a mismatching size" )
+{
+ struct F { static void blow() { int a[2]; span<int> u(a); span<int, 3> v( u.begin(), 2 ); (void) v.size(); } };
+ struct G { static void blow() { int a[2]; span<int> u(a); span<int, 3> v( u.begin(), u.begin() + 2 ); (void) v.size(); } };
+ struct H { static void blow() { int a[2]; span<int, 2> u(a); span<int, 3> v( u.begin(), 2 ); (void) v.size(); } };
+ struct I { static void blow() { int a[2]; span<int, 2> u(a); span<int, 3> v( u.begin(), u.begin() + 2 ); (void) v.size(); } };
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+ EXPECT_THROWS( H::blow() );
+ EXPECT_THROWS( I::blow() );
+}
+
+CASE( "span<>: Terminates construction from a nullptr and a non-zero size (C++11)" )
+{
+#if gsl_HAVE( NULLPTR )
+ struct F { static void blow() { span<int> v( nullptr, 42 ); (void) v.size(); } };
+ struct G { static void blow() { span<int, 42> v( nullptr, 42 ); (void) v.size(); } };
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+#else
+ EXPECT( !!"nullptr is not available (no C++11)" );
+#endif
+}
+
+CASE( "span<>: Terminates construction from two pointers in the wrong order" )
+{
+ struct F { static void blow() { int a[2]; span<int> v( &a[2], &a[0] ); (void) v.size(); } };
+ struct G { static void blow() { int a[2]; span<int, 2> v( &a[2], &a[0] ); (void) v.size(); } };
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+}
+
+CASE( "span<>: Terminates construction from two iterators in the wrong order" )
+{
+ struct F { static void blow() { int a[2]; span<int> u( a ); span<int> v( u.begin() + 2, u.begin() ); (void) v.size(); } };
+ struct G { static void blow() { int a[2]; span<int> u( a ); span<int, 2> v( u.begin() + 2, u.begin() ); (void) v.size(); } };
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+}
+
+CASE( "span<>: Terminates construction from a null pointer and a non-zero size" )
+{
+ struct F { static void blow() { int * p = gsl_nullptr; span<int> v( p, 42 ); (void) v.size(); } };
+ struct G { static void blow() { int * p = gsl_nullptr; span<int, 42> v( p, 42 ); (void) v.size(); } };
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+}
+
+CASE( "span<>: Terminates construction from a default-constructed iterator and a non-zero size" )
+{
+ struct F { static void blow() { span<int>::iterator it; span<int> v( it, 42 ); (void) v.size(); } };
+ struct G { static void blow() { span<int>::iterator it; span<int, 42> v( it, 42 ); (void) v.size(); } };
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+}
+
+CASE( "span<>: Terminates creation of a sub span of the first n elements for n exceeding the span" )
+{
+ struct F {
+ static void blow()
+ {
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+
+ (void) v.first( 4 );
+ }};
+ struct G {
+ static void blow()
+ {
+ int arr[] = { 1, 2, 3, };
+ span<int, 3> v( arr );
+
+ (void) v.first( 4 );
+ }};
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+}
+
+CASE( "span<>: Terminates creation of a sub span of the last n elements for n exceeding the span" )
+{
+ struct F {
+ static void blow()
+ {
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+
+ (void) v.last( 4 );
+ }};
+ struct G {
+ static void blow()
+ {
+ int arr[] = { 1, 2, 3, };
+ span<int, 3> v( arr );
+
+ (void) v.last( 4 );
+ }};
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+}
+
+CASE( "span<>: Terminates creation of a sub span outside the span" )
+{
+ struct F {
+ static void blow_offset()
+ {
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+
+ (void) v.subspan( 4 );
+ }
+ static void blow_count()
+ {
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+
+ (void) v.subspan( 1, 3 );
+ }};
+ struct G {
+ static void blow_offset()
+ {
+ int arr[] = { 1, 2, 3, };
+ span<int, 3> v( arr );
+
+ (void) v.subspan( 4 );
+ }
+ static void blow_count()
+ {
+ int arr[] = { 1, 2, 3, };
+ span<int, 3> v( arr );
+
+ (void) v.subspan( 1, 3 );
+ }};
+
+ EXPECT_THROWS( F::blow_offset() );
+ EXPECT_THROWS( F::blow_count() );
+ EXPECT_THROWS( G::blow_offset() );
+ EXPECT_THROWS( G::blow_count() );
+}
+
+CASE( "span<>: Terminates access outside the span" )
+{
+ struct F {
+ static void blow_ix(size_t i) { int arr[] = { 1, 2, 3, }; span<int> v( arr ); (void) v[i]; }
+ };
+ struct G {
+ static void blow_ix(size_t i) { int arr[] = { 1, 2, 3, }; span<int, 3> v( arr ); (void) v[i]; }
+ };
+
+ EXPECT_NO_THROW( F::blow_ix(2) );
+ EXPECT_THROWS( F::blow_ix(3) );
+ EXPECT_NO_THROW( G::blow_ix(2) );
+ EXPECT_THROWS( G::blow_ix(3) );
+}
+
+CASE( "span<>: Terminates access with front() and back() on empty span" )
+{
+ EXPECT_THROWS( (void) span<int>().front() );
+ EXPECT_THROWS( (void) span<int>().back() );
+ EXPECT_THROWS(( (void) span<int, 0>().front() ));
+ EXPECT_THROWS(( (void) span<int, 0>().back() ));
+}
+
+CASE( "span<>: Allows to default-construct" )
+{
+ span<int> v;
+ span<int, 0> w;
+
+ EXPECT( v.size() == size_type( 0 ) );
+ EXPECT( w.size() == size_type( 0 ) );
+}
+
+CASE( "span<>: Allows to construct from a nullptr and a zero size (C++11)" )
+{
+#if gsl_HAVE( NULLPTR )
+ span< int> v ( nullptr, size_type( 0 ) );
+ span<const int> cv( nullptr, size_type( 0 ) );
+ span< int, 0> w ( nullptr, size_type( 0 ) );
+ span<const int, 0> cw( nullptr, size_type( 0 ) );
+
+ EXPECT( v.size() == size_type( 0 ) );
+ EXPECT( cv.size() == size_type( 0 ) );
+ EXPECT( w.size() == size_type( 0 ) );
+ EXPECT( cw.size() == size_type( 0 ) );
+#else
+ EXPECT( !!"nullptr is not available (no C++11)" );
+#endif
+}
+
+CASE( "span<>: Allows to construct from a default-constructed iterator and a zero size" )
+{
+ span<int>::iterator it;
+ span< int> v ( it, size_type( 0 ) );
+ span<const int> cv( it, size_type( 0 ) );
+ span< int, 0> w ( it, size_type( 0 ) );
+ span<const int, 0> cw( it, size_type( 0 ) );
+
+ EXPECT( v.size() == size_type( 0 ) );
+ EXPECT( cv.size() == size_type( 0 ) );
+ EXPECT( w.size() == size_type( 0 ) );
+ EXPECT( cw.size() == size_type( 0 ) );
+}
+
+CASE( "span<>: Allows to construct from two pointers" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span< int> v ( arr, arr + gsl_DIMENSION_OF( arr ) );
+ span<const int> cv( arr, arr + gsl_DIMENSION_OF( arr ) );
+ span< int, 9> w ( arr, arr + gsl_DIMENSION_OF( arr ) );
+ span<const int, 9> cw( arr, arr + gsl_DIMENSION_OF( arr ) );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from two iterators" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<int> u( arr );
+ span< int> v ( u.begin(), u.begin() + u.ssize() );
+ span<const int> cv( u.begin(), u.begin() + u.ssize() );
+ span< int, 9> w ( u.begin(), u.begin() + u.ssize() );
+ span<const int, 9> cw( u.begin(), u.begin() + u.ssize() );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from two pointers to const" )
+{
+ const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<const int> cv( arr, arr + gsl_DIMENSION_OF( arr ) );
+ span<const int, 9> cw( arr, arr + gsl_DIMENSION_OF( arr ) );
+
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from a non-null pointer and a size" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span< int> v ( arr, gsl_DIMENSION_OF( arr ) );
+ span<const int> cv( arr, gsl_DIMENSION_OF( arr ) );
+ span< int, 9> w ( arr, gsl_DIMENSION_OF( arr ) );
+ span<const int, 9> cw( arr, gsl_DIMENSION_OF( arr ) );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from an iterator and a size" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<int> u( arr );
+ span< int> v ( u.begin(), u.size() );
+ span<const int> cv( u.begin(), u.size() );
+ span< int, 9> w ( u.begin(), u.size() );
+ span<const int, 9> cw( u.begin(), u.size() );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from a non-null pointer to const and a size" )
+{
+ const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<const int> cv( arr, gsl_DIMENSION_OF( arr ) );
+ span<const int, 9> cw( arr, gsl_DIMENSION_OF( arr ) );
+
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from a const iterator and a size" )
+{
+ const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<const int> u( arr );
+ span<const int> cv( u.begin(), u.size() );
+ span<const int, 9> cw( u.begin(), u.size() );
+
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from a temporary pointer and a size" )
+{
+ int x = 42;
+
+ span< int> v ( &x, 1 );
+ span<const int> cv( &x, 1 );
+ span< int, 1> w ( &x, 1 );
+ span<const int, 1> cw( &x, 1 );
+
+ EXPECT( std::equal( v.begin(), v.end(), &x ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), &x ) );
+ EXPECT( std::equal( w.begin(), w.end(), &x ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), &x ) );
+}
+
+CASE( "span<>: Allows to construct from a temporary pointer to const and a size" )
+{
+ const int x = 42;
+
+ span<const int> cv( &x, 1 );
+ span<const int, 1> cw( &x, 1 );
+
+ EXPECT( std::equal( cv.begin(), cv.end(), &x ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), &x ) );
+}
+
+CASE( "span<>: Allows to construct from any pointer and a zero size" )
+{
+ struct F {
+ static void null() {
+ int * p = gsl_nullptr; span<int> v( p, size_type( 0 ) );
+ }
+ static void nonnull() {
+ int i = 7; int * p = &i; span<int> v( p, size_type( 0 ) );
+ }
+ };
+
+ EXPECT_NO_THROW( F::null() );
+ EXPECT_NO_THROW( F::nonnull() );
+}
+
+CASE( "span<>: Allows to construct from any iterator and a zero size" )
+{
+ struct F {
+ static void null() {
+ span<int>::iterator it; span<int> v( it, size_type( 0 ) );
+ }
+ static void nonnull() {
+ int a[2]; span<int> u( a ); span<int> v( u.begin(), size_type( 0 ) );
+ }
+ };
+
+ EXPECT_NO_THROW( F::null() );
+ EXPECT_NO_THROW( F::nonnull() );
+}
+
+CASE( "span<>: Allows to construct from a C-array" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span< int> v ( arr );
+ span<const int> cv( arr );
+ span< int, 9> w ( arr );
+ span<const int, 9> cw( arr );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from a const C-array" )
+{
+ const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<const int> cv( arr );
+ span<const int, 9> cw( arr );
+
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+}
+
+CASE( "span<>: Allows to construct from a C-array with size via decay to pointer (potentially dangerous)" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ {
+ span< int> v( arr, gsl_DIMENSION_OF(arr) );
+ span<const int> w( arr, gsl_DIMENSION_OF(arr) );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr ) );
+ }
+
+#if gsl_CPP14_OR_GREATER
+ {
+ span< int> v( arr, 3 );
+ span<const int> w( arr, 3 );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr, arr + 3 ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr, arr + 3 ) );
+ }
+#endif
+}
+
+CASE( "span<>: Allows to construct from a const C-array with size via decay to pointer (potentially dangerous)" )
+{
+ const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ {
+ span<const int> v( arr, gsl_DIMENSION_OF(arr) );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ }
+
+#if gsl_CPP14_OR_GREATER
+ {
+ span<const int> w( arr, 3 );
+
+ EXPECT( std::equal( w.begin(), w.end(), arr, arr + 3 ) );
+ }
+#endif
+}
+
+CASE( "span<>: Allows to construct from a std::initializer_list<> (C++11)" )
+{
+#if gsl_HAVE( INITIALIZER_LIST ) && ( gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR ) )
+ auto il = { 1, 2, 3, 4, 5, };
+
+ span<int const> v( il );
+
+ EXPECT( std::equal( v.begin(), v.end(), il.begin() ) );
+#else
+ EXPECT( !!"std::initializer_list<> is not available (no C++11)" );
+#endif
+}
+
+CASE( "span<>: Allows to construct from a std::array<> (C++11)" )
+{
+# if gsl_HAVE( ARRAY )
+ std::array<int,9> arr = {{ 1, 2, 3, 4, 5, 6, 7, 8, 9, }};
+
+ span<int> v( arr );
+ span<int, 9> w( arr );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr.begin() ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr.begin() ) );
+
+ span<const int> cv( arr );
+ span<const int, 9> cw( arr );
+
+ EXPECT( std::equal( cv.begin(), cv.end(), arr.begin() ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr.begin() ) );
+
+#else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+#endif
+}
+
+gsl_constexpr14 int use_span_with_array( int const (&array)[3], span<int const> sp )
+{
+ gsl_Assert( sp.size() == 3 );
+ gsl_Assert( sp.front() == 0 );
+ gsl_Assert( sp[1] == array[1] );
+ gsl_Assert( sp.back() == 2 );
+ gsl_Assert( sp.first( 0 ).size() == 0 );
+ gsl_Assert( sp.last( 1 ).size() == 1 );
+ gsl_Assert( sp.subspan( 1, 2 ).size() == 2 );
+ gsl_Assert( ! sp.empty() );
+
+ int array2[3] = { 0, 0, 0 };
+ span<int> sp2 = span<int>( array2 );
+ sp = sp2;
+#if gsl_CPP17_OR_GREATER
+ array2[0] = 1;
+ gsl_Assert( sp2[0] == 1 );
+#endif
+ sp2[1] = 2;
+ gsl_Assert( array2[1] == 2 );
+ return 0;
+}
+
+gsl_constexpr14 int use_fixed_span_with_array( int const (&array)[3], span<int const, 3> sp )
+{
+ gsl_Assert( sp.size() == 3 );
+ gsl_Assert( sp.front() == 0 );
+ gsl_Assert( sp[1] == array[1] );
+ gsl_Assert( sp.back() == 2 );
+ gsl_Assert( sp.first( 0 ).size() == 0 );
+ gsl_Assert( sp.last( 1 ).size() == 1 );
+ gsl_Assert( sp.subspan( 1, 2 ).size() == 2 );
+ gsl_Assert( ! sp.empty() );
+
+ int array2[3] = { 0, 0, 0 };
+ span<int, 3> sp2 = span<int, 3>( array2 );
+ sp = sp2;
+#if gsl_CPP17_OR_GREATER
+ array2[0] = 1;
+ gsl_Assert( sp2[0] == 1 );
+#endif
+ sp2[1] = 2;
+ gsl_Assert( array2[1] == 2 );
+ return 0;
+}
+
+CASE("span<>: Allows constexpr use (C++14)")
+{
+#if gsl_HAVE( CONSTEXPR_14 ) && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 700 )
+ constexpr int array[3] = { 0, 1, 2 };
+# if gsl_FEATURE_TO_STD( MAKE_SPAN )
+ constexpr int r1 = use_span_with_array( array, make_span( array ) );
+ constexpr int r2 = use_span_with_array( array, make_span( array, array + 3 ) );
+ constexpr int r3 = use_span_with_array( array, make_span( array, 3 ) );
+ constexpr int s1 = use_fixed_span_with_array( array, make_span( array ) );
+# endif
+ constexpr int r4 = use_span_with_array( array, span<int const>( array ) );
+ constexpr int r5 = use_span_with_array( array, span<int const>( array, array + 3 ) );
+ constexpr int r6 = use_span_with_array( array, span<int const>( array, 3 ) );
+ constexpr int s2 = use_fixed_span_with_array( array, span<int const, 3>( array ) );
+ EXPECT( (r1 | r2 | r3 | r4 | r5 | r6) == 0 );
+ EXPECT( (s1 | s2) == 0 );
+# if gsl_HAVE( DEDUCTION_GUIDES )
+ constexpr int r7 = use_span_with_array( array, span( array ) );
+ constexpr int r8 = use_span_with_array( array, span( array, array + 3 ) );
+ constexpr int r9 = use_span_with_array( array, span( array, 3 ) );
+ constexpr int s3 = use_fixed_span_with_array( array, span( array ) );
+ EXPECT( (r7 | r8 | r9) == 0 );
+ EXPECT( s3 == 0 );
+# endif
+#endif
+}
+
+CASE( "span<>: Allows to construct from a std::array<> with const data (C++11)" )
+{
+#if gsl_HAVE( ARRAY )
+ std::array<const int,9> arr = {{ 1, 2, 3, 4, 5, 6, 7, 8, 9, }};
+
+ span<const int> v( arr );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr.begin() ) );
+#else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+#endif
+}
+
+CASE( "span<>: Allows to construct from a container (std::vector<>)" )
+{
+ std::vector<int> vec = vector_iota(10);
+
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ span< int > v ( vec );
+ span<const int > cv( vec );
+ span< int, 10> w ( vec );
+ span<const int, 10> cw( vec );
+
+ EXPECT( std::equal( v.begin(), v.end(), vec.begin() ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), vec.begin() ) );
+ EXPECT( std::equal( w.begin(), w.end(), vec.begin() ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), vec.begin() ) );
+#else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+#endif
+}
+
+CASE( "span<>: Allows to construct from a temporary container (potentially dangerous)" )
+{
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ std::vector<int> vec = vector_iota( 10 );
+
+ EXPECT( std::equal( vec.begin(), vec.end(), span<const int>( vector_iota(10) ).begin() ) );
+ EXPECT( std::equal( vec.begin(), vec.end(), span<const int, 10>( vector_iota(10) ).begin() ) );
+#else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+#endif
+}
+
+CASE( "span<>: Allows to tag-construct from a container (std::vector<>)" )
+{
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ std::vector<int> vec = vector_iota(10);
+ span< int> v ( with_container, vec );
+ span<const int> cv( with_container, vec );
+ span< int, 10> w ( with_container, vec );
+ span<const int, 10> cw( with_container, vec );
+
+ EXPECT( std::equal( v.begin(), v.end(), vec.begin() ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), vec.begin() ) );
+ EXPECT( std::equal( w.begin(), w.end(), vec.begin() ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), vec.begin() ) );
+#else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+#endif
+}
+
+CASE( "span<>: Allows to tag-construct from a temporary container (potentially dangerous)" )
+{
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ std::vector<int> vec = vector_iota(10);
+
+ EXPECT( std::equal( vec.begin(), vec.end(), span<const int>( with_container, vector_iota( 10 ) ).begin() ) );
+ EXPECT( std::equal( vec.begin(), vec.end(), span<const int, 10>( with_container, vector_iota( 10 ) ).begin() ) );
+#else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+#endif
+}
+
+CASE( "span<>: Allows to default construct in a constexpr context")
+{
+#if gsl_HAVE( CONSTEXPR_11 )
+ constexpr auto spn = gsl_lite::span<int>{ };
+ constexpr auto spn2 = gsl_lite::span<int, 0>{ };
+ EXPECT( spn.size() == size_type( 0 ) );
+ EXPECT( spn2.size() == size_type( 0 ) );
+#else
+ EXPECT( !!"construction in a constexpr context is not available (C++11)");
+#endif
+}
+
+CASE( "span<>: Allows to copy-construct from another span of the same type" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+ span< int> v ( arr );
+ span<const int> cv( arr );
+ span< int, 9> w ( arr );
+ span<const int, 9> cw( arr );
+
+ span< int> x ( v );
+ span<const int> cx( w );
+ span< int, 9> y ( v );
+ span<const int, 9> cy( w );
+
+ EXPECT( std::equal( x.begin(), x.end(), arr ) );
+ EXPECT( std::equal( cx.begin(), cx.end(), arr ) );
+ EXPECT( std::equal( y.begin(), y.end(), arr ) );
+ EXPECT( std::equal( cy.begin(), cy.end(), arr ) );
+}
+
+CASE( "span<>: Allows to copy-construct from another span of a compatible type" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+ span< int> v ( arr );
+ span<const int> cv( arr );
+ span< int, 9> w ( arr );
+ span<const int, 9> cw( arr );
+
+ span<const volatile int> x1( v );
+ span<const volatile int> x2( cv );
+ span<const volatile int> x3( w );
+ span<const volatile int> x4( cw );
+ span<const volatile int, 9> y1( v );
+ span<const volatile int, 9> y2( cv );
+ span<const volatile int, 9> y3( v );
+ span<const volatile int, 9> y4( cv );
+
+#if !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1500 )
+ EXPECT( std::equal( x1.begin(), x1.end(), arr ) );
+ EXPECT( std::equal( x2.begin(), x2.end(), arr ) );
+ EXPECT( std::equal( x3.begin(), x3.end(), arr ) );
+ EXPECT( std::equal( x4.begin(), x4.end(), arr ) );
+ EXPECT( std::equal( y1.begin(), y1.end(), arr ) );
+ EXPECT( std::equal( y2.begin(), y2.end(), arr ) );
+ EXPECT( std::equal( y3.begin(), y3.end(), arr ) );
+ EXPECT( std::equal( y4.begin(), y4.end(), arr ) );
+#endif // !gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1500 )
+}
+
+CASE( "span<>: Allows to move-construct from another span of the same type (C++11)" )
+{
+#if gsl_STDLIB_CPP11_OR_GREATER
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span< int> v (( span< int> ( arr ) ));
+// span< int> w (( span<const int> ( arr ) ));
+ span<const int> cv(( span< int> ( arr ) ));
+ span<const int> cw(( span<const int> ( arr ) ));
+ span< int, 9> x (( span< int, 9>( arr ) ));
+// span< int, 9> y (( span<const int, 9>( arr ) ));
+ span<const int, 9> cx(( span< int, 9>( arr ) ));
+ span<const int, 9> cy(( span<const int, 9>( arr ) ));
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( cv.begin(), cv.end(), arr ) );
+ EXPECT( std::equal( cw.begin(), cw.end(), arr ) );
+ EXPECT( std::equal( x.begin(), x.end(), arr ) );
+ EXPECT( std::equal( cx.begin(), cx.end(), arr ) );
+ EXPECT( std::equal( cy.begin(), cy.end(), arr ) );
+#else
+ EXPECT( !!"move-semantics are not available (no C++11)" );
+#endif
+}
+
+CASE( "span<>: Allows to copy-assign from another span of the same type" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+ int arr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, };
+ span< int> x( arr );
+ span< int, 9> y( arr );
+ span< int> s( arr2 );
+ span<const int> t( arr2 );
+ span< int, 9> u( arr2 );
+ span<const int, 9> v( arr2 );
+
+ s = x;
+ t = x;
+ u = y;
+ v = y;
+
+ EXPECT( std::equal( s.begin(), s.end(), arr ) );
+ EXPECT( std::equal( t.begin(), t.end(), arr ) );
+ EXPECT( std::equal( u.begin(), u.end(), arr ) );
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+}
+
+CASE( "span<>: Allows to move-assign from another span of the same type (C++11)" )
+{
+#if gsl_STDLIB_CPP11_OR_GREATER
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+ int arr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, };
+ span< int> s( arr2 );
+ span<const int> t( arr2 );
+ span< int, 9> u( arr2 );
+ span<const int, 9> v( arr2 );
+
+ s = span<int>( arr );
+ t = span<const int>( arr );
+ u = span<int, 9>( arr );
+ v = span<const int, 9>( arr );
+
+ EXPECT( std::equal( s.begin(), s.end(), arr ) );
+ EXPECT( std::equal( t.begin(), t.end(), arr ) );
+ EXPECT( std::equal( u.begin(), u.end(), arr ) );
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+#else
+ EXPECT( !!"move-semantics are not available (no C++11)" );
+#endif
+}
+
+CASE( "span<>: Allows to create a sub span of the first n elements" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, };
+ span<int> v( arr );
+ span<int, 5> w( arr );
+ size_type count = 3;
+
+ span< int> s1 = v.first( count );
+ span<const int> t1 = v.first( count );
+ span< int> s2 = w.first( count );
+ span<const int> t2 = w.first( count );
+ span< int, 3> s3 = v.first<3>( );
+ span<const int, 3> t3 = v.first<3>( );
+ span< int, 3> s4 = w.first<3>( );
+ span<const int, 3> t4 = w.first<3>( );
+
+ EXPECT( s1.size() == count );
+ EXPECT( t1.size() == count );
+ EXPECT( s2.size() == count );
+ EXPECT( t2.size() == count );
+ EXPECT( s3.size() == count );
+ EXPECT( t3.size() == count );
+ EXPECT( s4.size() == count );
+ EXPECT( t4.size() == count );
+ EXPECT( std::equal( s1.begin(), s1.end(), arr ) );
+ EXPECT( std::equal( t1.begin(), t1.end(), arr ) );
+ EXPECT( std::equal( s2.begin(), s2.end(), arr ) );
+ EXPECT( std::equal( t2.begin(), t2.end(), arr ) );
+ EXPECT( std::equal( s3.begin(), s3.end(), arr ) );
+ EXPECT( std::equal( t3.begin(), t3.end(), arr ) );
+ EXPECT( std::equal( s4.begin(), s4.end(), arr ) );
+ EXPECT( std::equal( t4.begin(), t4.end(), arr ) );
+}
+
+CASE( "span<>: Allows to create a sub span of the last n elements" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, };
+ span<int> v( arr );
+ span<int, 5> w( arr );
+ size_type count = 3;
+
+ span< int> s1 = v.last( count );
+ span<const int> t1 = v.last( count );
+ span< int> s2 = w.last( count );
+ span<const int> t2 = w.last( count );
+ span< int, 3> s3 = v.last<3>( );
+ span<const int, 3> t3 = v.last<3>( );
+ span< int, 3> s4 = w.last<3>( );
+ span<const int, 3> t4 = w.last<3>( );
+
+ EXPECT( s1.size() == count );
+ EXPECT( t1.size() == count );
+ EXPECT( s2.size() == count );
+ EXPECT( t2.size() == count );
+ EXPECT( s3.size() == count );
+ EXPECT( t3.size() == count );
+ EXPECT( s4.size() == count );
+ EXPECT( t4.size() == count );
+ EXPECT( std::equal( s1.begin(), s1.end(), arr + v.size() - count ) );
+ EXPECT( std::equal( t1.begin(), t1.end(), arr + v.size() - count ) );
+ EXPECT( std::equal( s2.begin(), s2.end(), arr + v.size() - count ) );
+ EXPECT( std::equal( t2.begin(), t2.end(), arr + v.size() - count ) );
+ EXPECT( std::equal( s3.begin(), s3.end(), arr + v.size() - count ) );
+ EXPECT( std::equal( t3.begin(), t3.end(), arr + v.size() - count ) );
+ EXPECT( std::equal( s4.begin(), s4.end(), arr + v.size() - count ) );
+ EXPECT( std::equal( t4.begin(), t4.end(), arr + v.size() - count ) );
+}
+
+CASE( "span<>: Allows to create a sub span starting at a given offset" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int, 3> w( arr );
+ size_type offset = 1;
+
+ span< int> s1 = v.subspan( offset );
+ span<const int> t1 = v.subspan( offset );
+ span< int> s2 = w.subspan( offset );
+ span<const int> t2 = w.subspan( offset );
+ span< int> s3 = v.subspan<1>( );
+ span<const int> t3 = v.subspan<1>( );
+ span< int, 2> s4 = w.subspan<1>( );
+ span<const int, 2> t4 = w.subspan<1>( );
+
+ EXPECT( s1.size() == v.size() - offset );
+ EXPECT( t1.size() == v.size() - offset );
+ EXPECT( s2.size() == v.size() - offset );
+ EXPECT( t2.size() == v.size() - offset );
+ EXPECT( s3.size() == v.size() - offset );
+ EXPECT( t3.size() == v.size() - offset );
+ EXPECT( s4.size() == v.size() - offset );
+ EXPECT( t4.size() == v.size() - offset );
+ EXPECT( std::equal( s1.begin(), s1.end(), arr + offset ) );
+ EXPECT( std::equal( t1.begin(), t1.end(), arr + offset ) );
+ EXPECT( std::equal( s2.begin(), s2.end(), arr + offset ) );
+ EXPECT( std::equal( t2.begin(), t2.end(), arr + offset ) );
+ EXPECT( std::equal( s3.begin(), s3.end(), arr + offset ) );
+ EXPECT( std::equal( t3.begin(), t3.end(), arr + offset ) );
+ EXPECT( std::equal( s4.begin(), s4.end(), arr + offset ) );
+ EXPECT( std::equal( t4.begin(), t4.end(), arr + offset ) );
+}
+
+CASE( "span<>: Allows to create a sub span starting at a given offset with a given length" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int, 3> w( arr );
+ size_type offset = 1;
+ size_type length = 1;
+
+ span< int> s1 = v.subspan( offset, length );
+ span<const int> t1 = v.subspan( offset, length );
+ span< int> s2 = w.subspan( offset, length );
+ span<const int> t2 = w.subspan( offset, length );
+ span< int, 1> s3 = v.subspan<1, 1>( );
+ span<const int, 1> t3 = v.subspan<1, 1>( );
+ span< int, 1> s4 = w.subspan<1, 1>( );
+ span<const int, 1> t4 = w.subspan<1, 1>( );
+
+ EXPECT( s1.size() == length );
+ EXPECT( t1.size() == length );
+ EXPECT( s2.size() == length );
+ EXPECT( t2.size() == length );
+ EXPECT( s3.size() == length );
+ EXPECT( t3.size() == length );
+ EXPECT( s4.size() == length );
+ EXPECT( t4.size() == length );
+ EXPECT( std::equal( s1.begin(), s1.end(), arr + offset ) );
+ EXPECT( std::equal( t1.begin(), t1.end(), arr + offset ) );
+ EXPECT( std::equal( s2.begin(), s2.end(), arr + offset ) );
+ EXPECT( std::equal( t2.begin(), t2.end(), arr + offset ) );
+ EXPECT( std::equal( s3.begin(), s3.end(), arr + offset ) );
+ EXPECT( std::equal( t3.begin(), t3.end(), arr + offset ) );
+ EXPECT( std::equal( s4.begin(), s4.end(), arr + offset ) );
+ EXPECT( std::equal( t4.begin(), t4.end(), arr + offset ) );
+}
+
+CASE( "span<>: Allows to create an empty sub span at full offset" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int, 3> w( arr );
+ size_type offset = v.size();
+
+ span< int> s1 = v.subspan( offset );
+ span<const int> t1 = v.subspan( offset );
+ span< int> s2 = w.subspan( offset );
+ span<const int> t2 = w.subspan( offset );
+ span< int> s3 = v.subspan<3>( );
+ span<const int> t3 = v.subspan<3>( );
+ span< int, 0> s4 = w.subspan<3>( );
+ span<const int, 0> t4 = w.subspan<3>( );
+
+ EXPECT( s1.empty() );
+ EXPECT( t1.empty() );
+ EXPECT( s2.empty() );
+ EXPECT( t2.empty() );
+ EXPECT( s3.empty() );
+ EXPECT( t3.empty() );
+ EXPECT( s4.empty() );
+ EXPECT( t4.empty() );
+}
+
+CASE( "span<>: Allows to create an empty sub span at full offset with zero length" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int, 3> w( arr );
+ size_type offset = v.size();
+ size_type length = 0;
+
+ span< int> s1 = v.subspan( offset, length );
+ span<const int> t1 = v.subspan( offset, length );
+ span< int> s2 = w.subspan( offset, length );
+ span<const int> t2 = w.subspan( offset, length );
+ span< int> s3 = v.subspan<3, 0>( );
+ span<const int> t3 = v.subspan<3, 0>( );
+ span< int, 0> s4 = w.subspan<3, 0>( );
+ span<const int, 0> t4 = w.subspan<3, 0>( );
+
+ EXPECT( s1.empty() );
+ EXPECT( t1.empty() );
+ EXPECT( s2.empty() );
+ EXPECT( t2.empty() );
+ EXPECT( s3.empty() );
+ EXPECT( t3.empty() );
+ EXPECT( s4.empty() );
+ EXPECT( t4.empty() );
+}
+
+CASE( "span<>: Allows forward iteration" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int, 3> w( arr );
+
+ for ( span<int>::iterator pos = v.begin(); pos != v.end(); ++pos )
+ {
+ EXPECT( *pos == arr[ std::distance( v.begin(), pos )] );
+ }
+ for ( span<int, 3>::iterator pos = w.begin(); pos != w.end(); ++pos )
+ {
+ EXPECT( *pos == arr[ std::distance( w.begin(), pos )] );
+ }
+}
+
+CASE( "span<>: Allows const forward iteration" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int, 3> w( arr );
+
+ for ( span<int>::const_iterator pos = v.cbegin(); pos != v.cend(); ++pos )
+ {
+ EXPECT( *pos == arr[ std::distance( v.cbegin(), pos )] );
+ }
+ for ( span<int, 3>::const_iterator pos = w.cbegin(); pos != w.cend(); ++pos )
+ {
+ EXPECT( *pos == arr[ std::distance( w.cbegin(), pos )] );
+ }
+}
+
+CASE( "span<>: Allows reverse iteration" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int, 3> w( arr );
+
+ for ( span<int>::reverse_iterator pos = v.rbegin(); pos != v.rend(); ++pos )
+ {
+ size_t dist = narrow_failfast<size_t>( std::distance(v.rbegin(), pos) );
+ EXPECT( *pos == arr[ v.size() - 1 - dist ] );
+ }
+ for ( span<int, 3>::reverse_iterator pos = w.rbegin(); pos != w.rend(); ++pos )
+ {
+ size_t dist = narrow_failfast<size_t>( std::distance(v.rbegin(), pos) );
+ EXPECT( *pos == arr[ w.size() - 1 - dist ] );
+ }
+}
+
+CASE( "span<>: Allows const reverse iteration" )
+{
+ int arr[] = { 1, 2, 3, };
+ const span<int> v( arr );
+ const span<int, 3> w( arr );
+
+ for ( span<int>::const_reverse_iterator pos = v.crbegin(); pos != v.crend(); ++pos )
+ {
+ size_t dist = narrow_failfast<size_t>( std::distance(v.crbegin(), pos) );
+ EXPECT( *pos == arr[ v.size() - 1 - dist ] );
+ }
+ for ( span<int>::const_reverse_iterator pos = w.crbegin(); pos != w.crend(); ++pos )
+ {
+ size_t dist = narrow_failfast<size_t>( std::distance(v.crbegin(), pos) );
+ EXPECT( *pos == arr[ w.size() - 1 - dist ] );
+ }
+}
+
+CASE( "span<>: Allows to observe an element via array indexing" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v ( arr );
+ span<int> const cv( arr );
+ span<int, 3> w ( arr );
+ span<int, 3> const cw( arr );
+
+ for ( size_type i = 0; i < v.size(); ++i )
+ {
+ EXPECT( v[i] == arr[i] );
+ EXPECT( cv[i] == arr[i] );
+ EXPECT( &v[i] == &arr[i] );
+ EXPECT( &cv[i] == &arr[i] );
+ EXPECT( w[i] == arr[i] );
+ EXPECT( cw[i] == arr[i] );
+ EXPECT( &w[i] == &arr[i] );
+ EXPECT( &cw[i] == &arr[i] );
+ }
+}
+
+CASE( "span<>: Allows to observe an element via front() and back()" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v ( arr );
+ span<int> const cv( arr );
+ span<int, 3> w ( arr );
+ span<int, 3> const cw( arr );
+
+
+ EXPECT( v.front() == arr[0] );
+ EXPECT( &v.front() == &arr[0] );
+ EXPECT( cv.front() == arr[0] );
+ EXPECT( &cv.front() == &arr[0] );
+ EXPECT( w.back() == arr[2] );
+ EXPECT( &w.back() == &arr[2] );
+ EXPECT( cw.back() == arr[2] );
+ EXPECT( &cw.back() == &arr[2] );
+}
+
+CASE( "span<>: Allows to observe an element via data()" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v ( arr );
+ span<int> const cv( arr );
+ span<int, 3> w ( arr );
+ span<int, 3> const cw( arr );
+
+ EXPECT( *v.data() == *v.begin() );
+ EXPECT( v.data() == &*v.begin() );
+ EXPECT( *cv.data() == *v.begin() );
+ EXPECT( cv.data() == &*v.begin() );
+ EXPECT( *w.data() == *v.begin() );
+ EXPECT( w.data() == &*v.begin() );
+ EXPECT( *cw.data() == *v.begin() );
+ EXPECT( cw.data() == &*v.begin() );
+
+ for ( size_type i = 0; i < v.size(); ++i )
+ {
+ EXPECT( v.data()[i] == arr[i] );
+ EXPECT( cv.data()[i] == arr[i] );
+ EXPECT( w.data()[i] == arr[i] );
+ EXPECT( cw.data()[i] == arr[i] );
+ }
+}
+
+CASE( "span<>: Allows to change an element via array indexing" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, };
+ span<int> v( arr );
+ span<int> const cv( arr );
+ span<int, 5> w( arr );
+ span<int, 5> const cw( arr );
+
+ v[1] = 22;
+ cv[2] = 33;
+ w[3] = 44;
+ cw[4] = 55;
+
+ EXPECT( 22 == arr[1] );
+ EXPECT( 33 == arr[2] );
+ EXPECT( 44 == arr[3] );
+ EXPECT( 55 == arr[4] );
+}
+
+CASE( "span<>: Allows to change an element via front() and back()" )
+{
+ int arr[] = { 1, 2, 3, };
+ int arr2[] = { 1, 2, 3, };
+ int arr3[] = { 1, 2, 3, };
+ int arr4[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int> const cv( arr2 );
+ span<int, 3> w( arr3 );
+ span<int, 3> const cw( arr4 );
+
+ v.front() = 11;
+ v.back() = 33;
+ cv.front() = 11;
+ cv.back() = 33;
+ w.front() = 11;
+ w.back() = 33;
+ cw.front() = 11;
+ cw.back() = 33;
+
+ EXPECT( 11 == arr[0] );
+ EXPECT( 33 == arr[2] );
+ EXPECT( 11 == arr2[0] );
+ EXPECT( 33 == arr2[2] );
+ EXPECT( 11 == arr3[0] );
+ EXPECT( 33 == arr3[2] );
+ EXPECT( 11 == arr4[0] );
+ EXPECT( 33 == arr4[2] );
+}
+
+CASE( "span<>: Allows to change an element via data()" )
+{
+ int arr[] = { 1, 2, 3, };
+ span<int> v( arr );
+ span<int> const cv( arr );
+ span<int, 3> w( arr );
+ span<int, 3> const cw( arr );
+
+ *v.data() = 22;
+ EXPECT( 22 == *cv.data() );
+ *cv.data() = 33;
+ EXPECT( 33 == *v.data() );
+ *w.data() = 44;
+ EXPECT( 44 == *cw.data() );
+ *cw.data() = 55;
+ EXPECT( 55 == *w.data() );
+}
+
+#if gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+CASE( "span<>: Allows to compare equal to another span of the same type" )
+{
+ int a[] = { 1 }, b[] = { 2 }, c[] = { 1, 2 };
+ span<int> va( a );
+ span<int> vb( b );
+ span<int> vc( c );
+ span<int, 1> wa( a );
+ span<int, 1> wb( b );
+ span<int, 2> wc( c );
+
+ EXPECT( va == va );
+ EXPECT_NOT( vb == va );
+ EXPECT_NOT( vc == va );
+ EXPECT( wa == wa );
+ EXPECT( va == wa );
+ EXPECT_NOT( vb == wa );
+ EXPECT_NOT( vc == wa );
+}
+
+CASE( "span<>: Allows to compare unequal to another span of the same type" )
+{
+ int a[] = { 1 }, b[] = { 2 }, c[] = { 1, 2 };
+ span<int> va( a );
+ span<int> vb( b );
+ span<int> vc( c );
+ span<int, 1> wa( a );
+ span<int, 1> wb( b );
+ span<int, 2> wc( c );
+
+ EXPECT_NOT( va != va );
+ EXPECT( vb != va );
+ EXPECT( vc != va );
+ EXPECT( vc != va );
+ EXPECT_NOT( wa != wa );
+ EXPECT( wa != wb );
+ EXPECT_NOT( va != wa );
+ EXPECT( vb != wa );
+ EXPECT( vc != wa );
+}
+
+CASE( "span<>: Allows to compare less than another span of the same type" )
+{
+ int a[] = { 1 }, b[] = { 2 }, c[] = { 1, 2 };
+ span<int> va( a );
+ span<int> vb( b );
+ span<int> vc( c );
+ span<int, 1> wa( a );
+ span<int, 1> wb( b );
+ span<int, 2> wc( c );
+
+ EXPECT_NOT( va < va );
+ EXPECT( va < vb );
+ EXPECT( va < vc );
+ EXPECT_NOT( wa < wa );
+ EXPECT( wa < wb );
+ EXPECT( wa < wc );
+ EXPECT_NOT( va < wa );
+ EXPECT( va < wb );
+ EXPECT( va < wc );
+}
+
+CASE( "span<>: Allows to compare less than or equal to another span of the same type" )
+{
+ int a[] = { 1 }, b[] = { 2 }, c[] = { 1, 2 };
+ span<int> va( a );
+ span<int> vb( b );
+ span<int> vc( c );
+ span<int, 1> wa( a );
+ span<int, 1> wb( b );
+ span<int, 2> wc( c );
+
+ EXPECT_NOT( vb <= va );
+ EXPECT( va <= vb );
+ EXPECT( va <= vc );
+ EXPECT_NOT( wb <= wa );
+ EXPECT( wa <= wb );
+ EXPECT( wa <= wc );
+ EXPECT_NOT( vb <= wa );
+ EXPECT( va <= wb );
+ EXPECT( va <= wc );
+}
+
+CASE( "span<>: Allows to compare greater than another span of the same type" )
+{
+ int a[] = { 1 }, b[] = { 2 }, c[] = { 1, 2 };
+ span<int> va( a );
+ span<int> vb( b );
+ span<int> vc( c );
+ span<int, 1> wa( a );
+ span<int, 1> wb( b );
+ span<int, 2> wc( c );
+
+ EXPECT_NOT( va > va );
+ EXPECT( vb > va );
+ EXPECT( vc > va );
+ EXPECT_NOT( wa > wa );
+ EXPECT( wb > wa );
+ EXPECT( wc > wa );
+ EXPECT_NOT( va > wa );
+ EXPECT( vb > wa );
+ EXPECT( vc > wa );
+}
+
+CASE( "span<>: Allows to compare greater than or equal to another span of the same type" )
+{
+ int a[] = { 1 }, b[] = { 2 }, c[] = { 1, 2 };
+ span<int> va( a );
+ span<int> vb( b );
+ span<int> vc( c );
+ span<int, 1> wa( a );
+ span<int, 1> wb( b );
+ span<int, 2> wc( c );
+
+ EXPECT_NOT( va >= vb );
+ EXPECT( vb >= va );
+ EXPECT( vc >= va );
+ EXPECT_NOT( wa >= wb );
+ EXPECT( wb >= wa );
+ EXPECT( wc >= wa );
+ EXPECT_NOT( va >= wb );
+ EXPECT( vb >= wa );
+ EXPECT( vc >= wa );
+}
+
+CASE( "span<>: Allows to compare to another span of the same type and different cv-ness (non-standard)" )
+{
+#if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+ int aa[] = { 1 }, bb[] = { 2 };
+ span< int> a( aa );
+ span< const int> ca( aa );
+ span<volatile int> va( aa );
+ span< int> b( bb );
+ span< const int> cb( bb );
+ span< int, 1> af( aa );
+ span< const int, 1> caf( aa );
+ span<volatile int, 1> vaf( aa );
+ span< int, 1> bf( bb );
+ span< const int, 1> cbf( bb );
+
+ EXPECT( va == ca );
+ EXPECT( a == va );
+ EXPECT( vaf == caf );
+ EXPECT( af == vaf );
+ EXPECT( va == caf );
+ EXPECT( a == vaf );
+
+ EXPECT( a == ca );
+ EXPECT( a != cb );
+ EXPECT( a <= cb );
+ EXPECT( a < cb );
+ EXPECT( b >= ca );
+ EXPECT( b > ca );
+ EXPECT( af == ca );
+ EXPECT( af != cb );
+ EXPECT( af <= cb );
+ EXPECT( af < cb );
+ EXPECT( bf >= ca );
+ EXPECT( bf > ca );
+#else
+ EXPECT( !!"span<>: cannot compare different types (gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=0)" );
+#endif
+}
+
+CASE( "span<>: Allows to compare empty spans as equal" )
+{
+ int a;
+
+ span<int> p;
+ span<int> q;
+ span<int> r( &a, size_type( 0 ) );
+ span<int, 0> s;
+ span<int, 0> t( &a, size_type( 0 ) );
+
+ EXPECT( p == q );
+ EXPECT( p == r );
+ EXPECT( p == s );
+ EXPECT( p == t );
+ EXPECT( s == t );
+}
+#endif // gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+
+CASE( "span<>: Allows to test for empty span via empty(), empty case" )
+{
+ span<int> v;
+ span<int, 0> w;
+
+ EXPECT( v.empty() );
+ EXPECT( w.empty() );
+}
+
+CASE( "span<>: Allows to test for empty span via empty(), non-empty case" )
+{
+ int a[] = { 1 };
+ span<int> v( a );
+ span<int, 1> w( a );
+
+ EXPECT_NOT( v.empty() );
+ EXPECT_NOT( w.empty() );
+}
+
+CASE( "span<>: Allows to obtain the number of elements via size(), as configured" )
+{
+ int a[] = { 1, 2, 3, };
+ int b[] = { 1, 2, 3, 4, 5, };
+
+ span<int> z;
+ span<int> va( a );
+ span<int> vb( b );
+ span<int, 0> y;
+ span<int, 3> wa( a );
+ span<int, 5> wb( b );
+
+ EXPECT( va.size() == size_type( gsl_DIMENSION_OF( a ) ) );
+ EXPECT( vb.size() == size_type( gsl_DIMENSION_OF( b ) ) );
+ EXPECT( wa.size() == size_type( gsl_DIMENSION_OF( a ) ) );
+ EXPECT( wb.size() == size_type( gsl_DIMENSION_OF( b ) ) );
+ EXPECT( z.size() == size_type( 0 ) );
+ EXPECT( y.size() == size_type( 0 ) );
+}
+
+CASE( "span<>: Allows to obtain the number of elements via ssize(), signed" )
+{
+ int a[] = { 1, 2, 3, };
+ int b[] = { 1, 2, 3, 4, 5, };
+
+ span<int> z;
+ span<int> va( a );
+ span<int> vb( b );
+ span<int, 0> y;
+ span<int, 3> wa( a );
+ span<int, 5> wb( b );
+
+ EXPECT( va.ssize() == difference_type( gsl_DIMENSION_OF( a ) ) );
+ EXPECT( vb.ssize() == difference_type( gsl_DIMENSION_OF( b ) ) );
+ EXPECT( wa.ssize() == difference_type( gsl_DIMENSION_OF( a ) ) );
+ EXPECT( wb.ssize() == difference_type( gsl_DIMENSION_OF( b ) ) );
+ EXPECT( z.ssize() == difference_type( 0 ) );
+ EXPECT( y.ssize() == difference_type( 0 ) );
+}
+
+CASE( "span<>: Allows to obtain the number of bytes via size_bytes()" )
+{
+ int a[] = { 1, 2, 3, };
+ int b[] = { 1, 2, 3, 4, 5, };
+
+ span<int> z;
+ span<int> va( a );
+ span<int> vb( b );
+ span<int, 0> y;
+ span<int, 3> wa( a );
+ span<int, 5> wb( b );
+
+ EXPECT( va.size_bytes() == size_type( gsl_DIMENSION_OF( a ) * sizeof(int) ) );
+ EXPECT( vb.size_bytes() == size_type( gsl_DIMENSION_OF( b ) * sizeof(int) ) );
+ EXPECT( wa.size_bytes() == size_type( gsl_DIMENSION_OF( a ) * sizeof(int) ) );
+ EXPECT( wb.size_bytes() == size_type( gsl_DIMENSION_OF( b ) * sizeof(int) ) );
+ EXPECT( z.size_bytes() == size_type( 0 ) );
+ EXPECT( y.size_bytes() == size_type( 0 ) );
+}
+
+CASE( "span<>: Allows to swap with another span of the same type" )
+{
+ int a[] = { 1, 2, 3, };
+ int b[] = { 1, 2, 3, 4, 5, };
+ int c[] = { 4, 5, 6, };
+
+ span<int> va0( a );
+ span<int> vb0( b );
+ span<int> va( a );
+ span<int> vb( b );
+ span<int, 3> wa0( a );
+ span<int, 3> wc0( c );
+ span<int, 3> wa( a );
+ span<int, 3> wc( c );
+
+ va.swap( vb );
+ wa.swap( wc );
+
+ EXPECT( va.data() == vb0.data() ); EXPECT( va.size() == vb0.size() );
+ EXPECT( vb.data() == va0.data() ); EXPECT( vb.size() == va0.size() );
+ EXPECT( wa.data() == wc0.data() ); EXPECT( wa.size() == wc0.size() );
+ EXPECT( wc.data() == wa0.data() ); EXPECT( wc.size() == wa0.size() );
+}
+
+bool is_little_endian()
+{
+ union U
+ {
+ U() : i(1) {}
+ int i;
+ unsigned char c[ sizeof(int) ];
+ };
+ return 1 != U().c[ sizeof(int) - 1 ];
+}
+
+CASE( "span<>: Allows to view the elements as read-only bytes" )
+{
+#if gsl_FEATURE( BYTE )
+# if gsl_HAVE( SIZED_TYPES )
+ typedef int32_t type;
+# else
+ typedef int type;
+# endif
+ typedef gsl_lite::byte gyte;
+
+ EXPECT( sizeof( type ) == size_t( 4 ) );
+
+ type a[] = { 0x12345678, };
+ gyte be[] = { to_byte(0x12), to_byte(0x34), to_byte(0x56), to_byte(0x78), };
+ gyte le[] = { to_byte(0x78), to_byte(0x56), to_byte(0x34), to_byte(0x12), };
+
+ gyte * b = is_little_endian() ? le : be;
+
+ span<type> va( a );
+ span<const gyte> vc( as_bytes( va ) );
+
+ EXPECT( vc[0] == b[0] );
+ EXPECT( vc[1] == b[1] );
+ EXPECT( vc[2] == b[2] );
+ EXPECT( vc[3] == b[3] );
+
+#endif // gsl_FEATURE( BYTE )
+}
+
+CASE( "span<>: Allows to view and change the elements as writable bytes" )
+{
+#if gsl_FEATURE( BYTE )
+# if gsl_HAVE( SIZED_TYPES )
+ typedef int32_t type;
+# else
+ typedef int type;
+# endif
+ typedef gsl_lite::byte gyte;
+
+ EXPECT( sizeof(type) == size_t( 4 ) );
+
+ {
+ type a[] = { 0x0, };
+ span<type> va( a );
+ span<gyte> vc( as_writable_bytes(va) );
+
+ for ( size_t i = 0; i < sizeof(type); ++i )
+ {
+ EXPECT( vc[i] == to_byte(0) );
+ }
+
+ vc[0] = to_byte(0x42);
+
+ EXPECT( vc[0] == to_byte(0x42) );
+ for ( size_t i = 1; i < sizeof(type); ++i )
+ {
+ EXPECT( vc[i] == to_byte(0) );
+ }
+ }
+
+#endif // gsl_FEATURE( BYTE )
+}
+
+CASE( "span<>: Allows to view the elements as a span of another type" )
+{
+#if ! gsl_DEPRECATE_TO_LEVEL( 9 )
+# if gsl_HAVE( SIZED_TYPES )
+ typedef int32_t type1;
+ typedef int16_t type2;
+# else
+ typedef int type1;
+ typedef short type2;
+# endif
+ EXPECT( sizeof( type1 ) == size_t( 4 ) );
+ EXPECT( sizeof( type2 ) == size_t( 2 ) );
+
+ type1 a[] = { 0x12345678, };
+ type2 be[] = { type2(0x1234), type2(0x5678), };
+ type2 le[] = { type2(0x5678), type2(0x1234), };
+
+ type2 * b = is_little_endian() ? le : be;
+
+ span<type1> va( a );
+ span<type2> vb( va.as_span<type2>() );
+
+ EXPECT( vb[0] == b[0] );
+ EXPECT( vb[1] == b[1] );
+#endif // ! gsl_DEPRECATE_TO_LEVEL( 9 )
+}
+
+CASE( "span<>: Allows to change the elements from a span of another type" )
+{
+#if ! gsl_DEPRECATE_TO_LEVEL( 9 )
+# if gsl_HAVE( SIZED_TYPES )
+ typedef int32_t type1;
+ typedef int16_t type2;
+# else
+ typedef int type1;
+ typedef short type2;
+# endif
+ EXPECT( sizeof( type1 ) == size_t( 4 ) );
+ EXPECT( sizeof( type2 ) == size_t( 2 ) );
+
+ type1 a[] = { 0x0, };
+
+ span<type1> va( a );
+ span<type2> vb( va.as_span<type2>() );
+
+ {for ( size_t i = 0; i < sizeof(type2); ++i ) EXPECT( vb[i] == type2(0) ); }
+
+ vb[0] = 0x42;
+
+ EXPECT( vb[0] == type2(0x42) );
+ {for ( size_t i = 1; i < sizeof(type2); ++i ) EXPECT( vb[i] == type2(0) ); }
+#endif // ! gsl_DEPRECATE_TO_LEVEL( 9 )
+}
+
+CASE( "span<>: Allows default construction of iterators" )
+{
+ span<int>::iterator it1;
+ span<int>::iterator it2;
+ EXPECT(it1 == it2);
+}
+
+CASE( "span<>: Allows comparison of iterators from same span" )
+{
+ int a[] = {1, 2, 3, 4};
+
+ span<int> s = a;
+ span<int>::iterator it = s.begin();
+ span<int>::iterator it2 = it + 1;
+
+ EXPECT(it == it);
+ EXPECT(it == s.begin());
+ EXPECT(s.begin() == it);
+
+ EXPECT(it != it2);
+ EXPECT(it2 != it);
+ EXPECT(it != s.end());
+ EXPECT(it2 != s.end());
+ EXPECT(s.end() != it);
+
+ EXPECT(it < it2);
+ EXPECT(it <= it2);
+ EXPECT(it2 <= s.end());
+ EXPECT(it < s.end());
+
+ EXPECT(it2 > it);
+ EXPECT(it2 >= it);
+ EXPECT(s.end() > it2);
+ EXPECT(s.end() >= it2);
+}
+
+CASE( "span<>: Terminates comparison of iterators from different spans" )
+{
+ struct F {
+ static void blow()
+ {
+ int a[] = {1, 2, 3, 4};
+ int b[] = {1, 2, 3, 4};
+ span<int> s( a );
+ span<int> s2( b );
+
+ (void) ( s.begin() == s2.begin() );
+ }};
+ struct G {
+ static void blow()
+ {
+ int a[] = {1, 2, 3, 4};
+ int b[] = {1, 2, 3, 4};
+ span<int> s( a );
+ span<int> s2( b );
+
+ (void) ( s.begin() <= s2.begin() );
+ }};
+
+ EXPECT_THROWS( F::blow() );
+ EXPECT_THROWS( G::blow() );
+}
+
+CASE( "span<>: Allows dereferencing iterators" )
+{
+ {
+ int a[] = {1, 2, 3, 4};
+ span<int> s = a;
+
+ span<int>::iterator it = s.begin();
+#if gsl_STDLIB_CPP11_OR_GREATER
+ span<int>::iterator it2 = std::begin(s);
+#else // ! gsl_STDLIB_CPP11_OR_GREATER
+ span<int>::iterator it2 = s.begin();
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+ EXPECT(it == it2);
+
+ it = s.end();
+#if gsl_STDLIB_CPP11_OR_GREATER
+ it2 = std::end(s);
+#else // ! gsl_STDLIB_CPP11_OR_GREATER
+ it2 = s.end();
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+ EXPECT(it == it2);
+ }
+
+ {
+ int a[] = {1, 2, 3, 4};
+ span<int> s = a;
+
+ span<int>::iterator it = s.begin();
+ span<int>::iterator first = it;
+ EXPECT(it == first);
+ EXPECT(*it == 1);
+
+ span<int>::iterator beyond = s.end();
+ EXPECT(it != beyond);
+
+ EXPECT(beyond - first == difference_type( 4 ));
+ EXPECT(first - first == difference_type( 0 ));
+ EXPECT(beyond - beyond == difference_type( 0 ));
+
+ ++it;
+ EXPECT(it - first == difference_type( 1 ));
+ EXPECT(*it == 2);
+ *it = 22;
+ EXPECT(*it == 22);
+ EXPECT(beyond - it == difference_type( 3 ));
+
+ it = first;
+ EXPECT(it == first);
+ while (it != s.end())
+ {
+ *it = 5;
+ ++it;
+ }
+
+ EXPECT(it == beyond);
+ EXPECT(it - beyond == difference_type( 0 ));
+
+ for (span<int>::const_iterator pos = s.begin(); pos != s.end(); ++pos)
+ {
+ EXPECT(*pos == 5);
+ }
+ }
+}
+
+CASE( "span<>: Terminates dereferencing past-the-end iterators" )
+{
+ int a[] = {1, 2, 3, 4};
+ span<int> s = a;
+
+ span<int>::iterator beyond = s.end();
+ EXPECT_THROWS(*beyond);
+}
+
+CASE( "span<>: Allows dereferencing reverse iterators" )
+{
+ int a[] = {1, 2, 3, 4};
+ span<int> s = a;
+
+ span<int>::reverse_iterator it = s.rbegin();
+ span<int>::reverse_iterator first = it;
+ EXPECT(it == first);
+ EXPECT(*it == 4);
+
+ span<int>::reverse_iterator beyond = s.rend();
+ EXPECT(it != beyond);
+
+ EXPECT(beyond - first == difference_type( 4 ));
+ EXPECT(first - first == difference_type( 0 ));
+ EXPECT(beyond - beyond == difference_type( 0 ));
+
+ ++it;
+ EXPECT(it - s.rbegin() == difference_type( 1 ));
+ EXPECT(*it == 3);
+ *it = 22;
+ EXPECT(*it == 22);
+ EXPECT(beyond - it == difference_type( 3 ));
+
+ it = first;
+ EXPECT(it == first);
+ while (it != s.rend())
+ {
+ *it = 5;
+ ++it;
+ }
+
+ EXPECT(it == beyond);
+ EXPECT(it - beyond == difference_type( 0 ));
+
+ for (span<int>::const_reverse_iterator pos = s.rbegin(); pos != s.rend(); ++pos)
+ {
+ EXPECT(*pos == 5);
+ }
+}
+
+CASE( "span<>: Terminates dereferencing past-the-end reverse iterators" )
+{
+ struct F {
+ static void blow()
+ {
+ int a[] = {1, 2, 3, 4};
+ span<int> s = a;
+
+ span<int>::reverse_iterator beyond = s.rend();
+ (void) *beyond;
+ }};
+
+ EXPECT_THROWS(F::blow());
+}
+
+CASE( "span<>: Allows appropriate fixed-size conversions" )
+{
+ int arr[] = {1, 2, 3, 4};
+
+ // converting to a span from an equal size array is ok
+ span<int, 4> s4 = arr;
+ EXPECT(s4.size() == size_type( 4 ));
+
+ // converting to dynamic_range is always ok
+ {
+ span<int> s = s4;
+ EXPECT(s.size() == s4.size());
+ (void) s;
+ }
+
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+ // initialization or assignment to static span is NOT ok
+ static_assert( !std::is_convertible< int[4], span<int, 2> >::value, "static assertion failed" );
+ static_assert( !std::is_convertible< span<int, 4>, span<int, 2> >::value, "static assertion failed" );
+ static_assert( !std::is_convertible< int[2], span<int, 4> >::value, "static assertion failed" );
+ static_assert( !std::is_convertible< span<int, 2>, span<int, 4> >::value, "static assertion failed" );
+
+ // even when done dynamically
+ static_assert( !std::is_convertible< span<int>, span<int, 2> >::value, "static assertion failed" );
+
+ // but doing so explicitly is ok
+ static_assert( std::is_constructible< span<int>, span<int, 2> >::value, "static assertion failed" );
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+
+ // you can convert statically
+ {
+ const span<int, 2> s2( &arr[0], 2 );
+ (void) s2;
+ }
+ {
+ const span<int, 1> s1 = s4.first<1>();
+ (void) s1;
+ }
+}
+
+CASE( "span<>: Terminates inappropriate fixed-size conversions" )
+{
+ struct F {
+ static void blow()
+ {
+ int arr2[2] = {1, 2};
+ const span<int, 4> s4(arr2, 2);
+ (void) s4;
+ }};
+
+ EXPECT_THROWS( F::blow() );
+}
+
+CASE( "copy(): Allows to copy a span to another span of the same element type" )
+{
+ int a[] = { 1, 2, 3, };
+ int b[] = { 0, 0, 0, 0, 0, };
+ int c[] = { 0, 0, 0, 0, 0, };
+ int d[] = { 0, 0, 0, 0, 0, };
+ int e[] = { 0, 0, 0, 0, 0, };
+
+ span<int> src1( a );
+ span<int, 3> src2( a );
+ span<int> dst1( b );
+ span<int, 5> dst2( c );
+ span<int> dst3( d );
+ span<int, 5> dst4( e );
+
+ copy( src1, dst1 );
+ copy( src1, dst2 );
+ copy( src2, dst3 );
+ copy( src2, dst4 );
+
+ EXPECT( std::equal(src1.begin(), src1.end(), dst1.begin()) );
+ EXPECT( std::equal(src1.begin(), src1.end(), dst2.begin()) );
+ EXPECT( std::equal(src1.begin(), src1.end(), dst3.begin()) );
+ EXPECT( std::equal(src1.begin(), src1.end(), dst4.begin()) );
+}
+
+CASE( "copy(): Allows to copy a span to another span of a different element type" )
+{
+ char a[] = { 'a', 'b', 'c', };
+ int b[] = { 0 , 0 , 0 , 0, 0, };
+ int c[] = { 0 , 0 , 0 , 0, 0, };
+ int d[] = { 0 , 0 , 0 , 0, 0, };
+ int e[] = { 0 , 0 , 0 , 0, 0, };
+
+ span<char> src1( a );
+ span<char, 3> src2( a );
+ span<int> dst1( b );
+ span<int, 5> dst2( c );
+ span<int> dst3( d );
+ span<int, 5> dst4( e );
+
+ copy( src1, dst1 );
+ copy( src1, dst2 );
+ copy( src2, dst3 );
+ copy( src2, dst4 );
+
+ for ( span<int>::size_type i = 0; i < src1.size(); ++i )
+ {
+ EXPECT( src1[i] == dst1[i] );
+ EXPECT( src1[i] == dst2[i] );
+ EXPECT( src1[i] == dst3[i] );
+ EXPECT( src1[i] == dst4[i] );
+ }
+}
+
+CASE( "size(): Allows to obtain the number of elements in span via size(span), unsigned" )
+{
+ int a[] = { 1, 2, 3, };
+ int b[] = { 1, 2, 3, 4, 5, };
+
+ span<int> z;
+ span<int> va( a );
+ span<int> vb( b );
+ span<int, 0> y;
+ span<int, 3> wa( a );
+ span<int, 5> wb( b );
+
+ EXPECT( size( va ) == size_type( gsl_DIMENSION_OF( a ) ) );
+ EXPECT( size( vb ) == size_type( gsl_DIMENSION_OF( b ) ) );
+ EXPECT( size( wa ) == size_type( gsl_DIMENSION_OF( a ) ) );
+ EXPECT( size( wb ) == size_type( gsl_DIMENSION_OF( b ) ) );
+ EXPECT( size( z ) == size_type( 0 ) );
+ EXPECT( size( y ) == size_type( 0 ) );
+}
+
+CASE( "ssize(): Allows to obtain the number of elements in span via ssize(span), signed" )
+{
+ int a[] = { 1, 2, 3, };
+ int b[] = { 1, 2, 3, 4, 5, };
+
+ span<int> z;
+ span<int> va( a );
+ span<int> vb( b );
+ span<int, 0> y;
+ span<int, 3> wa( a );
+ span<int, 5> wb( b );
+
+ EXPECT( ssize( va ) == difference_type( gsl_DIMENSION_OF( a ) ) );
+ EXPECT( ssize( vb ) == difference_type( gsl_DIMENSION_OF( b ) ) );
+ EXPECT( ssize( wa ) == difference_type( gsl_DIMENSION_OF( a ) ) );
+ EXPECT( ssize( wb ) == difference_type( gsl_DIMENSION_OF( b ) ) );
+ EXPECT( ssize( z ) == difference_type( 0 ) );
+ EXPECT( ssize( y ) == difference_type( 0 ) );
+}
+
+#if ! gsl_FEATURE_TO_STD( MAKE_SPAN )
+
+CASE( "make_span(): unavailable (gsl_FEATURE_MAKE_SPAN=0)" )
+{
+ EXPECT( !!"(avoid warning)" ); // suppress: unused parameter 'lest_env' [-Wunused-parameter]
+}
+
+#else
+
+CASE( "make_span(): (gsl_FEATURE_MAKE_SPAN=1)" )
+{
+ EXPECT( !!"(avoid warning)" ); // suppress: unused parameter 'lest_env' [-Wunused-parameter]
+}
+
+CASE( "make_span(): Allows to build from two pointers" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<int> v = make_span( arr, arr + gsl_DIMENSION_OF( arr ) );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+}
+
+CASE( "make_span(): Allows to build from two const pointers" )
+{
+ const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<const int> v = make_span( arr, arr + gsl_DIMENSION_OF( arr ) );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+}
+
+CASE( "make_span(): Allows to build from a non-null pointer and a size" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<int> v = make_span( arr, gsl_DIMENSION_OF( arr ) );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+}
+
+CASE( "make_span(): Allows to build from a non-null const pointer and a size" )
+{
+ const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<const int> v = make_span( arr, gsl_DIMENSION_OF( arr ) );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+}
+
+CASE( "make_span(): Allows to build from a C-array" )
+{
+ int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<int> v = make_span( arr );
+ span<int, 9> w = make_span( arr );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr ) );
+}
+
+CASE( "make_span(): Allows to build from a const C-array" )
+{
+ const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<const int> v = make_span( arr );
+ span<const int, 9> w = make_span( arr );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr ) );
+}
+
+CASE( "make_span(): Allows building from a std::initializer_list<> (C++11)" )
+{
+#if gsl_HAVE( INITIALIZER_LIST ) && ( gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR ) )
+ auto il = { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ span<int const> v = make_span( il );
+
+ EXPECT( std::equal( v.begin(), v.end(), il.begin() ) );
+#else
+ EXPECT( !!"std::initializer_list<> is not available (no C++11)" );
+#endif
+}
+
+CASE( "make_span(): Allows to build from a std::array<> (C++11)" )
+{
+#if gsl_HAVE( ARRAY )
+ std::array<int,9> arr = {{ 1, 2, 3, 4, 5, 6, 7, 8, 9, }};
+
+ span<int> v = make_span( arr );
+ span<int, 9> w = make_span( arr );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr.begin() ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr.begin() ) );
+#else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+#endif
+}
+
+CASE( "make_span(): Allows to build from a const std::array<> (C++11)" )
+{
+#if gsl_HAVE( ARRAY )
+ const std::array<int,9> arr = {{ 1, 2, 3, 4, 5, 6, 7, 8, 9, }};
+
+ span<const int> v = make_span( arr );
+ span<const int, 9> w = make_span( arr );
+
+ EXPECT( std::equal( v.begin(), v.end(), arr.begin() ) );
+ EXPECT( std::equal( w.begin(), w.end(), arr.begin() ) );
+#else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+#endif
+}
+
+CASE( "make_span(): Allows to build from a container (std::vector<>)" )
+{
+ std::vector<int> vec = vector_iota(10);
+ span<int> v = make_span( vec );
+
+ EXPECT( std::equal( v.begin(), v.end(), vec.begin() ) );
+}
+
+CASE( "make_span(): Allows to build from a const container (std::vector<>)" )
+{
+ const std::vector<int> vec = vector_iota(10);
+ span<const int> v = make_span( vec );
+
+ EXPECT( std::equal( v.begin(), v.end(), vec.begin() ) );
+}
+
+CASE( "make_span(): Allows to build from a temporary container (potentially dangerous)" )
+{
+ std::vector<int> vec = vector_iota(10);
+
+ EXPECT( std::equal( vec.begin(), vec.end(), make_span( vector_iota( 10 ) ).begin() ) );
+}
+
+CASE( "make_span(): Allows to tag-build from a container (std::vector<>)" )
+{
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ std::vector<int> vec = vector_iota(10);
+ span< int> v = make_span( with_container, vec );
+ span<const int> w = make_span( with_container, vec );
+
+ EXPECT( std::equal( v.begin(), v.end(), vec.begin() ) );
+ EXPECT( std::equal( w.begin(), w.end(), vec.begin() ) );
+#else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+#endif
+}
+
+CASE( "make_span(): Allows to tag-build from a temporary container (potentially dangerous)" )
+{
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ std::vector<int> vec = vector_iota(10);
+
+ EXPECT( std::equal( vec.begin(), vec.end(), make_span( with_container, vector_iota( 10 ) ).begin() ) );
+#else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+#endif
+}
+
+#endif // gsl_FEATURE( MAKE_SPAN )
+
+#if ! gsl_FEATURE( BYTE ) || ! gsl_FEATURE_TO_STD( BYTE_SPAN )
+
+CASE( "byte_span(): unavailable (gsl_FEATURE_BYTE_SPAN=0)" )
+{
+ EXPECT( !!"(avoid warning)" ); // suppress: unused parameter 'lest_env' [-Wunused-parameter]
+}
+
+#else
+
+CASE( "byte_span() (gsl_FEATURE_BYTE_SPAN=1)" )
+{
+ EXPECT( !!"(avoid warning)" ); // suppress: unused parameter 'lest_env' [-Wunused-parameter]
+}
+
+# if gsl_COMPILER_MSVC_VERSION
+# pragma warning( push )
+# pragma warning( disable : 4127 ) // conditional expression is constant
+# endif
+
+CASE( "byte_span(): Allows to build a span of gsl_lite::byte from a single object" )
+{
+# if gsl_HAVE( ENUM_CLASS )
+ int x = (std::numeric_limits<int>::max)();
+
+ span<gsl_lite::byte> spn = byte_span( x );
+
+ EXPECT( spn.size() == size_type( sizeof x ) );
+ if ( sizeof x > 1 )
+ {
+ if ( std20::endian::native == std20::endian::little )
+ {
+ EXPECT( spn[0] == to_byte( 0xff ) );
+ EXPECT( spn[sizeof x - 1] == to_byte( 0x7f ) );
+ }
+ else if ( std20::endian::native == std20::endian::big )
+ {
+ EXPECT( spn[sizeof x - 1] == to_byte( 0xff ) );
+ EXPECT( spn[0] == to_byte( 0x7f ) );
+ }
+ }
+# endif // gsl_HAVE( ENUM_CLASS )
+}
+
+CASE( "byte_span(): Allows to build a span of const gsl_lite::byte from a single const object" )
+{
+# if gsl_HAVE( ENUM_CLASS )
+ const int x = (std::numeric_limits<int>::max)();
+
+ span<const gsl_lite::byte> spn = byte_span( x );
+
+ EXPECT( spn.size() == size_type( sizeof x ) );
+ if ( sizeof x > 1 )
+ {
+ if ( std20::endian::native == std20::endian::little )
+ {
+ EXPECT( spn[0] == to_byte( 0xff ) );
+ EXPECT( spn[sizeof x - 1] == to_byte( 0x7f ) );
+ }
+ else if ( std20::endian::native == std20::endian::big )
+ {
+ EXPECT( spn[sizeof x - 1] == to_byte( 0xff ) );
+ EXPECT( spn[0] == to_byte( 0x7f ) );
+ }
+ }
+# endif // gsl_HAVE( ENUM_CLASS )
+}
+
+# if gsl_COMPILER_MSVC_VERSION
+# pragma warning( pop )
+# endif
+
+#endif // span_PROVIDE( BYTE_SPAN )
+
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/string_span.t.cpp b/thirdparty/gsl-lite/test/string_span.t.cpp
new file mode 100644
index 000000000..0756e4139
--- /dev/null
+++ b/thirdparty/gsl-lite/test/string_span.t.cpp
@@ -0,0 +1,1461 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+
+#include <sstream> // std::ostringstream
+#include <string.h> // strlen()
+
+#if gsl_HAVE( WCHAR )
+# include <wchar.h> // wcslen()
+#endif
+
+using namespace gsl_lite;
+
+#if gsl_FEATURE( STRING_SPAN )
+
+typedef string_span::index_type index_type;
+
+template< typename T >
+inline std::vector<T> vector_iota( int n )
+{
+ std::vector<T> result;
+
+ for ( int i = 0; i < n; ++i )
+ result.push_back( static_cast<T>( i ) );
+
+ return result;
+}
+
+CASE( "string_span: Disallows construction of a string_span from a cstring_span (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+# if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+ cstring_span sv = "hello";
+
+ string_span v2 = sv;
+# endif
+}
+
+CASE( "string_span: Disallows construction of a string_span from a const std::string (define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS)" )
+{
+# if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+ const std::string s = "hello, world";
+
+ string_span sv( s );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+# endif
+}
+
+CASE( "string_span: Allows to default-construct" )
+{
+ string_span s;
+
+ EXPECT( s.size() == index_type( 0 ) );
+}
+
+CASE( "string_span: Allows to construct from a nullptr (C++11)" )
+{
+# if gsl_HAVE( NULLPTR )
+ string_span v( nullptr );
+ cstring_span w( nullptr );
+
+ EXPECT( v.size() == index_type( 0 ) );
+ EXPECT( w.size() == index_type( 0 ) );
+# else
+ EXPECT( !!"nullptr is not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a const C-string" )
+{
+ cstring_span sv = "hello";
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == "hello" );
+}
+
+CASE( "string_span: Allows to construct a string_span from a non-const C-string and size" )
+{
+ char s[] = "hello";
+
+ string_span sv( s, strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a string_span from a non-const C-string begin and end pointer" )
+{
+ char s[] = "hello";
+
+ string_span sv( s, s + strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a string_span from a non-const C-array" )
+{
+ char s[] = { 'w', 'o', 'r', 'l', 'd', '\0' };
+
+ string_span sv( s );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == "world" );
+}
+
+CASE( "string_span: Allows to construct a string_span from a non-const std::string" )
+{
+ std::string s = "hello, world";
+
+ string_span sv( s );
+
+ EXPECT( sv.length() == 12u );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a string_span from a non-const std::array (C++11)" )
+{
+# if gsl_HAVE( ARRAY )
+ std::array<char,6> arr = {{ 'w', 'o', 'r', 'l', 'd', '\0' }};
+
+ string_span sv( arr );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), arr.begin() ) );
+# else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a string_span from a non-const container (std::vector)" )
+{
+
+# if gsl_HAVE( INITIALIZER_LIST )
+ std::vector<char> vec = { 'w', 'o', 'r', 'l', 'd', '\0' };
+# else
+ std::vector<char> vec( 6, 'w' );
+# endif
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ string_span sv( vec );
+
+ EXPECT( sv.length() == index_type( 6 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a string_span from a non-const container, via a tag (std::vector)" )
+{
+# if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ std::vector<char> vec = vector_iota<char>( 10 );
+
+ string_span sv( with_container, vec );
+
+ EXPECT( sv.length() == index_type( 10 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a non-const C-string and size" )
+{
+ char s[] = "hello";
+
+ cstring_span sv( s, strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a non-const C-string begin and end pointer" )
+{
+ char s[] = "hello";
+
+ cstring_span sv( s, s + strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a non-const C-array" )
+{
+ char s[] = { 'w', 'o', 'r', 'l', 'd', '\0' };
+
+ cstring_span sv( s );
+
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_COMPILER_MSVC_VERSION
+ EXPECT( sv.length() == index_type( 5 ) );
+# elif gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ EXPECT( !!"Warning: Unconstrained span container constructor enabled: terminating '\0' included in span" );
+ EXPECT( sv.length() == index_type( 6 ) );
+# else
+ EXPECT( sv.length() == index_type( 5 ) );
+# endif
+ EXPECT( std::string( sv.data() ) == "world" );
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a non-const std::string" )
+{
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ std::string s = "hello, world";
+
+ cstring_span sv( s );
+
+ EXPECT( sv.length() == 12u );
+ EXPECT( std::string( sv.data() ) == s );
+# else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a non-const std::array (C++11)" )
+{
+# if gsl_HAVE( ARRAY )
+ std::array<char,6> arr = {{ 'w', 'o', 'r', 'l', 'd', '\0' }};
+
+ cstring_span sv( arr );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), arr.begin() ) );
+# else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a non-const container (std::vector)" )
+{
+# if gsl_HAVE( INITIALIZER_LIST )
+ std::vector<char> vec = { 'w', 'o', 'r', 'l', 'd', '\0' };
+# else
+ std::vector<char> vec( 6, 'w' );
+# endif
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ cstring_span sv( vec );
+
+ EXPECT( sv.length() == index_type( 6 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a non-const container, via a tag (std::vector)" )
+{
+# if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ std::vector<char> vec = vector_iota<char>( 9 );
+
+ cstring_span sv( with_container, vec );
+
+ EXPECT( sv.length() == index_type( 9 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a const C-string and size" )
+{
+ const char s[] = "hello";
+
+ cstring_span sv( s, strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a non-const C-string begin and end pointer" )
+{
+ const char s[] = "hello";
+
+ cstring_span sv( s, s + strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a const C-array" )
+{
+ const char s[] = { 'w', 'o', 'r', 'l', 'd', '\0' };
+
+ cstring_span sv( s );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == "world" );
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a const std::string" )
+{
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ const std::string s = "hello, world";
+
+ cstring_span sv( s );
+
+ EXPECT( sv.length() == 12u );
+ EXPECT( std::string( sv.data() ) == s );
+# else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a const std::array (C++11)" )
+{
+# if gsl_HAVE( ARRAY )
+ const std::array<char,6> arr = {{ 'w', 'o', 'r', 'l', 'd', '\0' }};
+
+ cstring_span sv( arr );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), arr.begin() ) );
+# else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a const container (std::vector)" )
+{
+# if gsl_HAVE( INITIALIZER_LIST )
+ const std::vector<char> vec = { 'w', 'o', 'r', 'l', 'd', '\0' };
+# else
+ const std::vector<char> vec( 6, 'w' );
+# endif
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ cstring_span sv( vec );
+
+ EXPECT( sv.length() == index_type( 6 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cstring_span from a const container, via a tag (std::vector)" )
+{
+# if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ const std::vector<char> vec = vector_iota<char>( 9 );
+
+ cstring_span sv( with_container, vec );
+
+ EXPECT( sv.length() == index_type( 9 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+# endif
+}
+
+# if gsl_HAVE( WCHAR )
+
+CASE( "string_span: Allows to construct a wstring_span from a non-const C-string and size" )
+{
+ wchar_t s[] = L"hello";
+
+ wstring_span sv( s, wcslen( s ) );
+
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+CASE( "string_span: Allows to construct a wstring_span from a non-const C-string begin and end pointer" )
+{
+ wchar_t s[] = L"hello";
+
+ wstring_span sv( s, s + wcslen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a wstring_span from a non-const C-array" )
+{
+ wchar_t s[] = { L'w', L'o', L'r', L'l', L'd', L'\0' };
+
+ wstring_span sv( s );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+CASE( "string_span: Allows to construct a wstring_span from a non-const std::wstring" )
+{
+ std::wstring s = L"hello, world";
+
+ wstring_span sv( s );
+
+ EXPECT( sv.length() == 12u );
+ EXPECT( std::wstring( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a wstring_span from a non-const std::array (C++11)" )
+{
+# if gsl_HAVE( ARRAY )
+ std::array<wchar_t,6> arr = {{ 'w', 'o', 'r', 'l', 'd', '\0' }};
+
+ wstring_span sv( arr );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), arr.begin() ) );
+# else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a wstring_span from a non-const container (std::vector)" )
+{
+# if gsl_HAVE( INITIALIZER_LIST )
+ std::vector<wchar_t> vec = { L'w', L'o', L'r', L'l', L'd', L'\0' };
+# else
+ std::vector<wchar_t> vec( 6, 'w' );
+# endif
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ wstring_span sv( vec );
+
+ EXPECT( sv.length() == index_type( 6 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a wstring_span from a non-const container, via a tag (std::vector)" )
+{
+# if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ std::vector<wchar_t> vec = vector_iota<wchar_t>( 9 );
+
+ wstring_span sv( with_container, vec );
+
+ EXPECT( sv.length() == index_type( 9 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a non-const C-string and size" )
+{
+ wchar_t s[] = L"hello";
+
+ cwstring_span sv( s, wcslen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a non-const C-string begin and end pointer" )
+{
+ wchar_t s[] = L"hello";
+
+ cwstring_span sv( s, s + wcslen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a non-const C-array" )
+{
+ wchar_t s[] = { L'w', L'o', L'r', L'l', L'd', L'\0' };
+
+ cwstring_span sv( s );
+
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_COMPILER_MSVC_VERSION
+ EXPECT( sv.length() == index_type( 5 ) );
+# elif gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ EXPECT( !!"Warning: Unconstrained span container constructor enabled: terminating '\0' included in span" );
+ EXPECT( sv.length() == index_type( 6 ) );
+# else
+ EXPECT( sv.length() == index_type( 5 ) );
+# endif
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a non-const std::wstring" )
+{
+ std::wstring s = L"hello, world";
+
+ cwstring_span sv( s );
+
+ EXPECT( sv.length() == 12u );
+ EXPECT( std::wstring( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a non-const std::array (C++11)" )
+{
+# if gsl_HAVE( ARRAY )
+ std::array<wchar_t,6> arr = {{ 'w', 'o', 'r', 'l', 'd', '\0' }};
+
+ cwstring_span sv( arr );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), arr.begin() ) );
+# else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a non-const container (std::vector)" )
+{
+# if gsl_HAVE( INITIALIZER_LIST )
+ std::vector<wchar_t> vec = { L'w', L'o', L'r', L'l', L'd', L'\0' };
+# else
+ std::vector<wchar_t> vec( 6, 'w' );
+# endif
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ cwstring_span sv( vec );
+
+ EXPECT( sv.length() == index_type( 6 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a non-const container, via a tag (std::vector)" )
+{
+# if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ std::vector<wchar_t> vec = vector_iota<wchar_t>( 9 );
+
+ cwstring_span sv( with_container, vec );
+
+ EXPECT( sv.length() == index_type( 9 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a const C-string and size" )
+{
+ const wchar_t s[] = L"hello";
+
+ cwstring_span sv( s, wcslen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a const C-string begin and end pointer" )
+{
+ const wchar_t s[] = L"hello";
+
+ cwstring_span sv( s, s + wcslen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a const C-array" )
+{
+ const wchar_t s[] = { L'w', L'o', L'r', L'l', L'd', L'\0' };
+
+ cwstring_span sv( s );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a const std::wstring" )
+{
+ const std::wstring s = L"hello, world";
+
+ cwstring_span sv( s );
+
+ EXPECT( sv.length() == 12u );
+ EXPECT( std::wstring( sv.data() ) == s );
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a const std::array (C++11)" )
+{
+# if gsl_HAVE( ARRAY )
+ const std::array<wchar_t,6> arr = {{ 'w', 'o', 'r', 'l', 'd', '\0' }};
+
+ cwstring_span sv( arr );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), arr.begin() ) );
+# else
+ EXPECT( !!"std::array<> is not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a const container (std::vector)" )
+{
+# if gsl_HAVE( INITIALIZER_LIST )
+ const std::vector<wchar_t> vec = { L'w', L'o', L'r', L'l', L'd', L'\0' };
+# else
+ const std::vector<wchar_t> vec( 6, 'w' );
+# endif
+# if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+ cwstring_span sv( vec );
+
+ EXPECT( sv.length() == index_type( 6 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"(un)constrained construction from container is not available" );
+# endif
+}
+
+CASE( "string_span: Allows to construct a cwstring_span from a const container, via a tag (std::vector)" )
+{
+# if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+ const std::vector<wchar_t> vec = vector_iota<wchar_t>( 9 );
+
+ cwstring_span sv( with_container, vec );
+
+ EXPECT( sv.length() == index_type( 9 ) );
+ EXPECT( std::equal( sv.begin(), sv.end(), vec.begin() ) );
+# else
+ EXPECT( !!"with_container is not available (gsl_FEATURE_WITH_CONTAINER_TO_STD)" );
+# endif
+}
+
+# endif // gsl_HAVE( WCHAR )
+
+CASE( "string_span: Allows to copy-construct from another span of the same type" )
+{
+ cstring_span a = "hello";
+
+ cstring_span b( a );
+
+ EXPECT( a.length() == b.length() );
+ EXPECT( std::equal( a.begin(), a.end(), b.begin() ) );
+}
+
+CASE( "string_span: Allows to copy-construct from another span of a compatible type" )
+{
+ char hello[] = "hello";
+ string_span a = hello;
+
+ cstring_span b( a );
+
+ EXPECT( a.length() == b.length() );
+ EXPECT( std::equal( a.begin(), a.end(), b.begin() ) );
+}
+
+CASE( "string_span: Allows to move-construct from another span of the same type (C++11)" )
+{
+# if gsl_STDLIB_CPP11_OR_GREATER
+ char hello[] = "hello";
+
+ string_span a(( string_span( hello ) ));
+
+ EXPECT( a.length() == index_type( strlen( hello ) ) );
+ EXPECT( std::equal( a.begin(), a.end(), hello ) );
+# else
+ EXPECT( !!"move-semantics are not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to copy-assign from another span of the same type" )
+{
+ char hello[] = "hello";
+ string_span a = hello;
+ string_span b;
+
+ b = a;
+
+ EXPECT( a.length() == b.length() );
+ EXPECT( std::equal( a.begin(), a.end(), b.begin() ) );
+}
+
+CASE( "string_span: Allows to move-assign from another span of the same type (C++11)" )
+{
+# if gsl_STDLIB_CPP11_OR_GREATER
+ char hello[] = "hello";
+ string_span a;
+
+ a = string_span( hello );
+
+ EXPECT( a.length() == index_type( strlen( hello ) ) );
+ EXPECT( std::equal( a.begin(), a.end(), hello ) );
+# else
+ EXPECT( !!"move-semantics are not available (no C++11)" );
+# endif
+}
+
+CASE( "string_span: Allows to create a sub span of the first n elements" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+ index_type count = 2;
+
+ string_span s = a.first( count );
+
+ EXPECT( s.size() == count );
+ EXPECT( std::equal( s.begin(), s.end(), hello ) );
+}
+
+CASE( "string_span: Allows to create a sub span of the last n elements" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+ index_type count = 2;
+
+ string_span s = a.last( count );
+
+ EXPECT( s.size() == count );
+ EXPECT( std::equal( s.begin(), s.end(), hello + strlen(hello) - count ) );
+}
+
+CASE( "string_span: Allows to create a sub span starting at a given offset" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+ index_type offset = 1;
+
+ string_span s = a.subspan( offset );
+
+ EXPECT( s.size() == index_type( strlen(hello) - offset ) );
+ EXPECT( std::equal( s.begin(), s.end(), hello + offset ) );
+}
+
+CASE( "string_span: Allows to create a sub span starting at a given offset with a given length" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+ index_type offset = 1;
+ index_type length = 1;
+
+ string_span s = a.subspan( offset, length );
+
+ EXPECT( s.size() == length );
+ EXPECT( std::equal( s.begin(), s.end(), hello + offset ) );
+}
+
+CASE( "string_span: Allows to create an empty sub span at full offset" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+ index_type offset = strlen( hello );
+
+ string_span s = a.subspan( offset );
+
+ EXPECT( s.empty() );
+}
+
+CASE( "string_span: Allows to create an empty sub span at full offset with zero length" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+ index_type offset = strlen( hello );
+ index_type length = 0;
+
+ string_span s = a.subspan( offset, length );
+
+ EXPECT( s.empty() );
+}
+
+CASE( "string_span: Allows forward iteration" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ for ( string_span::iterator pos = a.begin(); pos != a.end(); ++pos )
+ {
+ index_type i = narrow_failfast<index_type>( std::distance( a.begin(), pos ) );
+ EXPECT( *pos == a[i] );
+ }
+}
+
+CASE( "string_span: Allows const forward iteration" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ for ( string_span::const_iterator pos = a.begin(); pos != a.end(); ++pos )
+ {
+ index_type i = narrow_failfast<index_type>( std::distance( a.cbegin(), pos ) );
+ EXPECT( *pos == a[i] );
+ }
+}
+
+CASE( "string_span: Allows reverse iteration" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ for ( string_span::reverse_iterator pos = a.rbegin(); pos != a.rend(); ++pos )
+ {
+ index_type dist = narrow_failfast<index_type>( std::distance( a.rbegin(), pos ) );
+ EXPECT( *pos == a[ a.size() - 1 - dist ] );
+ }
+}
+
+CASE( "string_span: Allows const reverse iteration" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ for ( string_span::const_reverse_iterator pos = a.crbegin(); pos != a.crend(); ++pos )
+ {
+ index_type dist = narrow_failfast<index_type>( std::distance( a.crbegin(), pos ) );
+ EXPECT( *pos == a[ a.size() - 1 - dist ] );
+ }
+}
+
+CASE( "string_span: Allows to observe an element via array indexing" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ for ( index_type i = 0; i < a.size(); ++i )
+ {
+ EXPECT( a[i] == hello[i] );
+ EXPECT( &a[i] == &hello[i] );
+ }
+}
+
+CASE( "string_span: Allows to observe an element via front() and back()" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ EXPECT( a.front() == hello[0] );
+ EXPECT( &a.front() == &hello[0] );
+ EXPECT( a.back() == hello[4] );
+ EXPECT( &a.back() == &hello[4] );
+}
+
+CASE( "string_span: Allows to observe an element via data()" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ EXPECT( *a.data() == *a.begin() );
+ EXPECT( a.data() == &*a.begin() );
+
+ for ( index_type i = 0; i < a.size(); ++i )
+ {
+ EXPECT( a.data()[i] == hello[i] );
+ EXPECT( a.data()[i] == hello[i] );
+ }
+}
+
+CASE( "string_span: Allows to change an element via array indexing" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ a[1] = '7';
+
+ EXPECT( hello[1] == '7' );
+}
+
+CASE( "string_span: Allows to change an element via front() and back()" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ a.front() = '1';
+ a.back() = '2';
+
+ EXPECT( hello[0] == '1' );
+ EXPECT( hello[4] == '2' );
+}
+
+# if 0
+CASE( "string_span: Allows to change an element via at()" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ a.at(1) = '7';
+
+ EXPECT( hello[1] == '7' );
+}
+# endif
+
+CASE( "string_span: Allows to change an element via data()" )
+{
+ char hello[] = "hello";
+ string_span a( hello );
+
+ *a.data() = '7';
+
+ EXPECT( hello[0] == '7' );
+}
+
+CASE( "string_span: Allows to compare a string_span with another string_span" )
+{
+ char s[] = "hello";
+ char t[] = "world";
+
+ string_span sv( s, strlen( s ) );
+ string_span tv( t, strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( tv.length() == index_type( 5 ) );
+
+ EXPECT( sv == sv );
+ EXPECT( sv != tv );
+ EXPECT( sv <= sv );
+ EXPECT( sv <= tv );
+ EXPECT( sv < tv );
+ EXPECT( tv >= tv );
+ EXPECT( tv >= sv );
+ EXPECT( tv > sv );
+}
+
+CASE( "string_span: Allows to compare empty spans as equal (questionable)" "[.]" )
+{
+ string_span a, b;
+
+ EXPECT( a == b );
+}
+
+CASE( "string_span: Allows to compare empty span to non-empty span" )
+{
+ char s[] = "hello";
+ string_span a, b( s, strlen( s ) );
+
+ EXPECT( a != b );
+ EXPECT( b != a );
+}
+
+CASE( "string_span: Allows to compare a string_span with a cstring_span" )
+{
+# if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+ char s[] = "hello";
+
+ string_span sv( s, strlen( s ) );
+ cstring_span csv( s, strlen( s ) );
+
+ EXPECT( sv == csv );
+# else
+ EXPECT( !!"string_span: cannot compare different types (gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=0)" );
+# endif
+}
+
+CASE( "string_span: Allows to compare with types convertible to string_span" )
+{
+# if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+ char const * phello = "hello";
+ char const ahello[] = "hello";
+ std::string shello = "hello";
+ cstring_span a = phello;
+
+ EXPECT( a == phello );
+ EXPECT( a == ahello );
+ EXPECT( a == shello );
+ EXPECT( a <= phello );
+ EXPECT( a <= ahello );
+ EXPECT( a <= shello );
+ EXPECT( a >= phello );
+ EXPECT( a >= ahello );
+ EXPECT( a >= shello );
+
+ EXPECT_NOT( a != phello );
+ EXPECT_NOT( a != ahello );
+ EXPECT_NOT( a != shello );
+ EXPECT_NOT( a < phello );
+ EXPECT_NOT( a < ahello );
+ EXPECT_NOT( a < shello );
+ EXPECT_NOT( a > phello );
+ EXPECT_NOT( a > ahello );
+ EXPECT_NOT( a > shello );
+
+# if gsl_HAVE( OWNER_TEMPLATE )
+ EXPECT( phello == a );
+ EXPECT( ahello == a );
+ EXPECT( shello == a );
+ EXPECT( phello <= a );
+ EXPECT( ahello <= a );
+ EXPECT( shello <= a );
+ EXPECT( phello >= a );
+ EXPECT( ahello >= a );
+ EXPECT( shello >= a );
+
+ EXPECT_NOT( phello != a );
+ EXPECT_NOT( ahello != a );
+ EXPECT_NOT( shello != a );
+ EXPECT_NOT( phello < a );
+ EXPECT_NOT( ahello < a );
+ EXPECT_NOT( shello < a );
+ EXPECT_NOT( phello > a );
+ EXPECT_NOT( ahello > a );
+ EXPECT_NOT( shello > a );
+# endif
+
+# if gsl_HAVE( ARRAY )
+ std::array<char,6> world = {{ 'w', 'o', 'r', 'l', 'd', '\0' }};
+ cstring_span b = world;
+
+ EXPECT( b == world );
+# if gsl_HAVE( OWNER_TEMPLATE )
+ EXPECT( world == b );
+# endif
+# endif
+# else
+ EXPECT( !!"string_span: cannot compare different types (gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=0)" );
+# endif
+}
+
+CASE( "string_span: Allows to test for empty span via empty(), empty case" )
+{
+ string_span sz;
+
+ EXPECT( sz.empty() );
+}
+
+CASE( "string_span: Allows to test for empty span via empty(), non-empty case" )
+{
+ cstring_span s = "hello";
+
+ EXPECT_NOT( s.empty() );
+}
+
+CASE( "string_span: Allows to obtain the number of elements via length()" )
+{
+ char a[] = "hello";
+ char b[] = "world";
+ string_span sz;
+ string_span sa = a;
+ string_span sb = b;
+
+ EXPECT( sz.length() == index_type( 0 ) );
+ EXPECT( sa.length() == index_type( strlen( a ) ) );
+ EXPECT( sb.length() == index_type( strlen( b ) ) );
+}
+
+CASE( "string_span: Allows to obtain the number of elements via size()" )
+{
+ char a[] = "hello";
+ char b[] = "world";
+ string_span sz;
+ string_span sa = a;
+ string_span sb = b;
+
+ EXPECT( sz.size() == index_type( 0 ) );
+ EXPECT( sa.size() == index_type( strlen( a ) ) );
+ EXPECT( sb.size() == index_type( strlen( b ) ) );
+}
+
+# if gsl_HAVE( WCHAR )
+
+CASE( "string_span: Allows to obtain the number of bytes via length_bytes()" )
+{
+ wchar_t a[] = L"hello";
+ wchar_t b[] = L"world";
+ wstring_span sz;
+ wstring_span sa = a;
+ wstring_span sb = b;
+
+ EXPECT( sz.length_bytes() == index_type( 0 ) );
+ EXPECT( sa.length_bytes() == index_type( sizeof(wchar_t) * wcslen( a ) ) );
+ EXPECT( sb.length_bytes() == index_type( sizeof(wchar_t) * wcslen( b ) ) );
+}
+
+CASE( "string_span: Allows to obtain the number of bytes via size_bytes()" )
+{
+ wchar_t a[] = L"hello";
+ wchar_t b[] = L"world";
+ wstring_span sz;
+ wstring_span sa = a;
+ wstring_span sb = b;
+
+ EXPECT( sz.size_bytes() == index_type( 0 ) );
+ EXPECT( sa.size_bytes() == index_type( sizeof(wchar_t) * wcslen( a ) ) );
+ EXPECT( sb.size_bytes() == index_type( sizeof(wchar_t) * wcslen( b ) ) );
+}
+
+# endif // gsl_HAVE( WCHAR )
+
+CASE( "string_span: Allows to view the elements as read-only bytes" )
+{
+ char const * hello = "hello";
+ cstring_span s( hello);
+
+ span<const gsl_lite::byte> b = as_bytes( s );
+
+ EXPECT( b[0] == to_byte( hello[0] ) );
+ EXPECT( b[1] == to_byte( hello[1] ) );
+ EXPECT( b[2] == to_byte( hello[2] ) );
+ EXPECT( b[3] == to_byte( hello[3] ) );
+ EXPECT( b[4] == to_byte( hello[4] ) );
+}
+
+//------------------------------------------------------------------------
+// zstring_span
+
+CASE( "zstring_span: Terminates construction of a zstring_span from an empty span" )
+{
+ span<char> s;
+ EXPECT_THROWS( (void) zstring_span( s ) );
+}
+
+CASE( "zstring_span: Allows to construct a zstring_span from a zero-terminated empty string (via span)" )
+{
+ char zero[] = "";
+
+ zstring_span zsv( make_span( zero, 1 ) );
+
+ EXPECT_NOT( zsv.empty() );
+ EXPECT( zsv.ensure_z().size() == 0u );
+ EXPECT( zsv.as_string_span().size() == 0u );
+ EXPECT( std::string( zsv.as_string_span().data() ) == "" );
+}
+
+CASE( "zstring_span: Allows to construct a zstring_span from a zero-terminated non-empty string (via span)" )
+{
+ char hello[] = "hello, world";
+ const index_type len = std::string(hello).length();
+
+ zstring_span zsv( make_span( hello, len + 1 ) );
+
+ EXPECT_NOT( zsv.empty() );
+ EXPECT( zsv.ensure_z().size() == len );
+ EXPECT( zsv.as_string_span().size() == len );
+ EXPECT( std::string( zsv.as_string_span().data() ) == hello );
+}
+
+CASE( "zstring_span: Terminates construction of a zstring_span from a non-zero-terminated string (via span)" )
+{
+ struct F
+ {
+ static void blow()
+ {
+ char hello[] = "hello, worldxxx";
+ const index_type len = std::string(hello).length();
+
+ zstring_span zsv( make_span( hello, len ) );
+ }
+ };
+
+ EXPECT_THROWS( F::blow() );
+}
+
+# if gsl_HAVE( WCHAR )
+
+CASE( "zstring_span: Terminates construction of a wzstring_span from an empty span" )
+{
+ span<wchar_t> s;
+ EXPECT_THROWS( (void) wzstring_span( s ) );
+}
+
+CASE( "zstring_span: Allows to construct a wzstring_span from a zero-terminated empty string (via span)" )
+{
+ wchar_t zero[] = L"";
+
+ wzstring_span wzsv( make_span( zero, 1 ) );
+
+ EXPECT_NOT( wzsv.empty() );
+ EXPECT( wzsv.ensure_z().size() == 0u );
+ EXPECT( wzsv.as_string_span().size() == 0u );
+ EXPECT( std::wstring( wzsv.as_string_span().data() ) == L"" );
+}
+
+CASE( "zstring_span: Allows to construct a wzstring_span from a zero-terminated non-empty string (via span)" )
+{
+ wchar_t hello[] = L"hello, world";
+ const index_type len = std::wstring(hello).length();
+
+ wzstring_span wzsv( make_span( hello, len + 1 ) );
+
+ EXPECT_NOT( wzsv.empty() );
+ EXPECT( wzsv.ensure_z().size() == len );
+ EXPECT( wzsv.as_string_span().size() == len );
+// EXPECT( std::wstring( wzsv.as_string_span().data() ) == hello );
+}
+
+CASE( "zstring_span: Terminates construction of a wzstring_span from a non-zero-terminated string (via span)" )
+{
+ struct F
+ {
+ static void blow()
+ {
+ wchar_t hello[] = L"hello, worldxxx";
+ const index_type len = std::wstring(hello).length();
+
+ wzstring_span wzsv( make_span( hello, len ) );
+ }
+ };
+
+ EXPECT_THROWS( F::blow() );
+}
+
+# endif // gsl_HAVE( WCHAR )
+
+CASE( "zstring_span: Allows to use a zstring_span with a legacy API via member assume_z()" )
+{
+ char hello[] = "hello, world";
+ const std::string::size_type len = std::string(hello).length();
+
+ zstring_span zsv( make_span( hello, len + 1 ) );
+ czstring czs( zsv.assume_z() );
+
+ EXPECT( strlen( czs ) == len );
+ EXPECT( *(czs + len ) == '\0');
+}
+
+# if gsl_HAVE( WCHAR )
+
+CASE( "zstring_span: Allows to use a wzstring_span with a legacy API via member assume_z()" )
+{
+ wchar_t hello[] = L"hello, world";
+ const index_type len = std::wstring(hello).length();
+
+ wzstring_span wzsv( make_span( hello, len + 1 ) );
+ cwzstring cwzs( wzsv.assume_z() );
+
+ EXPECT( wcslen( cwzs ) == len );
+ EXPECT( *(cwzs + len ) == '\0');
+}
+
+# endif // gsl_HAVE( WCHAR )
+
+//------------------------------------------------------------------------
+// global functions:
+
+CASE( "to_string(): Allows to explicitly convert from string_span to std::string" )
+{
+ char s[] = "hello";
+
+ string_span sv( s, strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( to_string( sv ) == s );
+}
+
+CASE( "to_string(): Allows to explicitly convert from cstring_span to std::string" )
+{
+ const char s[] = "hello";
+
+ cstring_span sv( s, strlen( s ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( to_string( sv ) == s );
+}
+
+# if gsl_HAVE( WCHAR )
+
+CASE( "to_string(): Allows to explicitly convert from wstring_span to std::wstring" )
+{
+ wchar_t s[] = L"hello";
+
+ wstring_span sv( s, wcslen( s ) );
+
+ std::wstring ws( to_string( wstring_span( s, wcslen( s ) ) ) );
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::equal( ws.begin(), ws.end(), s ) );
+}
+
+CASE( "to_string(): Allows to explicitly convert from cwstring_span to std::wstring" )
+{
+ wchar_t s[] = L"hello";
+
+ std::wstring ws( to_string( cwstring_span( s, wcslen( s ) ) ) );
+
+ EXPECT( ws.length() == 5u );
+ EXPECT( std::equal( ws.begin(), ws.end(), s ) );
+}
+
+# endif // gsl_HAVE( WCHAR )
+
+CASE( "ensure_z(): Disallows to build a string_span from a const C-string" )
+{
+# if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+ const char s[] = "hello";
+
+ string_span sv = ensure_z( s );
+
+ EXPECT( sv.length() == 5u );
+ EXPECT( std::string( sv.data() ) == s );
+# endif
+}
+
+# if gsl_HAVE( WCHAR )
+CASE( "ensure_z(): Disallows to build a wstring_span from a const wide C-string" )
+{
+# if gsl_CONFIG( CONFIRMS_COMPILATION_ERRORS )
+ const wchar_t s[] = L"hello";
+
+ wstring_span sv = ensure_z( s );
+
+ EXPECT( sv.length() == 5 );
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+# endif
+}
+# endif // gsl_HAVE( WCHAR )
+
+CASE( "ensure_z(): Allows to build a string_span from a non-const C-string" )
+{
+ char s[] = "hello";
+
+# if gsl_COMPILER_MSVC_VERSION != 60
+ string_span sv = ensure_z( s );
+# else
+ string_span sv = ensure_z( &s[0] );
+# endif
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "ensure_z(): Allows to build a cstring_span from a non-const C-string" )
+{
+ char s[] = "hello";
+
+# if gsl_COMPILER_MSVC_VERSION != 60
+ cstring_span sv = ensure_z( s );
+# else
+ cstring_span sv = ensure_z( &s[0] );
+# endif
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+CASE( "ensure_z(): Allows to build a cstring_span from a const C-string" )
+{
+ const char s[] = "hello";
+
+# if gsl_COMPILER_MSVC_VERSION != 60
+ cstring_span sv = ensure_z( s );
+# else
+ cstring_span sv = ensure_z( &s[0] );
+# endif
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::string( sv.data() ) == s );
+}
+
+# if gsl_HAVE( WCHAR )
+
+CASE( "ensure_z(): Allows to build a wstring_span from a non-const wide C-string" )
+{
+ wchar_t s[] = L"hello";
+
+# if gsl_COMPILER_MSVC_VERSION != 60
+ wstring_span sv = ensure_z( s );
+# else
+ wstring_span sv = ensure_z( &s[0] );
+# endif
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+CASE( "ensure_z(): Allows to build a cwstring_span from a non-const wide C-string" )
+{
+ wchar_t s[] = L"hello";
+
+# if gsl_COMPILER_MSVC_VERSION != 60
+ cwstring_span sv = ensure_z( s );
+# else
+ cwstring_span sv = ensure_z( &s[0] );
+# endif
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+CASE( "ensure_z(): Allows to build a cwstring_span from a const wide C-string" )
+{
+ const wchar_t s[] = L"hello";
+
+# if gsl_COMPILER_MSVC_VERSION != 60
+ cwstring_span sv = ensure_z( s );
+# else
+ cwstring_span sv = ensure_z( &s[0] );
+# endif
+
+ EXPECT( sv.length() == index_type( 5 ) );
+ EXPECT( std::wstring( sv.data() ) == std::wstring( s ) );
+}
+
+# endif // gsl_HAVE( WCHAR )
+
+CASE( "ensure_z(): Allows to specify ultimate location of the sentinel and ensure its presence" )
+{
+ const char * s = "hello"; // not: s[]
+
+ EXPECT_THROWS( (void) ensure_z( s, index_type( 3 ) ) );
+}
+
+CASE ( "operator<<: Allows printing a string_span to an output stream" )
+{
+ std::ostringstream oss;
+ char s[] = "hello";
+ string_span sv = ensure_z( s );
+
+ oss << sv << '\n'
+ << std::right << std::setw(10) << sv << '\n'
+ << sv << '\n'
+ << std::setfill('.') << std::left << std::setw(10) << sv;
+
+ EXPECT( oss.str() == "hello\n hello\nhello\nhello....." );
+}
+
+CASE ( "operator<<: Allows printing a cstring_span to an output stream" )
+{
+ std::ostringstream oss;
+ char s[] = "hello";
+ cstring_span sv = ensure_z( s );
+
+ oss << sv << '\n'
+ << std::right << std::setw(10) << sv << '\n'
+ << sv << '\n'
+ << std::setfill('.') << std::left << std::setw(10) << sv;
+
+ EXPECT( oss.str() == "hello\n hello\nhello\nhello....." );
+}
+
+# if gsl_HAVE( WCHAR )
+
+CASE ( "operator<<: Allows printing a wstring_span to an output stream" )
+{
+ std::wostringstream oss;
+ wchar_t s[] = L"hello";
+ wstring_span sv = ensure_z( s );
+
+ oss << sv << '\n'
+ << std::right << std::setw(10) << sv << '\n'
+ << sv << '\n'
+ << std::setfill(L'.') << std::left << std::setw(10) << sv;
+
+ EXPECT( oss.str() == L"hello\n hello\nhello\nhello....." );
+}
+
+CASE ( "operator<<: Allows printing a cwstring_span to an output stream" )
+{
+ std::wostringstream oss;
+ wchar_t s[] = L"hello";
+ cwstring_span sv = ensure_z( s );
+
+ oss << sv << '\n'
+ << std::right << std::setw(10) << sv << '\n'
+ << sv << '\n'
+ << std::setfill(L'.') << std::left << std::setw(10) << sv;
+
+ EXPECT( oss.str() == L"hello\n hello\nhello\nhello....." );
+}
+
+# endif // gsl_HAVE( WCHAR )
+
+# if ! gsl_HAVE( WCHAR )
+
+CASE( "string_span: wstring_span and cwstring_span not available (wchar_t not available)" )
+{
+ EXPECT( true );
+}
+# endif // gsl_HAVE( WCHAR )
+#endif // gsl_FEATURE( STRING_SPAN )
+
+// end of file
diff --git a/thirdparty/gsl-lite/test/util.t.cpp b/thirdparty/gsl-lite/test/util.t.cpp
new file mode 100644
index 000000000..0c99efd32
--- /dev/null
+++ b/thirdparty/gsl-lite/test/util.t.cpp
@@ -0,0 +1,337 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "gsl-lite.t.hpp"
+#include <cstddef>
+#include <complex>
+#include <functional>
+
+#if gsl_STDLIB_CPP11_OR_GREATER
+# include <limits>
+# include <cstdint>
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+
+#define gsl_STDLIB_CPP11_OR_GREATER_WRT_FINAL ( gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 110 )
+
+using namespace gsl_lite;
+
+CASE( "finally: Allows to run lambda on leaving scope" )
+{
+#if gsl_STDLIB_CPP11_OR_GREATER_WRT_FINAL
+ struct F { static void incr( int & i ) { i += 1; } };
+
+ int i = 0;
+ {
+ auto _ = finally( [&]() { F::incr( i ); } );
+ EXPECT( i == 0 );
+ }
+ EXPECT( i == 1 );
+#else
+ EXPECT( !!"lambda is not available (no C++11)" );
+#endif
+}
+
+CASE( "finally: Allows to run function (bind) on leaving scope" )
+{
+#if gsl_STDLIB_CPP11_OR_GREATER_WRT_FINAL
+ struct F { static void incr( int & i ) { i += 1; } };
+
+ int i = 0;
+ {
+ auto _ = finally( std::bind( &F::incr, std::ref( i ) ) );
+ EXPECT( i == 0 );
+ }
+ EXPECT( i == 1 );
+#else
+ EXPECT( !!"auto and std::ref perhaps not available (no C++11)" );
+#endif
+}
+
+namespace{ int g_i = 0; }
+
+CASE( "finally: Allows to run function (pointer) on leaving scope" )
+{
+ struct F { static void incr() { g_i += 1; } };
+
+#if gsl_STDLIB_CPP11_OR_GREATER_WRT_FINAL
+
+ g_i = 0;
+ {
+ auto _ = finally( &F::incr );
+ EXPECT( g_i == 0 );
+ }
+ EXPECT( g_i == 1 );
+#endif
+}
+
+CASE( "on_return: Allows to perform action on leaving scope without exception (gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD)" )
+{
+#if gsl_HAVE( EXCEPTIONS )
+# if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+# if gsl_STDLIB_CPP11_OR_GREATER_WRT_FINAL
+ struct F {
+ static void incr() { g_i += 1; }
+ static void pass() { try { auto _ = on_return( &F::incr ); /*throw std::exception();*/ } catch (...) {} }
+ static void fail() { try { auto _ = on_return( &F::incr ); throw std::exception(); } catch (...) {} }
+ };
+ struct G {
+ ~G() { F::pass(); }
+ };
+ { g_i = 0; F::pass(); EXPECT( g_i == 1 ); }
+ { g_i = 0; F::fail(); EXPECT( g_i == 0 ); }
+ { g_i = 0; try { G g; throw std::exception(); } catch (...) {}; EXPECT( g_i == 1 ); }
+# endif
+# else
+ EXPECT( !!"on_return not available (no gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD)" );
+# endif
+#endif // gsl_HAVE( EXCEPTIONS )
+}
+
+CASE( "on_error: Allows to perform action on leaving scope via an exception (gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD)" )
+{
+#if gsl_HAVE( EXCEPTIONS )
+# if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+# if gsl_STDLIB_CPP11_OR_GREATER_WRT_FINAL
+ struct F {
+ static void incr() { g_i += 1; }
+ static void pass() { try { auto _ = on_error( &F::incr ); /*throw std::exception();*/ } catch (...) {} }
+ static void fail() { try { auto _ = on_error( &F::incr ); throw std::exception(); } catch (...) {} }
+ };
+ struct G {
+ ~G() { F::pass(); }
+ };
+ { g_i = 0; F::pass(); EXPECT( g_i == 0 ); }
+ { g_i = 0; F::fail(); EXPECT( g_i == 1 ); }
+ { g_i = 0; try { G g; throw std::exception(); } catch (...) {}; EXPECT( g_i == 0 ); }
+# endif
+# else
+ EXPECT( !!"on_error not available (no gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD)" );
+# endif
+#endif // gsl_HAVE( EXCEPTIONS )
+}
+
+CASE( "narrow_cast<>: Allows narrowing without value loss" )
+{
+ EXPECT( narrow_cast<char>( 120 ) == 120 );
+}
+
+CASE( "narrow_cast<>: Allows narrowing with value loss" )
+{
+ EXPECT( narrow_cast<unsigned char>( 300 ) == 44 );
+}
+
+#if gsl_STDLIB_CPP11_OR_GREATER
+const std::uint8_t u8 = std::uint8_t((std::numeric_limits< std::uint8_t>::max)() - 1);
+const std::uint16_t u16 = std::uint16_t((std::numeric_limits<std::uint16_t>::max)() - 1);
+const std::int8_t i8n = std::int8_t((std::numeric_limits< std::int8_t>::min)() + 1);
+const std::int16_t i16n = std::int16_t((std::numeric_limits< std::int16_t>::min)() + 1);
+const std::int8_t i8p = std::int8_t((std::numeric_limits< std::int8_t>::max)() - 1);
+const std::int16_t i16p = std::int16_t((std::numeric_limits< std::int16_t>::max)() - 1);
+#endif // gsl_CPP11_OR_GREATER
+
+CASE( "narrow<>(): Allows narrowing without value loss" )
+{
+#if gsl_HAVE( EXCEPTIONS )
+ EXPECT( narrow<char>( 120 ) == 120 );
+
+# if gsl_STDLIB_CPP11_OR_GREATER
+ std::uint8_t lu8;
+ std::uint16_t lu16;
+ std::int8_t li8;
+ std::int16_t li16;
+
+ // uint <-> uint
+ EXPECT_NO_THROW((lu16 = narrow<std::uint16_t>( std::uint8_t( u8)))); EXPECT(lu16 == u8);
+ EXPECT_NO_THROW(( lu8 = narrow< std::uint8_t>( std::uint8_t( u8)))); EXPECT( lu8 == u8);
+ EXPECT_NO_THROW(( lu8 = narrow< std::uint8_t>(std::uint16_t( u8)))); EXPECT( lu8 == u8);
+
+ // int <-> int
+ EXPECT_NO_THROW((li16 = narrow< std::int16_t>( std::int8_t(i8n)))); EXPECT(li16 == i8n);
+ EXPECT_NO_THROW((li16 = narrow< std::int16_t>( std::int8_t(i8p)))); EXPECT(li16 == i8p);
+ EXPECT_NO_THROW(( li8 = narrow< std::int8_t>( std::int8_t(i8n)))); EXPECT( li8 == i8n);
+ EXPECT_NO_THROW(( li8 = narrow< std::int8_t>( std::int8_t(i8p)))); EXPECT( li8 == i8p);
+ EXPECT_NO_THROW(( li8 = narrow< std::int8_t>( std::int16_t(i8n)))); EXPECT( li8 == i8n);
+ EXPECT_NO_THROW(( li8 = narrow< std::int8_t>( std::int16_t(i8p)))); EXPECT( li8 == i8p);
+
+ // uint <-> int
+ EXPECT_NO_THROW((lu16 = narrow<std::uint16_t>( std::int8_t(i8p)))); EXPECT(lu16 == i8p);
+ EXPECT_NO_THROW((li16 = narrow< std::int16_t>( std::uint8_t(i8p)))); EXPECT(li16 == i8p);
+ EXPECT_NO_THROW(( lu8 = narrow< std::uint8_t>( std::int8_t(i8p)))); EXPECT( lu8 == i8p);
+ EXPECT_NO_THROW(( li8 = narrow< std::int8_t>( std::uint8_t(i8p)))); EXPECT( li8 == i8p);
+ EXPECT_NO_THROW(( lu8 = narrow< std::uint8_t>( std::int16_t(i8p)))); EXPECT( lu8 == i8p);
+ EXPECT_NO_THROW(( li8 = narrow< std::int8_t>(std::uint16_t(i8p)))); EXPECT( li8 == i8p);
+# endif // gsl_STDLIB_CPP11_OR_GREATER
+#endif // gsl_HAVE( EXCEPTIONS )
+}
+
+CASE( "narrow<>(): Allows narrowing unordered type without precision loss" )
+{
+#if gsl_HAVE( EXCEPTIONS ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+ std::complex<float> cf;
+ EXPECT_NO_THROW( cf = narrow<std::complex<float>>( std::complex<double>( 4, 2 ) ) );
+ EXPECT( narrow<std::complex<float>>( std::complex<double>( 4, 2 ) ) == std::complex<float>( 4, 2 ) );
+#endif // gsl_HAVE( EXCEPTIONS ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+}
+
+CASE( "narrow<>(): Throws when narrowing with value loss" )
+{
+#if gsl_HAVE( EXCEPTIONS ) && gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ EXPECT_THROWS_AS( (void) narrow<char>( 300 ), narrowing_error );
+
+# if gsl_STDLIB_CPP11_OR_GREATER
+ // uint <-> uint
+ EXPECT_THROWS_AS( (void) narrow< std::uint8_t>( std::uint16_t( u16) ), narrowing_error );
+
+ // int <-> int
+ EXPECT_THROWS_AS( (void) narrow< std::int8_t>( std::int16_t(i16n) ), narrowing_error );
+ EXPECT_THROWS_AS( (void) narrow< std::int8_t>( std::int16_t(i16p) ), narrowing_error );
+
+ // uint <-> int
+ EXPECT_THROWS_AS( (void) narrow< std::int8_t>( std::uint8_t( u8 ) ), narrowing_error );
+ EXPECT_THROWS_AS( (void) narrow< std::uint8_t>( std::int16_t(i16p) ), narrowing_error );
+ EXPECT_THROWS_AS( (void) narrow< std::int8_t>( std::uint16_t( u8 ) ), narrowing_error );
+ EXPECT_THROWS_AS( (void) narrow< std::int8_t>( std::uint16_t(u16 ) ), narrowing_error );
+# endif // gsl_STDLIB_CPP11_OR_GREATER
+#endif // gsl_HAVE( EXCEPTIONS ) && gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+}
+
+CASE( "narrow<>(): Throws when narrowing with sign loss" )
+{
+#if gsl_HAVE( EXCEPTIONS ) && gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ EXPECT_THROWS_AS( (void) narrow<unsigned>( -42 ), narrowing_error );
+
+# if gsl_STDLIB_CPP11_OR_GREATER
+ // uint <-> int
+ EXPECT_THROWS_AS( (void) narrow<std::uint16_t>( std::int8_t( i8n) ), narrowing_error );
+ EXPECT_THROWS_AS( (void) narrow< std::uint8_t>( std::int8_t( i8n) ), narrowing_error );
+ EXPECT_THROWS_AS( (void) narrow< std::uint8_t>( std::int16_t( i8n) ), narrowing_error );
+ EXPECT_THROWS_AS( (void) narrow< std::uint8_t>( std::int16_t(i16n) ), narrowing_error );
+# endif // gsl_STDLIB_CPP11_OR_GREATER
+#endif // gsl_HAVE( EXCEPTIONS ) && gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+}
+
+CASE( "narrow<>(): Throws when narrowing unordered type with precision loss" )
+{
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXCEPTIONS ) && gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+ EXPECT_THROWS_AS( (void) narrow<std::complex<float>>( std::complex<double>( 4.2 ) ), narrowing_error );
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXCEPTIONS ) && gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION )
+}
+
+CASE( "narrow_failfast<>(): Allows narrowing without value loss" )
+{
+ EXPECT( narrow_failfast<char>( 120 ) == 120 );
+
+#if gsl_STDLIB_CPP11_OR_GREATER
+ std::uint8_t lu8;
+ std::uint16_t lu16;
+ std::int8_t li8;
+ std::int16_t li16;
+
+ // uint <-> uint
+ EXPECT_NO_THROW((lu16 = narrow_failfast<std::uint16_t>( std::uint8_t( u8)))); EXPECT(lu16 == u8);
+ EXPECT_NO_THROW(( lu8 = narrow_failfast< std::uint8_t>( std::uint8_t( u8)))); EXPECT( lu8 == u8);
+ EXPECT_NO_THROW(( lu8 = narrow_failfast< std::uint8_t>(std::uint16_t( u8)))); EXPECT( lu8 == u8);
+
+ // int <-> int
+ EXPECT_NO_THROW((li16 = narrow_failfast< std::int16_t>( std::int8_t(i8n)))); EXPECT(li16 == i8n);
+ EXPECT_NO_THROW((li16 = narrow_failfast< std::int16_t>( std::int8_t(i8p)))); EXPECT(li16 == i8p);
+ EXPECT_NO_THROW(( li8 = narrow_failfast< std::int8_t>( std::int8_t(i8n)))); EXPECT( li8 == i8n);
+ EXPECT_NO_THROW(( li8 = narrow_failfast< std::int8_t>( std::int8_t(i8p)))); EXPECT( li8 == i8p);
+ EXPECT_NO_THROW(( li8 = narrow_failfast< std::int8_t>( std::int16_t(i8n)))); EXPECT( li8 == i8n);
+ EXPECT_NO_THROW(( li8 = narrow_failfast< std::int8_t>( std::int16_t(i8p)))); EXPECT( li8 == i8p);
+
+ // uint <-> int
+ EXPECT_NO_THROW((lu16 = narrow_failfast<std::uint16_t>( std::int8_t(i8p)))); EXPECT(lu16 == i8p);
+ EXPECT_NO_THROW((li16 = narrow_failfast< std::int16_t>( std::uint8_t(i8p)))); EXPECT(li16 == i8p);
+ EXPECT_NO_THROW(( lu8 = narrow_failfast< std::uint8_t>( std::int8_t(i8p)))); EXPECT( lu8 == i8p);
+ EXPECT_NO_THROW(( li8 = narrow_failfast< std::int8_t>( std::uint8_t(i8p)))); EXPECT( li8 == i8p);
+ EXPECT_NO_THROW(( lu8 = narrow_failfast< std::uint8_t>( std::int16_t(i8p)))); EXPECT( lu8 == i8p);
+ EXPECT_NO_THROW(( li8 = narrow_failfast< std::int8_t>(std::uint16_t(i8p)))); EXPECT( li8 == i8p);
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+}
+
+CASE( "narrow_failfast<>(): Allows narrowing unordered type without precision loss" )
+{
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+ std::complex<float> cf;
+ EXPECT_NO_THROW( cf = narrow_failfast<std::complex<float>>( std::complex<double>( 4, 2 ) ) );
+ EXPECT( narrow_failfast<std::complex<float>>( std::complex<double>( 4, 2 ) ) == std::complex<float>( 4, 2 ) );
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+}
+
+CASE( "narrow_failfast<>(): Fails when narrowing with value loss" )
+{
+ EXPECT_THROWS_AS( (void) narrow_failfast<char>( 300 ), fail_fast );
+
+#if gsl_STDLIB_CPP11_OR_GREATER
+ // uint <-> uint
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::uint8_t>( std::uint16_t( u16) ), fail_fast );
+
+ // int <-> int
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::int8_t>( std::int16_t(i16n) ), fail_fast );
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::int8_t>( std::int16_t(i16p) ), fail_fast );
+
+ // uint <-> int
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::int8_t>( std::uint8_t( u8 ) ), fail_fast );
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::uint8_t>( std::int16_t(i16p) ), fail_fast );
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::int8_t>( std::uint16_t( u8 ) ), fail_fast );
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::int8_t>( std::uint16_t(u16 ) ), fail_fast );
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+}
+
+CASE( "narrow_failfast<>(): Fails when narrowing with sign loss" )
+{
+ EXPECT_THROWS_AS( (void) narrow_failfast<unsigned>( -42 ), fail_fast );
+
+#if gsl_STDLIB_CPP11_OR_GREATER
+ // uint <-> int
+ EXPECT_THROWS_AS( (void) narrow_failfast<std::uint16_t>( std::int8_t( i8n) ), fail_fast );
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::uint8_t>( std::int8_t( i8n) ), fail_fast );
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::uint8_t>( std::int16_t( i8n) ), fail_fast );
+ EXPECT_THROWS_AS( (void) narrow_failfast< std::uint8_t>( std::int16_t(i16n) ), fail_fast );
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+}
+
+CASE( "narrow_failfast<>(): Fails when narrowing unordered type with precision loss" )
+{
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+ EXPECT_THROWS_AS( (void) narrow_failfast<std::complex<float>>( std::complex<double>( 4.2 ) ), fail_fast );
+#endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+}
+
+#if gsl_CPP20_OR_GREATER && ( ! defined( _MSC_VER ) || gsl_COMPILER_MSVC_VERSION >= 1929 || gsl_COMPILER_CLANG_VERSION >= 1800 )
+struct Empty { };
+struct NoEmptyMember
+{
+ int nonEmpty;
+};
+struct OneEmptyMember
+{
+ gsl_NO_UNIQUE_ADDRESS Empty empty;
+ int nonEmpty;
+};
+
+CASE( "gsl_NO_UNIQUE_ADDRESS: Class layout is compressed if attribute is used on empty members" )
+{
+ EXPECT( sizeof( NoEmptyMember ) == sizeof( int ) );
+ EXPECT( sizeof( OneEmptyMember ) == sizeof( NoEmptyMember ) );
+ EXPECT( offsetof( OneEmptyMember, nonEmpty ) == offsetof( NoEmptyMember, nonEmpty ) );
+}
+#endif // gsl_CPP20_OR_GREATER && ( ! defined( _MSC_VER ) || gsl_COMPILER_MSVC_VERSION >= 1929 || gsl_COMPILER_CLANG_VERSION >= 1800 )
+
+// end of file
diff --git a/thirdparty/xmake.lua b/thirdparty/xmake.lua
index 30c6e39be..ae31dc784 100644
--- a/thirdparty/xmake.lua
+++ b/thirdparty/xmake.lua
@@ -168,3 +168,11 @@ target("ryml")
else
add_cxxflags("-Wno-unused-but-set-variable", "-Wno-undef")
end
+
+target("gsl-lite")
+ set_kind("headeronly")
+ set_group("thirdparty")
+ -- TODO: should migrate to new include path `gsl-lite/gsl-lite.hpp` so this can be removed
+ add_defines("gsl_FEATURE_GSL_COMPATIBILITY_MODE=1", {public=true})
+ add_headerfiles("gsl-lite/include/**.hpp")
+ add_includedirs("gsl-lite/include", {public=true})
diff --git a/xmake.lua b/xmake.lua
index b60ad72cb..a85c5c8cf 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -12,7 +12,6 @@ add_requires("http_parser", {system = false})
add_requires(
"vcpkg::curl",
"vcpkg::eastl",
- "vcpkg::gsl-lite",
"vcpkg::zlib"
)