Compare commits

..

41 Commits

Author SHA1 Message Date
Herb Sutter 882720bd73 Changed default to per-TU violation handlers
And removed the feature test macro to instead tgest for a specific C++ version.
2021-01-27 16:36:59 -08:00
Herb Sutter 81c10b8017 normalize is a more accurate name than sanitize 2020-12-22 17:04:07 -08:00
Herb Sutter 0b80ac7d02 gsl/assert cleanup
Removed unnecessary headers
Added missing const
2020-12-19 12:58:31 -08:00
Herb Sutter e269976910 Added inline variable support 2020-12-18 13:16:40 -08:00
Herb Sutter 60beb7a363 Fixed the default
Accidentally flipped on the previous commit
2020-12-18 12:53:36 -08:00
Herb Sutter d5fc4efbf6 Turn off GCC bounds checking for the tests where we intentionally test out of bounds 2020-12-18 12:48:15 -08:00
Herb Sutter 25c0dee6e3 Reinstance the GSL_*_ON_CONTRACT_VIOLATION macros
At least the nonthrowing ones
2020-12-18 12:45:05 -08:00
Herb Sutter e02baff283 Remove minor code duplication 2020-12-18 12:34:07 -08:00
Herb Sutter 71fd73fa04 Make constructor more constinit-friendly 2020-12-18 12:27:33 -08:00
Herb Sutter c78ad8661c Added "vestigial" comments for downlevel feature test workarounds 2020-12-18 12:18:23 -08:00
Herb Sutter 070db845f8 Add -Wno-global-constructors for Clang 2020-12-18 12:10:36 -08:00
Herb Sutter 0c5a66b666 Added workaround for non-constexpr std::exchange 2020-12-18 12:02:42 -08:00
Herb Sutter 248a7cbdce Add feature test for literal constructor in downlevel compilers 2020-12-18 11:56:36 -08:00
Herb Sutter b77eaa87ee Make contract_group a literal type 2020-12-18 11:40:50 -08:00
Herb Sutter 9033021831 Removed stray .exchange 2020-12-18 11:34:25 -08:00
Herb Sutter a45265a75e Handler shouldn't be internally synchronized 2020-12-18 11:30:17 -08:00
Herb Sutter 8bd828744f Remove constexpr again to see what the failures were 2020-12-18 11:25:04 -08:00
Herb Sutter 1c37688ccd Replaced some of the previous workarounds with feature tests
As always with feature tests, they can only be used to aggressively adopt new features even before all compilers we need have the features -- the test lets us write a vestigial workaround for downllevel compilers, to be removed as soon as all compilers support the feature.
2020-12-18 11:20:03 -08:00
Herb Sutter 8dfd03feeb Remove constexpr from contract_group constructor 2020-12-17 13:19:29 -08:00
Herb Sutter d83e9ea05f Add workarounds for Android compiler and constexpr test 2020-12-17 12:11:42 -08:00
Herb Sutter 59f38376b9 Change auto to void to satisfy some compilers about definition ordering 2020-12-17 12:03:59 -08:00
Herb Sutter dd45e5cfbd Went back to old-style declaration for older compilers that don't do C++17 guaranteed copy elision
A concession to older compilers.
2020-12-17 11:58:53 -08:00
Herb Sutter 0cbb9e221d Removed double .load
Require `chandler` to be never null by installing `[]()noexcept{}` as the handler if given a null pointer.
This lets us remove the double test in `assertion`.
2020-12-17 11:36:23 -08:00
Herb Sutter b7548fd1cd Update multi_span
Revert changes in multi_span to avoid a merge conflict, since this file was deleted in a parallel PR
2020-12-17 10:35:34 -08:00
Herb Sutter cbfd8cd734 Parameterize Expects1 and Ensures` by contract group
Allows independently controlling handling of different categories of bugs, such as bounds checks vs. null checks.
User-extensible: Companies can instantiate their own `contract_group` objects for their own categories of contract checks, including for distinguishing contract "levels" like `Normal` vs. `Audit` by just creating those two groups that can then be controlled independently or in combination.
2020-11-27 17:06:01 -08:00
Herb Sutter c16e4ce59f Replace GSL_CONTRACT_CHECK with contract_group 2020-11-27 16:33:12 -08:00
Herb Sutter b34dc221a1 Remove GSL_ASSUME (unused code)
This is not specified in the C++ Core Guidelines as part of GSL, so it should not be documented or supported with a GSL name. And since we don't use it in the GSL repo either, we should just remove it directly. For more about why assumptions are a dangerous blunt instrument, including that they actively eliminate contracts checks including GSL's `Expects` and `Ensures`, see [P2064](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2064r0.pdf).
2020-11-27 11:10:53 -08:00
Herb Sutter c20a54c8e7 Remove __builtin_expect prediction assistance
In microbenchmarks I tried, using `__builtin_expect` to indicate which branch was likely/unlikely was never faster, and often slower, than just omitting. In GSL, this is used only for `Expects` and `Ensures` which are nearly always true, and all processors have long been great at predicting such branches well.
2020-11-27 11:07:55 -08:00
Jordan Maples [MSFT] 0140ab1d73 Change build status badges (#955)
Using Azure Pipelines badge instead of the Travis-ci and Appveyor badges.
2020-11-23 16:11:40 -08:00
hdf89shfdfs 475b785d2c Use CMAKE_CXX_STANDARD when available (#953)
* Use CMAKE_CXX_STANDARD when available

If the use has provided the variable CMAKE_CXX_STANDARD use that instead of providing a default cache variable.

* Typo
2020-11-16 14:05:33 -08:00
Jordan Maples [MSFT] 959ce58bbc Update gsl (#954) 2020-11-16 09:31:12 -08:00
Jordan Maples [MSFT] 804a14fe8b Update README.md
update the supported matrix
2020-11-11 13:52:11 -08:00
beinhaerter 00d4a5aab6 suppress bounds.1 (#950)
Suppress "warning C26481: Don't use pointer arithmetic. Use span instead (bounds.1)."

Co-authored-by: Werner Henze <werner.henze+gitcommits@posteo.de>
2020-11-11 13:47:58 -08:00
Jordan Maples [MSFT] 9150ce9a95 Adding std::hash<not_null<T>> tests to notnull_tests.cpp (#947)
* added std::hash<not_null> tests

* nl
2020-11-03 16:56:09 -08:00
Jordan Maples [MSFT] a150aaa4ed renaming main logic files. Added warning message of the removal and include passthrough. Renamed includes in the source files. Ran Clang-Format (#946)
Header rename
2020-10-29 17:38:48 -07:00
Jordan Maples [MSFT] e8978c01ab Remove deprecation of basic_zstring et al (#945)
* Azure pipeline (#8)

* azure-pipeline test

* nl @ eof

* trimming the pipeline and adding debug steps

* removing redundant lines

* change ctest to script cmd and remove debug

* removed bad char

* added dir change for ctest

* explicit output file and cmake standard

* test cat

* more ctest tests

* injecting failure in test for validation

* another test

* removing bad test

* massive matrix

* added parallel

* commenting everything but xcode out for testing purposes

* uncomment the other tests

* testing some variables

* rename

* changed macos versions

* adding one more layer of templates

* fixing jobs.yml

* idk what i'm doing

* slight modifications

* maybe some spaces will help

* removing 'variables.'

* another test

* adding back pr w/ autocancel

* adding failing test to validate error = failing task

* remove failing test

* trigger master

* nl in steps.yml

* removing deprecation of basic_zstring and derived types. only *string_span should have been deprecated
2020-10-29 11:34:05 -07:00
Jordan Maples [MSFT] 2c3ab0211c Fix C26481 warning in span array ctor (#944)
* Azure pipeline (#8)

* azure-pipeline test

* nl @ eof

* trimming the pipeline and adding debug steps

* removing redundant lines

* change ctest to script cmd and remove debug

* removed bad char

* added dir change for ctest

* explicit output file and cmake standard

* test cat

* more ctest tests

* injecting failure in test for validation

* another test

* removing bad test

* massive matrix

* added parallel

* commenting everything but xcode out for testing purposes

* uncomment the other tests

* testing some variables

* rename

* changed macos versions

* adding one more layer of templates

* fixing jobs.yml

* idk what i'm doing

* slight modifications

* maybe some spaces will help

* removing 'variables.'

* another test

* adding back pr w/ autocancel

* adding failing test to validate error = failing task

* remove failing test

* trigger master

* nl in steps.yml

* remove forced decay of array reference to pointer in span array ctor
2020-10-29 10:54:37 -07:00
Jordan Maples [MSFT] 179fba51f5 Azure pipeline (#8) (#943) 2020-10-28 16:35:49 -07:00
Jordan Maples [MSFT] d74ae54b60 Update README.md
Closes #911
2020-10-28 15:47:06 -07:00
bowie7070 b6c57e2403 Include gsl_narrow from gsl and fix comment. (#939)
narrow() is now in gsl_narrow rather than gsl_util. Include gsl_narrow when exceptions are enabled. Ensures that #include <gsl/gsl> includes entire library as advertised in the documentation.

Co-authored-by: Bowie Owens <bowie.owens@csiro.au>
2020-10-28 15:38:32 -07:00
mtnpke 736b62a838 Allow usage on platforms not providing iostreams (#935)
Closes #933.
2020-10-28 15:37:02 -07:00
35 changed files with 1261 additions and 900 deletions
+19 -29
View File
@@ -1,5 +1,8 @@
cmake_minimum_required(VERSION 3.1.3...3.16)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(guidelineSupportLibrary)
project(GSL VERSION 3.1.0 LANGUAGES CXX)
include(ExternalProject)
@@ -8,39 +11,30 @@ find_package(Git)
# Use GNUInstallDirs to provide the right locations on all platforms
include(GNUInstallDirs)
# creates a library GSL which is an interface (header files only)
# Creates a library GSL which is an interface (header files only)
add_library(GSL INTERFACE)
# determine whether this is a standalone project or included by other projects
# NOTE: If you want to use GSL prefer to link against GSL using this alias target
# EX:
# target_link_libraries(foobar PRIVATE Microsoft.GSL::GSL)
#
# Add Microsoft.GSL::GSL alias for GSL so that dependents can be agnostic about
# whether GSL was added via `add_subdirectory` or `find_package`
add_library(Microsoft.GSL::GSL ALIAS GSL)
# Determine whether this is a standalone project or included by other projects
set(GSL_STANDALONE_PROJECT OFF)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(GSL_STANDALONE_PROJECT ON)
endif ()
set(GSL_CXX_STANDARD "14" CACHE STRING "Use c++ standard")
set(GSL_CXX_STD "cxx_std_${GSL_CXX_STANDARD}")
if (MSVC)
set(GSL_CXX_STD_OPT "-std:c++${GSL_CXX_STANDARD}")
else()
set(GSL_CXX_STD_OPT "-std=c++${GSL_CXX_STANDARD}")
endif()
# when minimum version required is 3.8.0 remove if below
# both branches do exactly the same thing
if (CMAKE_VERSION VERSION_LESS 3.7.9)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("${GSL_CXX_STD_OPT}" COMPILER_SUPPORTS_CXX_STANDARD)
# This GSL implementation generally assumes a platform that implements C++14 support.
set(gsl_min_cxx_standard "14")
if(COMPILER_SUPPORTS_CXX_STANDARD)
target_compile_options(GSL INTERFACE "${GSL_CXX_STD_OPT}")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no c++${GSL_CXX_STANDARD} support. Please use a different C++ compiler.")
endif()
else ()
target_compile_features(GSL INTERFACE "${GSL_CXX_STD}")
# on *nix systems force the use of -std=c++XX instead of -std=gnu++XX (default)
set(CMAKE_CXX_EXTENSIONS OFF)
if (GSL_STANDALONE_PROJECT)
gsl_set_default_cxx_standard(${gsl_min_cxx_standard})
else()
gsl_client_set_cxx_standard(${gsl_min_cxx_standard})
endif()
# add definitions to the library and targets that consume it
@@ -111,10 +105,6 @@ else()
endif()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL)
# Add Microsoft.GSL::GSL alias for GSL so that dependents can be agnostic about
# whether GSL was added via `add_subdirectory` or `find_package`
add_library(Microsoft.GSL::GSL ALIAS GSL)
option(GSL_TEST "Generate tests." ${GSL_STANDALONE_PROJECT})
if (GSL_TEST)
enable_testing()
+19 -22
View File
@@ -1,5 +1,5 @@
# GSL: Guidelines Support Library
[![Build Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL) [![Build status](https://ci.appveyor.com/api/projects/status/github/Microsoft/GSL?svg=true)](https://ci.appveyor.com/project/neilmacintosh/GSL)
[![Build Status](https://dev.azure.com/cppstat/GSL/_apis/build/status/microsoft.GSL?branchName=master)](https://dev.azure.com/cppstat/GSL/_build/latest?definitionId=1&branchName=master)
The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the
[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org).
@@ -29,14 +29,23 @@ owner | &#x2611; | an alias for a raw pointer
not_null | &#x2611; | restricts a pointer / smart pointer to hold non-null values
span | &#x2611; | a view over a contiguous sequence of memory. Based on the standardized verison of `std::span`, however `gsl::span` enforces bounds checking. See the [wiki](https://github.com/microsoft/GSL/wiki/gsl::span-and-std::span) for additional information.
span_p | &#x2610; | spans a range starting from a pointer to the first place for which the predicate is true
basic_zstring | &#x2611; | A pointer to a C-string (zero-terminated array) with a templated char type
zstring | &#x2611; | An alias to `basic_zstring` with a char type of char
czstring | &#x2611; | An alias to `basic_zstring` with a char type of const char
wzstring | &#x2611; | An alias to `basic_zstring` with a char type of wchar_t
cwzstring | &#x2611; | An alias to `basic_zstring` with a char type of const wchar_t
u16zstring | &#x2611; | An alias to `basic_zstring` with a char type of char16_t
cu16zstring | &#x2611; | An alias to `basic_zstring` with a char type of const char16_t
u32zstring | &#x2611; | An alias to `basic_zstring` with a char type of char32_t
cu32zstring | &#x2611; | An alias to `basic_zstring` with a char type of const char32_t
[**2. Owners**][cg-owners] | |
unique_ptr | &#x2611; | an alias to `std::unique_ptr`
shared_ptr | &#x2611; | an alias to `std::shared_ptr`
stack_array | &#x2610; | a stack-allocated array
dyn_array | &#x2610; | a heap-allocated array
[**3. Assertions**][cg-assertions] | |
Expects | &#x2611; | a precondition assertion; on failure it terminates
Ensures | &#x2611; | a postcondition assertion; on failure it terminates
Expects | &#x2611; | a precondition assertion; on failure it terminates by default if no user-installed handler
Ensures | &#x2611; | a postcondition assertion; on failure it terminates by default if no user-installed handler
[**4. Utilities**][cg-utilities] | |
move_owner | &#x2610; | a helper function that moves one `owner` to the other
byte | &#x2611; | either an alias to std::byte or a byte type
@@ -57,15 +66,6 @@ Feature | Supported? | Description
strict_not_null | &#x2611; | A stricter version of `not_null` with explicit constructors
multi_span | &#x2610; | Deprecated. Multi-dimensional span.
strided_span | &#x2610; | Deprecated. Support for this type has been discontinued.
basic_zstring | &#x2610; | Deprecated. A pointer to a C-string (zero-terminated array) with a templated char type
zstring | &#x2610; | Deprecated. An alias to `basic_zstring` with a char type of char
czstring | &#x2610; | Deprecated. An alias to `basic_zstring` with a char type of const char
wzstring | &#x2610; | Deprecated. An alias to `basic_zstring` with a char type of wchar_t
cwzstring | &#x2610; | Deprecated. An alias to `basic_zstring` with a char type of const wchar_t
u16zstring | &#x2610; | Deprecated. An alias to `basic_zstring` with a char type of char16_t
cu16zstring | &#x2610; | Deprecated. An alias to `basic_zstring` with a char type of const char16_t
u32zstring | &#x2610; | Deprecated. An alias to `basic_zstring` with a char type of char32_t
cu32zstring | &#x2610; | Deprecated. An alias to `basic_zstring` with a char type of const char32_t
basic_string_span | &#x2610; | Deprecated. Like `span` but for strings with a templated char type
string_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of char
cstring_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of const char
@@ -89,16 +89,13 @@ This is based on [CppCoreGuidelines semi-specification](https://github.com/isocp
The GSL officially supports the current and previous major release of MSVC, GCC, Clang, and XCode's Apple-Clang.
See our latest test results for the most up-to-date list of supported configurations.
Compiler |Toolset Versions Currently Tested| Build Status
:------- |:--|------------:
XCode |11.4 & 10.3 | [![Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL)
GCC |9 & 8| [![Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL)
Clang |11 & 10| [![Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL)
Visual Studio with MSVC | VS2017 (15.9) & VS2019 (16.4) | [![Status](https://ci.appveyor.com/api/projects/status/github/Microsoft/GSL?svg=true)](https://ci.appveyor.com/project/neilmacintosh/GSL)
Visual Studio with LLVM | VS2017 (Clang 9) & VS2019 (Clang 10) | [![Status](https://ci.appveyor.com/api/projects/status/github/Microsoft/GSL?svg=true)](https://ci.appveyor.com/project/neilmacintosh/GSL)
Note: For `gsl::byte` to work correctly with Clang and GCC you might have to use the ` -fno-strict-aliasing` compiler option.
Compiler |Toolset Versions Currently Tested
:------- |--:
XCode |11.4 & 10.3
GCC |9 & 8
Clang |11 & 10
Visual Studio with MSVC | VS2017 (15.9) & VS2019 (16.4)
Visual Studio with LLVM | VS2017 (Clang 9) & VS2019 (Clang 10)
---
If you successfully port GSL to another platform, we would love to hear from you!
+68
View File
@@ -0,0 +1,68 @@
trigger:
- master
pr:
autoCancel: true
# GCC
stages:
- stage: GCC
dependsOn: []
variables:
- name: CC
value: gcc
- name: CXX
value: g++
jobs:
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate GCC latest'
imageName: ubuntu-20.04
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate GCC Previous'
imageName: ubuntu-18.04
# Clang
- stage: Clang
dependsOn: []
variables:
- name: CC
value: clang
- name: CXX
value: clang++
jobs:
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate Clang latest'
imageName: ubuntu-20.04
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate Clang Previous'
imageName: ubuntu-18.04
# MSVC
- stage: MSVC
dependsOn: []
jobs:
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate MSVC latest'
imageName: windows-latest
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate MSVC Previous'
imageName: vs2017-win2016
# Apple-Clang
- stage: Apple_Clang
dependsOn: []
jobs:
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate Apple-Clang latest'
imageName: macos-10.15
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate Apple-Clang Previous'
imageName: macos-10.14
+61
View File
@@ -0,0 +1,61 @@
# This cmake module is meant to hold helper functions/macros
# that make maintaining the cmake build system much easier.
# This is especially helpful since gsl needs to provide coverage
# for multiple versions of cmake.
#
# Any functions/macros should have a gsl_* prefix to avoid problems
if (DEFINED guideline_support_library_include_guard)
return()
endif()
set(guideline_support_library_include_guard ON)
function(gsl_set_default_cxx_standard min_cxx_standard)
set(GSL_CXX_STANDARD "${min_cxx_standard}" CACHE STRING "Use c++ standard")
set(GSL_CXX_STD "cxx_std_${GSL_CXX_STANDARD}")
if (MSVC)
set(GSL_CXX_STD_OPT "-std:c++${GSL_CXX_STANDARD}")
else()
set(GSL_CXX_STD_OPT "-std=c++${GSL_CXX_STANDARD}")
endif()
# when minimum version required is 3.8.0 remove if below
# both branches do exactly the same thing
if (CMAKE_VERSION VERSION_LESS 3.7.9)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("${GSL_CXX_STD_OPT}" COMPILER_SUPPORTS_CXX_STANDARD)
if(COMPILER_SUPPORTS_CXX_STANDARD)
target_compile_options(GSL INTERFACE "${GSL_CXX_STD_OPT}")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no c++${GSL_CXX_STANDARD} support. Please use a different C++ compiler.")
endif()
else()
target_compile_features(GSL INTERFACE "${GSL_CXX_STD}")
# on *nix systems force the use of -std=c++XX instead of -std=gnu++XX (default)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
endfunction()
# The best way for a project to specify the GSL's C++ standard is by the client specifying
# the CMAKE_CXX_STANDARD. However, this isn't always ideal. Since the CMAKE_CXX_STANDARD is
# tied to the cmake version. And many projects have low cmake minimums.
#
# So provide an alternative approach in case that doesn't work.
function(gsl_client_set_cxx_standard min_cxx_standard)
if (DEFINED CMAKE_CXX_STANDARD)
if (${CMAKE_CXX_STANDARD} VERSION_LESS ${min_cxx_standard})
message(FATAL_ERROR "GSL: Requires at least CXX standard ${min_cxx_standard}, user provided ${CMAKE_CXX_STANDARD}")
endif()
# Set the GSL standard to what the client desires
set(GSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}" PARENT_SCOPE)
# Exit out early to avoid extra unneccessary work
return()
endif()
# Otherwise pick a reasonable default
gsl_set_default_cxx_standard(${min_cxx_standard})
endfunction()
+63
View File
@@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_ALGORITHM_H
#define GSL_ALGORITHM_H
#include <gsl/assert> // for contracts
#include <gsl/span> // for dynamic_extent, span
#include <algorithm> // for copy_n
#include <cstddef> // for ptrdiff_t
#include <type_traits> // for is_assignable
#ifdef _MSC_VER
#pragma warning(push)
// turn off some warnings that are noisy about our contract checks
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4996) // unsafe use of std::copy_n
#endif // _MSC_VER
namespace gsl
{
// Note: this will generate faster code than std::copy using span iterator in older msvc+stl
// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915)
template <class SrcElementType, std::size_t SrcExtent, class DestElementType,
std::size_t DestExtent>
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
{
static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value,
"Elements of source span can not be assigned to elements of destination span");
static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
(SrcExtent <= DestExtent),
"Source range is longer than target range");
Expects(dest.size() >= src.size(), Bounds);
// clang-format off
GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute
// clang-format on
std::copy_n(src.data(), src.size(), dest.data());
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_ALGORITHM_H
+149
View File
@@ -0,0 +1,149 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_CONTRACTS_H
#define GSL_CONTRACTS_H
//
// Temporary until MSVC STL supports no-exceptions mode.
// Currently terminate is a no-op in this mode, so we add termination behavior back
//
#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h>
#define RANGE_CHECKS_FAILURE 0
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-noreturn"
#endif // defined(__clang__)
#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) &&
// !_HAS_EXCEPTIONS))
#include <exception>
#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) &&
// !_HAS_EXCEPTIONS))
//
// make suppress attributes parse for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__
#define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
//
// GSL.assert: assertions
//
namespace gsl
{
namespace details
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
typedef void(__cdecl* terminate_handler)();
// clang-format off
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
// clang-format on
[[noreturn]] inline void __cdecl default_terminate_handler()
{
__fastfail(RANGE_CHECKS_FAILURE);
}
inline gsl::details::terminate_handler& get_terminate_handler() noexcept
{
static terminate_handler handler = &default_terminate_handler;
return handler;
}
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
[[noreturn]] inline void terminate() noexcept
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
(*gsl::details::get_terminate_handler())();
#else
std::terminate();
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
}
} // namespace details
class contract_group {
public:
#if defined __cpp_noexcept_function_type
using handler = void (*)() noexcept;
#else // VESTIGIAL, remove when no longer needed for downlevel compilers
using handler = void (*)();
#endif
constexpr contract_group (handler h = nullptr) : chandler(normalize(h)) { }
constexpr auto set_handler(handler h) -> handler { auto old = chandler; chandler = normalize(h); return old; }
constexpr auto get_handler() const -> handler { return chandler; }
constexpr auto expects (bool b) -> void { assertion(b); }
constexpr auto ensures (bool b) -> void { assertion(b); }
private:
constexpr auto assertion(bool b) -> void { if (!b) chandler(); }
constexpr auto normalize(handler h) -> handler { return h ? h : []()noexcept{}; }
handler chandler;
};
// By default, there is one violation handler per translation unit.
// Defining GSL_GLOBAL_CONTRACT_VIOLATION_HANDLERS and compiling as
// C++17 (or later) opts into using a global violation handler.
#if defined GSL_GLOBAL_CONTRACT_VIOLATION_HANDLERS && __cplusplus >= 201703L
#define GSL_CONTRACT_VIOLATION_GRANULARITY inline
#else
#define GSL_CONTRACT_VIOLATION_GRANULARITY static
#endif
auto GSL_CONTRACT_VIOLATION_GRANULARITY Default = contract_group(
#if defined GSL_UNENFORCED_ON_CONTRACT_VIOLATION
// use default == null handler
#else // if defined GSL_TERMINATE_ON_CONTRACT_VIOLATION
&gsl::details::terminate
#endif
);
auto GSL_CONTRACT_VIOLATION_GRANULARITY Bounds = Default;
auto GSL_CONTRACT_VIOLATION_GRANULARITY Null = Default;
auto GSL_CONTRACT_VIOLATION_GRANULARITY Testing = Default;
} // namespace gsl
#define Expects(cond, kind) kind.expects(cond)
#define Ensures(cond, kind) kind.ensures(cond)
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // GSL_CONTRACTS_H
+213
View File
@@ -0,0 +1,213 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_BYTE_H
#define GSL_BYTE_H
//
// make suppress attributes work for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__
#include <type_traits>
// VS2017 15.8 added support for the __cpp_lib_byte definition
// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires
#ifdef _MSC_VER
#pragma warning(push)
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates
// does not always work
#ifndef GSL_USE_STD_BYTE
// this tests if we are under MSVC and the standard lib has std::byte and it is enabled
#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || \
(defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
#define GSL_USE_STD_BYTE 1
#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >=
// 201603)
#define GSL_USE_STD_BYTE 0
#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >=
// 201603)
#endif // GSL_USE_STD_BYTE
#else // _MSC_VER
#ifndef GSL_USE_STD_BYTE
#include <cstddef> /* __cpp_lib_byte */
// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte
// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte
#if defined(__cplusplus) && (__cplusplus >= 201703L) && \
(defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \
defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 1
#else // defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 0
#endif // defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#endif // GSL_USE_STD_BYTE
#endif // _MSC_VER
// Use __may_alias__ attribute on gcc and clang
#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5)
#define byte_may_alias __attribute__((__may_alias__))
#else // defined __clang__ || defined __GNUC__
#define byte_may_alias
#endif // defined __clang__ || defined __GNUC__
#if GSL_USE_STD_BYTE
#include <cstddef>
#endif
namespace gsl
{
#if GSL_USE_STD_BYTE
using std::byte;
using std::to_integer;
#else // GSL_USE_STD_BYTE
// This is a simple definition for now that allows
// use of byte within span<> to be standards-compliant
enum class byte_may_alias byte : unsigned char
{
};
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator<<(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) >> shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator>>(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) >> shift);
}
constexpr byte& operator|=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte operator|(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte& operator&=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte operator&(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte& operator^=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator^(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr IntegerType to_integer(byte b) noexcept
{
return static_cast<IntegerType>(b);
}
#endif // GSL_USE_STD_BYTE
template <bool E, typename T>
constexpr byte to_byte_impl(T t) noexcept
{
static_assert(
E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
"If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version.");
return static_cast<byte>(t);
}
template <>
// NOTE: need suppression since c++14 does not allow "return {t}"
// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work
constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
{
return byte(t);
}
template <typename T>
constexpr byte to_byte(T t) noexcept
{
return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
}
template <int I>
constexpr byte to_byte() noexcept
{
static_assert(I >= 0 && I <= 255,
"gsl::byte only has 8 bits of storage, values must be in range 0-255");
return static_cast<byte>(I);
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_BYTE_H
+12 -8
View File
@@ -17,13 +17,17 @@
#ifndef GSL_GSL_H
#define GSL_GSL_H
#include <gsl/gsl_algorithm> // copy
#include <gsl/gsl_assert> // Ensures/Expects
#include <gsl/gsl_byte> // byte
#include <gsl/gsl_util> // finally()/narrow()/narrow_cast()...
#include <gsl/multi_span> // multi_span, strided_span...
#include <gsl/pointers> // owner, not_null
#include <gsl/span> // span
#include <gsl/string_span> // zstring, string_span, zstring_builder...
#include <gsl/algorithm> // copy
#include <gsl/assert> // contracts
#include <gsl/byte> // byte
#include <gsl/pointers> // owner, not_null
#include <gsl/multi_span> // multi_span, strided_span...
#include <gsl/span> // span
#include <gsl/string_span> // zstring, string_span, zstring_builder...
#include <gsl/util> // finally()/narrow_cast()...
#ifdef __cpp_exceptions
#include <gsl/narrow> // narrow()
#endif
#endif // GSL_GSL_H
+3 -61
View File
@@ -1,61 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_ALGORITHM_H
#define GSL_ALGORITHM_H
#include <gsl/gsl_assert> // for Expects
#include <gsl/span> // for dynamic_extent, span
#include <algorithm> // for copy_n
#include <cstddef> // for ptrdiff_t
#include <type_traits> // for is_assignable
#ifdef _MSC_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 : 4996) // unsafe use of std::copy_n
#endif // _MSC_VER
namespace gsl
{
// Note: this will generate faster code than std::copy using span iterator in older msvc+stl
// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915)
template <class SrcElementType, std::size_t SrcExtent, class DestElementType,
std::size_t DestExtent>
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
{
static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value,
"Elements of source span can not be assigned to elements of destination span");
static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
(SrcExtent <= DestExtent),
"Source range is longer than target range");
Expects(dest.size() >= src.size());
GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute
std::copy_n(src.data(), src.size(), dest.data());
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_ALGORITHM_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/algorithm> instead of <gsl/gsl_algorithm>")
#include <gsl/algorithm>
+3 -133
View File
@@ -1,133 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_CONTRACTS_H
#define GSL_CONTRACTS_H
//
// Temporary until MSVC STL supports no-exceptions mode.
// Currently terminate is a no-op in this mode, so we add termination behavior back
//
#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h>
#define RANGE_CHECKS_FAILURE 0
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-noreturn"
#endif // defined(__clang__)
#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
#include <exception>
#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
//
// make suppress attributes parse for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER) && ! defined(__INTEL_COMPILER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__
#define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
#if defined(__clang__) || defined(__GNUC__)
#define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define GSL_LIKELY(x) (!!(x))
#define GSL_UNLIKELY(x) (!!(x))
#endif // defined(__clang__) || defined(__GNUC__)
//
// GSL_ASSUME(cond)
//
// Tell the optimizer that the predicate cond must hold. It is unspecified
// whether or not cond is actually evaluated.
//
#ifdef _MSC_VER
#define GSL_ASSUME(cond) __assume(cond)
#elif defined(__GNUC__)
#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable())
#else
#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0)
#endif
//
// GSL.assert: assertions
//
namespace gsl
{
namespace details
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
typedef void(__cdecl* terminate_handler)();
// clang-format off
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
// clang-format on
[[noreturn]] inline void __cdecl default_terminate_handler()
{
__fastfail(RANGE_CHECKS_FAILURE);
}
inline gsl::details::terminate_handler& get_terminate_handler() noexcept
{
static terminate_handler handler = &default_terminate_handler;
return handler;
}
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
[[noreturn]] inline void terminate() noexcept
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
(*gsl::details::get_terminate_handler())();
#else
std::terminate();
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
}
} // namespace details
} // namespace gsl
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // GSL_CONTRACTS_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/assert> instead of <gsl/gsl_assert>")
#include <gsl/assert>
+3 -209
View File
@@ -1,209 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_BYTE_H
#define GSL_BYTE_H
//
// make suppress attributes work for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER) && ! defined(__INTEL_COMPILER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__
#include <type_traits>
// VS2017 15.8 added support for the __cpp_lib_byte definition
// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires
#ifdef _MSC_VER
#pragma warning(push)
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates does not always work
#ifndef GSL_USE_STD_BYTE
// this tests if we are under MSVC and the standard lib has std::byte and it is enabled
#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
#define GSL_USE_STD_BYTE 1
#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
#define GSL_USE_STD_BYTE 0
#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
#endif // GSL_USE_STD_BYTE
#else // _MSC_VER
#ifndef GSL_USE_STD_BYTE
#include <cstddef> /* __cpp_lib_byte */
// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte
// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte
#if defined(__cplusplus) && (__cplusplus >= 201703L) && \
(defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \
defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 1
#else // defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 0
#endif //defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#endif // GSL_USE_STD_BYTE
#endif // _MSC_VER
// Use __may_alias__ attribute on gcc and clang
#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5)
#define byte_may_alias __attribute__((__may_alias__))
#else // defined __clang__ || defined __GNUC__
#define byte_may_alias
#endif // defined __clang__ || defined __GNUC__
#if GSL_USE_STD_BYTE
#include <cstddef>
#endif
namespace gsl
{
#if GSL_USE_STD_BYTE
using std::byte;
using std::to_integer;
#else // GSL_USE_STD_BYTE
// This is a simple definition for now that allows
// use of byte within span<> to be standards-compliant
enum class byte_may_alias byte : unsigned char
{
};
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator<<(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) >> shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator>>(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) >> shift);
}
constexpr byte& operator|=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte operator|(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte& operator&=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte operator&(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte& operator^=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator^(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr IntegerType to_integer(byte b) noexcept
{
return static_cast<IntegerType>(b);
}
#endif // GSL_USE_STD_BYTE
template <bool E, typename T>
constexpr byte to_byte_impl(T t) noexcept
{
static_assert(
E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
"If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version.");
return static_cast<byte>(t);
}
template <>
// NOTE: need suppression since c++14 does not allow "return {t}"
// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work
constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
{
return byte(t);
}
template <typename T>
constexpr byte to_byte(T t) noexcept
{
return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
}
template <int I>
constexpr byte to_byte() noexcept
{
static_assert(I >= 0 && I <= 255,
"gsl::byte only has 8 bits of storage, values must be in range 0-255");
return static_cast<byte>(I);
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_BYTE_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/byte> instead of <gsl/gsl_byte>")
#include <gsl/byte>
+3 -52
View File
@@ -1,52 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_NARROW_H
#define GSL_NARROW_H
#include <gsl/gsl_assert> // for Expects
#include <gsl/gsl_util> // for narrow_cast
namespace gsl
{
struct narrowing_error : public std::exception
{
const char* what() const noexcept override
{
return "narrowing_error";
}
};
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
constexpr
T narrow(U u) noexcept(false)
{
constexpr const bool is_different_signedness = (std::is_signed<T>::value != std::is_signed<U>::value);
const T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u
|| (is_different_signedness
&& ((t < T{}) != (u < U{}))))
{
throw narrowing_error{};
}
return t;
}
}
#endif // GSL_NARROW_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/narrow> instead of <gsl/gsl_narrow>")
#include <gsl/narrow>
+3 -129
View File
@@ -1,129 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_UTIL_H
#define GSL_UTIL_H
#include <gsl/gsl_assert> // for Expects
#include <array>
#include <cstddef> // for ptrdiff_t, size_t
#include <initializer_list> // for initializer_list
#include <type_traits> // for is_signed, integral_constant
#include <utility> // for exchange, forward
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#endif // _MSC_VER
#if defined(__cplusplus) && (__cplusplus >= 201703L)
#define GSL_NODISCARD [[nodiscard]]
#else
#define GSL_NODISCARD
#endif // defined(__cplusplus) && (__cplusplus >= 201703L)
namespace gsl
{
//
// GSL.util: utilities
//
// index type for all container indexes/subscripts/sizes
using index = std::ptrdiff_t;
// final_action allows you to ensure something gets run at the end of a scope
template <class F>
class final_action
{
public:
static_assert(!std::is_reference<F>::value && !std::is_const<F>::value && !std::is_volatile<F>::value, "Final_action should store its callable by value");
explicit final_action(F f) noexcept : f_(std::move(f)) {}
final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) {}
final_action(const final_action&) = delete;
final_action& operator=(const final_action&) = delete;
final_action& operator=(final_action&&) = delete;
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
~final_action() noexcept
{
if (invoke_) f_();
}
private:
F f_;
bool invoke_{true};
};
// finally() - convenience function to generate a final_action
template <class F>
GSL_NODISCARD final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type> finally(F&& f) noexcept
{
return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(std::forward<F>(f));
}
// narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U>
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
constexpr T narrow_cast(U&& u) noexcept
{
return static_cast<T>(std::forward<U>(u));
}
//
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
//
template <class T, std::size_t N>
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
constexpr T& at(T (&arr)[N], const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(N));
return arr[narrow_cast<std::size_t>(i)];
}
template <class Cont>
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
using size_type = decltype(cont.size());
return cont[narrow_cast<size_type>(i)];
}
template <class T>
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr T at(const std::initializer_list<T> cont, const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
return *(cont.begin() + i);
}
} // namespace gsl
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_UTIL_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/util> instead of <gsl/gsl_util>")
#include <gsl/util>
+177 -61
View File
@@ -17,12 +17,12 @@
#ifndef GSL_MULTI_SPAN_H
#define GSL_MULTI_SPAN_H
#include <gsl/gsl_assert> // for Expects
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/assert> // for Expects
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#include <algorithm> // for transform, lexicographical_compare
#include <array> // for array
#include <algorithm> // for transform, lexicographical_compare
#include <array> // for array
#include <cstddef> // for std::ptrdiff_t, size_t, nullptr_t
#include <cstdint> // for PTRDIFF_MAX
#include <functional> // for divides, multiplies, minus, negate, plus
@@ -95,7 +95,8 @@ namespace details
} // namespace details
template <std::size_t Rank>
class [[deprecated]] multi_span_index final {
class [[deprecated]] multi_span_index final
{
static_assert(Rank > 0, "Rank must be greater than 0!");
template <std::size_t OtherRank>
@@ -110,10 +111,12 @@ public:
constexpr multi_span_index() noexcept {}
constexpr multi_span_index(const value_type(&values)[Rank]) noexcept
constexpr multi_span_index(const value_type (&values)[Rank]) noexcept
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::copy(values, values + Rank, elems);
}
@@ -127,8 +130,10 @@ public:
constexpr multi_span_index& operator=(const multi_span_index& rhs) noexcept = default;
// Preconditions: component_idx < rank
// clang-format off
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr reference operator[](std::size_t component_idx)
{
Expects(component_idx < Rank); // Component index must be less than rank
@@ -136,16 +141,20 @@ public:
}
// Preconditions: component_idx < rank
// clang-format off
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr const_reference operator[](std::size_t component_idx) const
{
Expects(component_idx < Rank); // Component index must be less than rank
return elems[component_idx];
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
constexpr bool operator==(const multi_span_index& rhs) const
{
return std::equal(elems, elems + rank, rhs.elems);
@@ -178,16 +187,20 @@ public:
constexpr multi_span_index& operator+=(const multi_span_index& rhs)
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::transform(elems, elems + rank, rhs.elems, elems, std::plus<value_type>{});
return *this;
}
constexpr multi_span_index& operator-=(const multi_span_index& rhs)
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::transform(elems, elems + rank, rhs.elems, elems, std::minus<value_type>{});
return *this;
}
@@ -213,8 +226,10 @@ public:
constexpr multi_span_index& operator*=(value_type v)
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::transform(elems, elems + rank, elems,
[v](value_type x) { return std::multiplies<value_type>{}(x, v); });
return *this;
@@ -222,8 +237,10 @@ public:
constexpr multi_span_index& operator/=(value_type v)
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::transform(elems, elems + rank, elems,
[v](value_type x) { return std::divides<value_type>{}(x, v); });
return *this;
@@ -286,7 +303,9 @@ const std::ptrdiff_t dynamic_range = -1;
struct [[deprecated]] generalized_mapping_tag
{
};
struct[[deprecated]] contiguous_mapping_tag : generalized_mapping_tag{};
struct [[deprecated]] contiguous_mapping_tag : generalized_mapping_tag
{
};
namespace details
{
@@ -298,7 +317,8 @@ namespace details
};
template <std::ptrdiff_t... Ranges>
struct [[deprecated]] BoundsRanges {
struct [[deprecated]] BoundsRanges
{
using size_type = std::ptrdiff_t;
static const size_type Depth = 0;
static const size_type DynamicNum = 0;
@@ -337,7 +357,7 @@ namespace details
};
template <std::ptrdiff_t... RestRanges>
struct[[deprecated]] BoundsRanges<dynamic_range, RestRanges...> : BoundsRanges<RestRanges...>
struct [[deprecated]] BoundsRanges<dynamic_range, RestRanges...> : BoundsRanges<RestRanges...>
{
using Base = BoundsRanges<RestRanges...>;
using size_type = std::ptrdiff_t;
@@ -350,9 +370,10 @@ namespace details
size_type m_bound;
public:
GSL_SUPPRESS(
f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format off
GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr BoundsRanges(const std::ptrdiff_t* const arr)
: Base(arr + 1), m_bound(*arr * this->Base::totalSize())
{
@@ -369,14 +390,16 @@ namespace details
{}
template <typename T, std::size_t Dim = 0>
constexpr void serialize(T & arr) const
constexpr void serialize(T& arr) const
{
arr[Dim] = elementNum();
this->Base::template serialize<T, Dim + 1>(arr);
}
template <typename T, std::size_t Dim = 0>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type linearize(const T& arr) const
{
const size_type index = this->Base::totalSize() * arr[Dim];
@@ -393,19 +416,22 @@ namespace details
return cur < m_bound ? cur + last : -1;
}
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type totalSize() const noexcept { return m_bound; }
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type elementNum() const noexcept
{
return totalSize() / this->Base::totalSize();
}
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type elementNum(std::size_t dim) const noexcept
{
if (dim > 0)
@@ -422,7 +448,7 @@ namespace details
};
template <std::ptrdiff_t CurRange, std::ptrdiff_t... RestRanges>
struct[[deprecated]] BoundsRanges<CurRange, RestRanges...> : BoundsRanges<RestRanges...>
struct [[deprecated]] BoundsRanges<CurRange, RestRanges...> : BoundsRanges<RestRanges...>
{
using Base = BoundsRanges<RestRanges...>;
using size_type = std::ptrdiff_t;
@@ -440,12 +466,14 @@ namespace details
bool firstLevel = true)
: Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
{
// clang-format off
GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
(void) firstLevel;
}
template <typename T, std::size_t Dim = 0>
constexpr void serialize(T & arr) const
constexpr void serialize(T& arr) const
{
arr[Dim] = elementNum();
this->Base::template serialize<T, Dim + 1>(arr);
@@ -454,9 +482,13 @@ namespace details
template <typename T, std::size_t Dim = 0>
constexpr size_type linearize(const T& arr) const
{
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
Expects(arr[Dim] >= 0 && arr[Dim] < CurrentRange); // Index is out of range
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
const std::ptrdiff_t d = arr[Dim];
return this->Base::totalSize() * d + this->Base::template linearize<T, Dim + 1>(arr);
}
@@ -470,19 +502,22 @@ namespace details
return this->Base::totalSize() * arr[Dim] + last;
}
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type totalSize() const noexcept
{
return CurrentRange * this->Base::totalSize();
}
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type elementNum() const noexcept { return CurrentRange; }
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type elementNum(std::size_t dim) const noexcept
{
if (dim > 0)
@@ -498,14 +533,17 @@ namespace details
};
template <typename SourceType, typename TargetType>
struct[[deprecated]] BoundsRangeConvertible
struct [[deprecated]] BoundsRangeConvertible
: public std::integral_constant<bool, (SourceType::TotalSize >= TargetType::TotalSize ||
TargetType::TotalSize == dynamic_range ||
SourceType::TotalSize == dynamic_range ||
TargetType::TotalSize == 0)>{};
TargetType::TotalSize == 0)>
{
};
template <typename TypeChain>
struct [[deprecated]] TypeListIndexer {
struct [[deprecated]] TypeListIndexer
{
const TypeChain& obj_;
constexpr TypeListIndexer(const TypeChain& obj) : obj_(obj) {}
@@ -518,13 +556,13 @@ namespace details
template <std::size_t N, typename MyChain = TypeChain,
typename MyBase = typename MyChain::Base>
constexpr auto getObj(std::false_type)
->decltype(TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>())
-> decltype(TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>())
{
return TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>();
}
template <std::size_t N>
constexpr auto get()->decltype(getObj<N - 1>(std::integral_constant<bool, N == 0>()))
constexpr auto get() -> decltype(getObj<N - 1>(std::integral_constant<bool, N == 0>()))
{
return getObj<N - 1>(std::integral_constant<bool, N == 0>());
}
@@ -543,7 +581,9 @@ namespace details
Ret ret{};
for (std::size_t i = 0; i < Rank - 1; ++i)
{
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
ret[i] = other[i + 1];
}
return ret;
@@ -554,13 +594,14 @@ template <typename IndexType>
class [[deprecated]] bounds_iterator;
template <std::ptrdiff_t... Ranges>
class [[deprecated]] static_bounds {
class [[deprecated]] static_bounds
{
public:
static_bounds(const details::BoundsRanges<Ranges...>&) {}
};
template <std::ptrdiff_t FirstRange, std::ptrdiff_t... RestRanges>
class[[deprecated]] static_bounds<FirstRange, RestRanges...>
class [[deprecated]] static_bounds<FirstRange, RestRanges...>
{
using MyRanges = details::BoundsRanges<FirstRange, RestRanges...>;
@@ -592,10 +633,10 @@ public:
template <std::size_t Rank, typename SourceType, typename TargetType,
typename Ret = BoundsRangeConvertible2<typename SourceType::Base,
typename TargetType::Base, Rank>>
static auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type)->Ret;
static auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type) -> Ret;
template <std::size_t Rank, typename SourceType, typename TargetType>
static auto helpBoundsRangeConvertible(SourceType, TargetType, ...)->std::false_type;
static auto helpBoundsRangeConvertible(SourceType, TargetType, ...) -> std::false_type;
template <typename SourceType, typename TargetType, std::size_t Rank>
struct BoundsRangeConvertible2
@@ -721,7 +762,8 @@ public:
};
template <std::size_t Rank>
class [[deprecated]] strided_bounds {
class [[deprecated]] strided_bounds
{
template <std::size_t OtherRank>
friend class strided_bounds;
@@ -745,7 +787,7 @@ public:
constexpr strided_bounds& operator=(const strided_bounds&) noexcept = default;
constexpr strided_bounds(const value_type(&values)[rank], index_type strides)
constexpr strided_bounds(const value_type (&values)[rank], index_type strides)
: m_extents(values), m_strides(std::move(strides))
{}
@@ -755,7 +797,9 @@ public:
constexpr index_type strides() const noexcept { return m_strides; }
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type total_size() const noexcept
{
size_type ret = 0;
@@ -763,7 +807,9 @@ public:
return ret + 1;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type size() const noexcept
{
size_type ret = 1;
@@ -780,7 +826,9 @@ public:
return true;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type linearize(const index_type& idx) const
{
size_type ret = 0;
@@ -792,7 +840,9 @@ public:
return ret;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type stride() const noexcept { return m_strides[0]; }
template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
@@ -803,7 +853,9 @@ public:
template <std::size_t Dim = 0>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type extent() const noexcept
{
static_assert(Dim < Rank,
@@ -823,14 +875,21 @@ private:
};
template <typename T>
struct[[deprecated]] is_bounds : std::integral_constant<bool, false>{};
struct [[deprecated]] is_bounds : std::integral_constant<bool, false>
{
};
template <std::ptrdiff_t... Ranges>
struct[[deprecated]] is_bounds<static_bounds<Ranges...>> : std::integral_constant<bool, true>{};
struct [[deprecated]] is_bounds<static_bounds<Ranges...>> : std::integral_constant<bool, true>
{
};
template <std::size_t Rank>
struct[[deprecated]] is_bounds<strided_bounds<Rank>> : std::integral_constant<bool, true>{};
struct [[deprecated]] is_bounds<strided_bounds<Rank>> : std::integral_constant<bool, true>
{
};
template <typename IndexType>
class [[deprecated]] bounds_iterator {
class [[deprecated]] bounds_iterator
{
public:
static const std::size_t rank = IndexType::rank;
using iterator_category = std::random_access_iterator_tag;
@@ -851,8 +910,10 @@ public:
constexpr pointer operator->() const noexcept { return &curr_; }
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
constexpr bounds_iterator& operator++() noexcept
{
@@ -877,7 +938,9 @@ public:
return ret;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr bounds_iterator& operator--()
{
if (!less(curr_, boundary_))
@@ -914,7 +977,9 @@ public:
return ret += n;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr bounds_iterator& operator+=(difference_type n)
{
auto linear_idx = linearize(curr_) + n;
@@ -964,15 +1029,17 @@ public:
constexpr bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); }
void swap(bounds_iterator & rhs) noexcept
void swap(bounds_iterator& rhs) noexcept
{
std::swap(boundary_, rhs.boundary_);
std::swap(curr_, rhs.curr_);
}
private:
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
constexpr bool less(index_type & one, index_type & other) const noexcept
// clang-format on
constexpr bool less(index_type& one, index_type& other) const noexcept
{
for (std::size_t i = 0; i < rank; ++i)
{
@@ -981,7 +1048,9 @@ private:
return false;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr index_size_type linearize(const value_type& idx) const noexcept
{
// TODO: Smarter impl.
@@ -1043,8 +1112,10 @@ namespace details
stride[Bounds::rank - 1] = 1;
for (std::size_t i = 1; i < Bounds::rank; ++i)
{
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
stride[Bounds::rank - i - 1] = stride[Bounds::rank - i] * extents[Bounds::rank - i];
}
return {stride};
@@ -1098,10 +1169,12 @@ constexpr dim_t<N> dim(std::ptrdiff_t n) noexcept
template <typename ValueType, std::ptrdiff_t FirstDimension = dynamic_range,
std::ptrdiff_t... RestDimensions>
class [[deprecated("gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span;
class [[deprecated(
"gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span;
template <typename ValueType, std::size_t Rank>
class [[deprecated("gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span;
class [[deprecated(
"gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span;
namespace details
{
@@ -1188,8 +1261,8 @@ namespace details
};
template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
struct [[deprecated]] is_multi_span_oracle<multi_span<ValueType, FirstDimension, RestDimensions...>>
: std::true_type
struct [[deprecated]] is_multi_span_oracle<
multi_span<ValueType, FirstDimension, RestDimensions...>> : std::true_type
{
};
@@ -1205,7 +1278,9 @@ namespace details
} // namespace details
template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
class [[deprecated("gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span {
class [[deprecated(
"gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span
{
// TODO do we still need this?
template <typename ValueType2, std::ptrdiff_t FirstDimension2,
std::ptrdiff_t... RestDimensions2>
@@ -1237,7 +1312,9 @@ private:
public:
// default constructor - same as constructing from nullptr_t
// clang-format off
GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
constexpr multi_span() noexcept : multi_span(nullptr, bounds_type{})
{
static_assert(bounds_type::dynamic_rank != 0 ||
@@ -1247,7 +1324,9 @@ public:
}
// construct from nullptr - get an empty multi_span
// clang-format off
GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
constexpr multi_span(std::nullptr_t) noexcept : multi_span(nullptr, bounds_type{})
{
static_assert(bounds_type::dynamic_rank != 0 ||
@@ -1271,7 +1350,9 @@ public:
// construct from a single element
// clang-format off
GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
constexpr multi_span(reference data) noexcept : multi_span(&data, bounds_type{1})
{
static_assert(bounds_type::dynamic_rank > 0 || bounds_type::static_size == 0 ||
@@ -1284,7 +1365,9 @@ public:
constexpr multi_span(value_type &&) = delete;
// construct from pointer + length
// clang-format off
GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
constexpr multi_span(pointer ptr, size_type size) : multi_span(ptr, bounds_type{size}) {}
// construct from pointer + length - multidimensional
@@ -1521,7 +1604,9 @@ public:
return this->operator[](idx);
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr reference operator[](const index_type& idx) const
{
return data_[bounds_.linearize(idx)];
@@ -1529,7 +1614,9 @@ public:
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr Ret operator[](size_type idx) const
{
Expects(idx >= 0 && idx < bounds_.size()); // index is out of bounds of the array
@@ -1544,7 +1631,9 @@ public:
constexpr iterator end() const noexcept { return iterator{this, false}; }
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
constexpr const_iterator cbegin() const noexcept
{
return const_iterator{reinterpret_cast<const const_span*>(this), true};
@@ -1642,8 +1731,7 @@ constexpr auto as_multi_span(SpanType s, Dimensions2... dims)
// convert a multi_span<T> to a multi_span<const byte>
template <typename U, std::ptrdiff_t... Dimensions>
multi_span<const byte, dynamic_range>
as_bytes(multi_span<U, Dimensions...> s) noexcept
multi_span<const byte, dynamic_range> as_bytes(multi_span<U, Dimensions...> s) noexcept
{
static_assert(std::is_trivial<std::decay_t<U>>::value,
"The value_type of multi_span must be a trivial type.");
@@ -1729,8 +1817,7 @@ constexpr auto as_multi_span(T* arr, std::ptrdiff_t len) ->
}
template <typename T, std::size_t N>
constexpr auto as_multi_span(T (&arr)[N]) ->
typename details::SpanArrayTraits<T, N>::type
constexpr auto as_multi_span(T (&arr)[N]) -> typename details::SpanArrayTraits<T, N>::type
{
return {arr};
}
@@ -1772,7 +1859,9 @@ constexpr auto as_multi_span(Cont&& arr) -> std::enable_if_t<
// from basic_string which doesn't have nonconst .data() member like other contiguous containers
template <typename CharT, typename Traits, typename Allocator>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr auto as_multi_span(std::basic_string<CharT, Traits, Allocator>& str)
-> multi_span<CharT, dynamic_range>
{
@@ -1783,7 +1872,8 @@ constexpr auto as_multi_span(std::basic_string<CharT, Traits, Allocator>& str)
// strided_span is an extension that is not strictly part of the GSL at this time.
// It is kept here while the multidimensional interface is still being defined.
template <typename ValueType, std::size_t Rank>
class [[deprecated("gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span
class [[deprecated(
"gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span
{
public:
using bounds_type = strided_bounds<Rank>;
@@ -1818,13 +1908,15 @@ public:
Expects((bounds_.size() > 0 && ptr != nullptr) || bounds_.size() == 0);
// Bounds cross data boundaries
Expects(this->bounds().total_size() <= size);
// clang-format off
GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
(void) size;
}
// from static array of size N
template <size_type N>
constexpr strided_span(value_type (&values)[N], bounds_type bounds)
constexpr strided_span(value_type(&values)[N], bounds_type bounds)
: strided_span(values, N, std::move(bounds))
{}
@@ -1839,7 +1931,7 @@ public:
// convertible
template <typename OtherValueType, typename = std::enable_if_t<std::is_convertible<
OtherValueType (*)[], value_type (*)[]>::value>>
OtherValueType(*)[], value_type(*)[]>::value>>
constexpr strided_span(const strided_span<OtherValueType, Rank>& other)
: data_(other.data_), bounds_(other.bounds_)
{}
@@ -1858,7 +1950,9 @@ public:
const size_type size = this->bounds().total_size() / d;
// clang-format off
GSL_SUPPRESS(type.3) // NO-FORMAT: attribute
// clang-format on
return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())),
size,
bounds_type{resize_extent(this->bounds().index_bounds(), d),
@@ -1872,14 +1966,18 @@ public:
bounds_type{extents, details::make_stride(bounds())}};
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr reference operator[](const index_type& idx) const
{
return data_[bounds_.linearize(idx)];
}
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr Ret operator[](size_type idx) const
{
Expects(idx < bounds_.size()); // index is out of bounds of the array
@@ -1983,7 +2081,9 @@ private:
static index_type resize_extent(const index_type& extent, std::ptrdiff_t d)
{
// The last dimension of the array needs to contain a multiple of new type elements
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
Expects(extent[Rank - 1] >= d && (extent[Rank - 1] % d == 0));
index_type ret = extent;
@@ -1996,14 +2096,18 @@ private:
static index_type resize_stride(const index_type& strides, std::ptrdiff_t, void* = nullptr)
{
// Only strided arrays with regular strides can be resized
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
Expects(strides[Rank - 1] == 1);
return strides;
}
template <bool Enabled = (Rank > 1), typename = std::enable_if_t<Enabled>>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
static index_type resize_stride(const index_type& strides, std::ptrdiff_t d)
{
// Only strided arrays with regular strides can be resized
@@ -2026,7 +2130,8 @@ private:
};
template <class Span>
class [[deprecated]] contiguous_span_iterator {
class [[deprecated]] contiguous_span_iterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = typename Span::value_type;
@@ -2041,14 +2146,18 @@ private:
pointer data_;
const Span* m_validator;
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
void validateThis() const
{
// iterator is out of range of the array
Expects(data_ >= m_validator->data_ && data_ < m_validator->data_ + m_validator->size());
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
contiguous_span_iterator(const Span* container, bool isbegin)
: data_(isbegin ? container->data_ : container->data_ + container->size())
, m_validator(container)
@@ -2066,7 +2175,9 @@ public:
return data_;
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
contiguous_span_iterator& operator++() noexcept
{
++data_;
@@ -2079,7 +2190,9 @@ public:
return ret;
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
contiguous_span_iterator& operator--() noexcept
{
--data_;
@@ -2132,7 +2245,7 @@ public:
bool operator>(const contiguous_span_iterator& rhs) const { return rhs < *this; }
bool operator>=(const contiguous_span_iterator& rhs) const { return !(rhs > *this); }
void swap(contiguous_span_iterator & rhs) noexcept
void swap(contiguous_span_iterator& rhs) noexcept
{
std::swap(data_, rhs.data_);
std::swap(m_validator, rhs.m_validator);
@@ -2147,7 +2260,8 @@ contiguous_span_iterator<Span> operator+(typename contiguous_span_iterator<Span>
}
template <typename Span>
class [[deprecated]] general_span_iterator {
class [[deprecated]] general_span_iterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = typename Span::value_type;
@@ -2213,7 +2327,9 @@ public:
return m_itr - rhs.m_itr;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
value_type operator[](difference_type n) const { return (*m_container)[m_itr[n]]; }
bool operator==(const general_span_iterator& rhs) const
@@ -2230,7 +2346,7 @@ public:
bool operator<=(const general_span_iterator& rhs) const { return !(rhs < *this); }
bool operator>(const general_span_iterator& rhs) const { return rhs < *this; }
bool operator>=(const general_span_iterator& rhs) const { return !(rhs > *this); }
void swap(general_span_iterator & rhs) noexcept
void swap(general_span_iterator& rhs) noexcept
{
std::swap(m_itr, rhs.m_itr);
std::swap(m_container, rhs.m_container);
+49
View File
@@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_NARROW_H
#define GSL_NARROW_H
#include <gsl/assert> // for contracts
#include <gsl/util> // for narrow_cast
namespace gsl
{
struct narrowing_error : public std::exception
{
const char* what() const noexcept override { return "narrowing_error"; }
};
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
// clang-format on
constexpr T narrow(U u) noexcept(false)
{
constexpr const bool is_different_signedness =
(std::is_signed<T>::value != std::is_signed<U>::value);
const T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u || (is_different_signedness && ((t < T{}) != (u < U{}))))
{
throw narrowing_error{};
}
return t;
}
} // namespace gsl
#endif // GSL_NARROW_H
+53 -32
View File
@@ -17,27 +17,32 @@
#ifndef GSL_POINTERS_H
#define GSL_POINTERS_H
#include <gsl/gsl_assert> // for Ensures, Expects
#include <gsl/assert> // for contracts
#include <algorithm> // for forward
#include <iosfwd> // for ptrdiff_t, nullptr_t, ostream, size_t
#include <cstddef> // for ptrdiff_t, nullptr_t, size_t
#include <memory> // for shared_ptr, unique_ptr
#include <system_error> // for hash
#include <type_traits> // for enable_if_t, is_convertible, is_assignable
#if !defined(GSL_NO_IOSTREAMS)
#include <iosfwd> // for ostream
#endif // !defined(GSL_NO_IOSTREAMS)
namespace gsl
{
//
// GSL.owner: ownership pointers
//
using std::unique_ptr;
using std::shared_ptr;
using std::unique_ptr;
//
// owner
//
// owner<T> is designed as a bridge for code that must deal directly with owning pointers for some reason
// owner<T> is designed as a bridge for code that must deal directly with owning pointers for some
// reason
//
// T must be a pointer type
// - disallow construction from any type other than pointer type
@@ -63,30 +68,30 @@ template <class T>
class not_null
{
public:
static_assert(std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value, "T cannot be compared to nullptr.");
static_assert(std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value,
"T cannot be compared to nullptr.");
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
{
Expects(ptr_ != nullptr);
Expects(ptr_ != nullptr, Null);
}
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr not_null(T u) : ptr_(std::move(u))
{
Expects(ptr_ != nullptr);
Expects(ptr_ != nullptr, Null);
}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(const not_null<U>& other) : not_null(other.get())
{
}
{}
not_null(const not_null& other) = default;
not_null& operator=(const not_null& other) = default;
constexpr std::conditional_t<std::is_copy_constructible<T>::value, T, const T&> get() const
{
Ensures(ptr_ != nullptr);
Ensures(ptr_ != nullptr, Null);
return ptr_;
}
@@ -112,49 +117,64 @@ private:
};
template <class T>
auto make_not_null(T&& t) noexcept {
auto make_not_null(T&& t) noexcept
{
return not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}
#if !defined(GSL_NO_IOSTREAMS)
template <class T>
std::ostream& operator<<(std::ostream& os, const not_null<T>& val)
{
os << val.get();
return os;
}
#endif // !defined(GSL_NO_IOSTREAMS)
template <class T, class U>
auto operator==(const not_null<T>& lhs, const not_null<U>& rhs) noexcept(noexcept(lhs.get() == rhs.get())) -> decltype(lhs.get() == rhs.get())
auto operator==(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() == rhs.get()))
-> decltype(lhs.get() == rhs.get())
{
return lhs.get() == rhs.get();
}
template <class T, class U>
auto operator!=(const not_null<T>& lhs, const not_null<U>& rhs) noexcept(noexcept(lhs.get() != rhs.get())) -> decltype(lhs.get() != rhs.get())
auto operator!=(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() != rhs.get()))
-> decltype(lhs.get() != rhs.get())
{
return lhs.get() != rhs.get();
}
template <class T, class U>
auto operator<(const not_null<T>& lhs, const not_null<U>& rhs) noexcept(noexcept(lhs.get() < rhs.get())) -> decltype(lhs.get() < rhs.get())
auto operator<(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() < rhs.get()))
-> decltype(lhs.get() < rhs.get())
{
return lhs.get() < rhs.get();
}
template <class T, class U>
auto operator<=(const not_null<T>& lhs, const not_null<U>& rhs) noexcept(noexcept(lhs.get() <= rhs.get())) -> decltype(lhs.get() <= rhs.get())
auto operator<=(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() <= rhs.get()))
-> decltype(lhs.get() <= rhs.get())
{
return lhs.get() <= rhs.get();
}
template <class T, class U>
auto operator>(const not_null<T>& lhs, const not_null<U>& rhs) noexcept(noexcept(lhs.get() > rhs.get())) -> decltype(lhs.get() > rhs.get())
auto operator>(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() > rhs.get()))
-> decltype(lhs.get() > rhs.get())
{
return lhs.get() > rhs.get();
}
template <class T, class U>
auto operator>=(const not_null<T>& lhs, const not_null<U>& rhs) noexcept(noexcept(lhs.get() >= rhs.get())) -> decltype(lhs.get() >= rhs.get())
auto operator>=(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() >= rhs.get()))
-> decltype(lhs.get() >= rhs.get())
{
return lhs.get() >= rhs.get();
}
@@ -202,28 +222,23 @@ namespace gsl
// - remove unnecessary asserts
//
template <class T>
class strict_not_null: public not_null<T>
class strict_not_null : public not_null<T>
{
public:
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr explicit strict_not_null(U&& u) :
not_null<T>(std::forward<U>(u))
constexpr explicit strict_not_null(U&& u) : not_null<T>(std::forward<U>(u))
{}
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr explicit strict_not_null(T u) :
not_null<T>(u)
constexpr explicit strict_not_null(T u) : not_null<T>(u)
{}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr strict_not_null(const not_null<U>& other) :
not_null<T>(other)
constexpr strict_not_null(const not_null<U>& other) : not_null<T>(other)
{}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr strict_not_null(const strict_not_null<U>& other) :
not_null<T>(other)
constexpr strict_not_null(const strict_not_null<U>& other) : not_null<T>(other)
{}
strict_not_null(strict_not_null&& other) = default;
@@ -260,15 +275,18 @@ template <class T>
strict_not_null<T> operator+(std::ptrdiff_t, const strict_not_null<T>&) = delete;
template <class T>
auto make_strict_not_null(T&& t) noexcept {
auto make_strict_not_null(T&& t) noexcept
{
return strict_not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}
#if ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
// deduction guides to prevent the ctad-maybe-unsupported warning
template <class T> not_null(T) -> not_null<T>;
template <class T> strict_not_null(T) -> strict_not_null<T>;
template <class T>
not_null(T) -> not_null<T>;
template <class T>
strict_not_null(T) -> strict_not_null<T>;
#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
@@ -279,7 +297,10 @@ namespace std
template <class T>
struct hash<gsl::strict_not_null<T>>
{
std::size_t operator()(const gsl::strict_not_null<T>& value) const { return hash<T>{}(value.get()); }
std::size_t operator()(const gsl::strict_not_null<T>& value) const
{
return hash<T>{}(value.get());
}
};
} // namespace std
+108 -99
View File
@@ -17,9 +17,9 @@
#ifndef GSL_SPAN_H
#define GSL_SPAN_H
#include <gsl/gsl_assert> // for Expects
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/assert> // for contracts
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#include <array> // for array
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
@@ -29,7 +29,7 @@
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
// turn off some warnings that are noisy about our Expects statements
// turn off some warnings that are noisy about our contract checks
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning( \
disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
@@ -137,21 +137,24 @@ namespace details
constexpr reference operator*() const noexcept
{
Expects(begin_ && end_);
Expects(begin_ <= current_ && current_ < end_);
Expects(begin_ && end_, Bounds);
Expects(begin_ <= current_ && current_ < end_, Bounds);
return *current_;
}
constexpr pointer operator->() const noexcept
{
Expects(begin_ && end_);
Expects(begin_ <= current_ && current_ < end_);
Expects(begin_ && end_, Bounds);
Expects(begin_ <= current_ && current_ < end_, Bounds);
return current_;
}
constexpr span_iterator& operator++() noexcept
{
Expects(begin_ && current_ && end_);
Expects(current_ < end_);
Expects(begin_ && current_ && end_, Bounds);
Expects(current_ < end_, Bounds);
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
++current_;
return *this;
}
@@ -165,8 +168,8 @@ namespace details
constexpr span_iterator& operator--() noexcept
{
Expects(begin_ && end_);
Expects(begin_ < current_);
Expects(begin_ && end_, Bounds);
Expects(begin_ < current_, Bounds);
--current_;
return *this;
}
@@ -180,9 +183,12 @@ namespace details
constexpr span_iterator& operator+=(const difference_type n) noexcept
{
if (n != 0) Expects(begin_ && current_ && end_);
if (n > 0) Expects(end_ - current_ >= n);
if (n < 0) Expects(current_ - begin_ >= -n);
if (n != 0) Expects(begin_ && current_ && end_, Bounds);
if (n > 0) Expects(end_ - current_ >= n, Bounds);
if (n < 0) Expects(current_ - begin_ >= -n, Bounds);
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
current_ += n;
return *this;
}
@@ -202,9 +208,9 @@ namespace details
constexpr span_iterator& operator-=(const difference_type n) noexcept
{
if (n != 0) Expects(begin_ && current_ && end_);
if (n > 0) Expects(current_ - begin_ >= n);
if (n < 0) Expects(end_ - current_ >= -n);
if (n != 0) Expects(begin_ && current_ && end_, Bounds);
if (n > 0) Expects(current_ - begin_ >= n, Bounds);
if (n < 0) Expects(end_ - current_ >= -n, Bounds);
current_ -= n;
return *this;
}
@@ -221,7 +227,7 @@ namespace details
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
constexpr difference_type operator-(const span_iterator<Type2>& rhs) const noexcept
{
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
Expects(begin_ == rhs.begin_ && end_ == rhs.end_, Bounds);
return current_ - rhs.current_;
}
@@ -235,7 +241,7 @@ namespace details
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
constexpr bool operator==(const span_iterator<Type2>& rhs) const noexcept
{
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
Expects(begin_ == rhs.begin_ && end_ == rhs.end_, Bounds);
return current_ == rhs.current_;
}
@@ -252,7 +258,7 @@ namespace details
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
constexpr bool operator<(const span_iterator<Type2>& rhs) const noexcept
{
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
Expects(begin_ == rhs.begin_ && end_ == rhs.end_, Bounds);
return current_ < rhs.current_;
}
@@ -288,14 +294,14 @@ namespace details
{ // test that [lhs, rhs) forms a valid range inside an STL algorithm
Expects(lhs.begin_ == rhs.begin_ // range spans have to match
&& lhs.end_ == rhs.end_ &&
lhs.current_ <= rhs.current_); // range must not be transposed
lhs.current_ <= rhs.current_, Bounds); // range must not be transposed
}
constexpr void _Verify_offset(const difference_type n) const noexcept
{ // test that *this + n is within the range of this call
if (n != 0) Expects(begin_ && current_ && end_);
if (n > 0) Expects(end_ - current_ >= n);
if (n < 0) Expects(current_ - begin_ >= -n);
if (n != 0) Expects(begin_ && current_ && end_, Bounds);
if (n > 0) Expects(end_ - current_ >= n, Bounds);
if (n < 0) Expects(current_ - begin_ >= -n, Bounds);
}
// clang-format off
@@ -340,7 +346,7 @@ namespace details
constexpr explicit extent_type(extent_type<dynamic_extent>);
constexpr explicit extent_type(size_type size) { Expects(size == Ext); }
constexpr explicit extent_type(size_type size) { Expects(size == Ext, Bounds); }
constexpr size_type size() const noexcept { return Ext; }
@@ -364,7 +370,7 @@ namespace details
constexpr explicit extent_type(size_type size) : size_(size)
{
Expects(size != dynamic_extent);
Expects(size != dynamic_extent, Bounds);
}
constexpr size_type size() const noexcept { return size_; }
@@ -376,7 +382,7 @@ namespace details
template <std::size_t Ext>
constexpr extent_type<Ext>::extent_type(extent_type<dynamic_extent> ext)
{
Expects(ext.size() == Ext);
Expects(ext.size() == Ext, Bounds);
}
template <class ElementType, std::size_t Extent, std::size_t Offset, std::size_t Count>
@@ -425,7 +431,7 @@ public:
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != dynamic_extent, int> = 0>
constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
{
Expects(count == Extent);
Expects(count == Extent, Bounds);
}
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == dynamic_extent, int> = 0>
@@ -436,7 +442,7 @@ public:
constexpr explicit span(pointer firstElem, pointer lastElem) noexcept
: storage_(firstElem, narrow_cast<std::size_t>(lastElem - firstElem))
{
Expects(lastElem - firstElem == static_cast<difference_type>(Extent));
Expects(lastElem - firstElem == static_cast<difference_type>(Extent), Bounds);
}
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == dynamic_extent, int> = 0>
@@ -447,7 +453,7 @@ public:
template <std::size_t N,
std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0>
constexpr span(element_type (&arr)[N]) noexcept
: storage_(KnownNotNull{arr + 0}, details::extent_type<N>())
: storage_(KnownNotNull{arr}, details::extent_type<N>())
{}
template <
@@ -472,66 +478,70 @@ public:
// requirement on Container to be a contiguous sequence container.
template <std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent != dynamic_extent &&
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
element_type (*)[]>::value, int> = 0>
MyExtent != dynamic_extent && !details::is_span<Container>::value &&
!details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
element_type (*)[]>::value,
int> = 0>
constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size())
{}
template <std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent == dynamic_extent &&
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
element_type (*)[]>::value, int> = 0>
MyExtent == dynamic_extent && !details::is_span<Container>::value &&
!details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
element_type (*)[]>::value,
int> = 0>
constexpr span(Container& cont) noexcept : span(cont.data(), cont.size())
{}
template <std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent != dynamic_extent &&
std::is_const<element_type>::value && !details::is_span<Container>::value &&
!details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
std::is_convertible<std::remove_pointer_t<
decltype(std::declval<const Container&>().data())> (*)[],
element_type (*)[]>::value, int> = 0>
template <
std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent != dynamic_extent && std::is_const<element_type>::value &&
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<const Container&>().data())> (*)[],
element_type (*)[]>::value,
int> = 0>
constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size())
{}
template <std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent == dynamic_extent &&
std::is_const<element_type>::value && !details::is_span<Container>::value &&
!details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
std::is_convertible<std::remove_pointer_t<
decltype(std::declval<const Container&>().data())> (*)[],
element_type (*)[]>::value, int> = 0>
template <
std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent == dynamic_extent && std::is_const<element_type>::value &&
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<const Container&>().data())> (*)[],
element_type (*)[]>::value,
int> = 0>
constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size())
{}
constexpr span(const span& other) noexcept = default;
template <
class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
std::enable_if_t<
(MyExtent == dynamic_extent || MyExtent == OtherExtent) &&
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value, int> = 0>
template <class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
std::enable_if_t<(MyExtent == dynamic_extent || MyExtent == OtherExtent) &&
details::is_allowed_element_type_conversion<OtherElementType,
element_type>::value,
int> = 0>
constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
{}
template <
class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
std::enable_if_t<
MyExtent != dynamic_extent && OtherExtent == dynamic_extent &&
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value, int> = 0>
template <class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
std::enable_if_t<MyExtent != dynamic_extent && OtherExtent == dynamic_extent &&
details::is_allowed_element_type_conversion<OtherElementType,
element_type>::value,
int> = 0>
constexpr explicit span(const span<OtherElementType, OtherExtent>& other) noexcept
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
{}
@@ -543,7 +553,7 @@ public:
template <std::size_t Count>
constexpr span<element_type, Count> first() const noexcept
{
Expects(Count <= size());
Expects(Count <= size(), Bounds);
return span<element_type, Count>{data(), Count};
}
@@ -553,7 +563,7 @@ public:
// clang-format on
constexpr span<element_type, Count> last() const noexcept
{
Expects(Count <= size());
Expects(Count <= size(), Bounds);
return span<element_type, Count>{data() + (size() - Count), Count};
}
@@ -564,26 +574,26 @@ public:
constexpr auto subspan() const noexcept ->
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
{
Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)));
using type = typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type;
Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)), Bounds);
using type =
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type;
return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
}
constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept
{
Expects(count <= size());
Expects(count <= size(), Bounds);
return {data(), count};
}
constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept
{
Expects(count <= size());
Expects(count <= size(), Bounds);
return make_subspan(size() - count, dynamic_extent, subspan_selector<Extent>{});
}
constexpr span<element_type, dynamic_extent> subspan(size_type offset,
size_type count = dynamic_extent) const
noexcept
constexpr span<element_type, dynamic_extent>
subspan(size_type offset, size_type count = dynamic_extent) const noexcept
{
return make_subspan(offset, count, subspan_selector<Extent>{});
}
@@ -593,7 +603,7 @@ public:
constexpr size_type size_bytes() const noexcept
{
Expects(size() < dynamic_extent / sizeof(element_type));
Expects(size() < dynamic_extent / sizeof(element_type), Bounds);
return size() * sizeof(element_type);
}
@@ -605,19 +615,19 @@ public:
// clang-format on
constexpr reference operator[](size_type idx) const noexcept
{
Expects(idx < size());
Expects(idx < size(), Bounds);
return data()[idx];
}
constexpr reference front() const noexcept
{
Expects(size() > 0);
Expects(size() > 0, Bounds);
return data()[0];
}
constexpr reference back() const noexcept
{
Expects(size() > 0);
Expects(size() > 0, Bounds);
return data()[size() - 1];
}
@@ -678,14 +688,14 @@ private:
constexpr storage_type(KnownNotNull data, OtherExtentType ext)
: ExtentType(ext), data_(data.p)
{
Expects(ExtentType::size() != dynamic_extent);
Expects(ExtentType::size() != dynamic_extent, Bounds);
}
template <class OtherExtentType>
constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
{
Expects(ExtentType::size() != dynamic_extent);
Expects(data || ExtentType::size() == 0);
Expects(ExtentType::size() != dynamic_extent, Bounds);
Expects(data || ExtentType::size() == 0, Bounds);
}
constexpr pointer data() const noexcept { return data_; }
@@ -706,9 +716,8 @@ private:
};
template <std::size_t CallerExtent>
constexpr span<element_type, dynamic_extent> make_subspan(size_type offset, size_type count,
subspan_selector<CallerExtent>) const
noexcept
constexpr span<element_type, dynamic_extent>
make_subspan(size_type offset, size_type count, subspan_selector<CallerExtent>) const noexcept
{
const span<element_type, dynamic_extent> tmp(*this);
return tmp.subspan(offset, count);
@@ -720,11 +729,11 @@ private:
constexpr span<element_type, dynamic_extent>
make_subspan(size_type offset, size_type count, subspan_selector<dynamic_extent>) const noexcept
{
Expects(size() >= offset);
Expects(size() >= offset, Bounds);
if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; }
Expects(size() - offset >= count);
Expects(size() - offset >= count, Bounds);
return {KnownNotNull{data() + offset}, count};
}
};
@@ -733,21 +742,21 @@ private:
// Deduction Guides
template <class Type, std::size_t Extent>
span(Type (&)[Extent])->span<Type, Extent>;
span(Type (&)[Extent]) -> span<Type, Extent>;
template <class Type, std::size_t Size>
span(std::array<Type, Size>&)->span<Type, Size>;
span(std::array<Type, Size>&) -> span<Type, Size>;
template <class Type, std::size_t Size>
span(const std::array<Type, Size>&)->span<const Type, Size>;
span(const std::array<Type, Size>&) -> span<const Type, Size>;
template <class Container,
class Element = std::remove_pointer_t<decltype(std::declval<Container&>().data())>>
span(Container&)->span<Element>;
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<const Container&>().data())>>
span(const Container&)->span<Element>;
class Element = std::remove_pointer_t<decltype(std::declval<const Container&>().data())>>
span(const Container&) -> span<Element>;
#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
+3 -4
View File
@@ -27,9 +27,8 @@
//
///////////////////////////////////////////////////////////////////////////////
#include <gsl/gsl_util> // for narrow_cast, narrow
#include <gsl/span> // for span
#include <gsl/span> // for span
#include <gsl/util> // for narrow_cast, narrow
#include <algorithm> // for lexicographical_compare
#include <cstddef> // for ptrdiff_t, size_t
@@ -125,7 +124,7 @@ template <class ElementType, std::size_t Extent>
constexpr ElementType& at(span<ElementType, Extent> s, index i)
{
// No bounds checking here because it is done in span::operator[] called below
Ensures(i >= 0);
Ensures(i >= 0, Bounds);
return s[narrow_cast<std::size_t>(i)];
}
+20 -38
View File
@@ -17,9 +17,9 @@
#ifndef GSL_STRING_SPAN_H
#define GSL_STRING_SPAN_H
#include <gsl/gsl_assert> // for Ensures, Expects
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/span_ext> // for operator!=, operator==, dynamic_extent
#include <gsl/assert> // for contracts
#include <gsl/span_ext> // for operator!=, operator==, dynamic_extent
#include <gsl/util> // for narrow_cast
#include <algorithm> // for equal, lexicographical_compare
#include <array> // for array
@@ -57,48 +57,31 @@ namespace gsl
//
template <typename CharT, std::size_t Extent = dynamic_extent>
using basic_zstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] = CharT*;
using basic_zstring = CharT*;
template <std::size_t Extent = dynamic_extent>
using czstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring<const char, Extent>;
using czstring = basic_zstring<const char, Extent>;
template <std::size_t Extent = dynamic_extent>
using cwzstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring<const wchar_t, Extent>;
using cwzstring = basic_zstring<const wchar_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using cu16zstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring<const char16_t, Extent>;
using cu16zstring = basic_zstring<const char16_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using cu32zstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring<const char32_t, Extent>;
using cu32zstring = basic_zstring<const char32_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using zstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring<char, Extent>;
using zstring = basic_zstring<char, Extent>;
template <std::size_t Extent = dynamic_extent>
using wzstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring<wchar_t, Extent>;
using wzstring = basic_zstring<wchar_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using u16zstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring<char16_t, Extent>;
using u16zstring = basic_zstring<char16_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using u32zstring [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring<char32_t, Extent>;
using u32zstring = basic_zstring<char32_t, Extent>;
namespace details
{
@@ -131,19 +114,19 @@ template <typename T, const T Sentinel>
"isocpp/CppCoreGuidelines PR#1680")]] constexpr span<T, dynamic_extent>
ensure_sentinel(T* seq, std::size_t max = static_cast<std::size_t>(-1))
{
Ensures(seq != nullptr);
Ensures(seq != nullptr, Null);
// clang-format off
GSL_SUPPRESS(f.23) // TODO: false positive // TODO: suppress does not work
// clang-format on
auto cur = seq;
Ensures(cur != nullptr); // workaround for removing the warning
Ensures(cur != nullptr, Null); // workaround for removing the warning
// clang-format off
GSL_SUPPRESS(bounds.1) // TODO: suppress does not work
// clang-format on
while (static_cast<std::size_t>(cur - seq) < max && *cur != Sentinel) ++cur;
Ensures(*cur == Sentinel);
Ensures(*cur == Sentinel, Bounds);
return {seq, static_cast<std::size_t>(cur - seq)};
}
@@ -184,10 +167,9 @@ class [[deprecated("string_span was removed from the C++ Core Guidelines. For mo
namespace details
{
template <typename T>
struct [
[deprecated("string_span was removed from the C++ Core Guidelines. For more information, "
"see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle
: std::false_type{};
struct [[deprecated(
"string_span was removed from the C++ Core Guidelines. For more information, "
"see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle : std::false_type{};
template <typename CharT, std::size_t Extent>
struct [[deprecated(
@@ -455,8 +437,8 @@ public:
constexpr basic_zstring_span(impl_type s) : span_(s)
{
// expects a zero-terminated span
Expects(s.size() > 0);
Expects(s[s.size() - 1] == value_type{});
Expects(s.size() > 0, Bounds);
Expects(s[s.size() - 1] == value_type{}, Bounds);
}
// copy
+145
View File
@@ -0,0 +1,145 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_UTIL_H
#define GSL_UTIL_H
#include <gsl/assert> // for contracts
#include <array>
#include <cstddef> // for ptrdiff_t, size_t
#include <initializer_list> // for initializer_list
#include <type_traits> // for is_signed, integral_constant
#include <utility> // for exchange, forward
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#endif // _MSC_VER
#if defined(__cplusplus) && (__cplusplus >= 201703L)
#define GSL_NODISCARD [[nodiscard]]
#else
#define GSL_NODISCARD
#endif // defined(__cplusplus) && (__cplusplus >= 201703L)
namespace gsl
{
//
// GSL.util: utilities
//
// index type for all container indexes/subscripts/sizes
using index = std::ptrdiff_t;
// final_action allows you to ensure something gets run at the end of a scope
template <class F>
class final_action
{
public:
static_assert(!std::is_reference<F>::value && !std::is_const<F>::value &&
!std::is_volatile<F>::value,
"Final_action should store its callable by value");
explicit final_action(F f) noexcept : f_(std::move(f)) {}
final_action(final_action&& other) noexcept
: f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false))
{}
final_action(const final_action&) = delete;
final_action& operator=(const final_action&) = delete;
final_action& operator=(final_action&&) = delete;
// clang-format off
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
// clang-format on
~final_action() noexcept
{
if (invoke_) f_();
}
private:
F f_;
bool invoke_{true};
};
// finally() - convenience function to generate a final_action
template <class F>
GSL_NODISCARD final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>
finally(F&& f) noexcept
{
return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(
std::forward<F>(f));
}
// narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
constexpr T narrow_cast(U&& u) noexcept
{
return static_cast<T>(std::forward<U>(u));
}
//
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
//
template <class T, std::size_t N>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
constexpr T& at(T (&arr)[N], const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(N), Bounds);
return arr[narrow_cast<std::size_t>(i)];
}
template <class Cont>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()), Bounds);
using size_type = decltype(cont.size());
return cont[narrow_cast<size_type>(i)];
}
template <class T>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr T at(const std::initializer_list<T> cont, const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()), Bounds);
return *(cont.begin() + i);
}
} // namespace gsl
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_UTIL_H
+26
View File
@@ -0,0 +1,26 @@
parameters:
jobName: ''
imageName: ''
jobs:
- job:
displayName: ${{ parameters.imageName }}
pool:
vmImage: ${{ parameters.imageName }}
strategy:
matrix:
14_debug:
GSL_CXX_STANDARD: '14'
BUILD_TYPE: 'Debug'
14_release:
GSL_CXX_STANDARD: '14'
BUILD_TYPE: 'Release'
17_debug:
GSL_CXX_STANDARD: '17'
BUILD_TYPE: 'Debug'
17_release:
GSL_CXX_STANDARD: '17'
BUILD_TYPE: 'Release'
continueOnError: false
steps:
- template: ./steps.yml
+17
View File
@@ -0,0 +1,17 @@
steps:
- task: CMake@1
name: Configure
inputs:
workingDirectory: build
cmakeArgs: '-DCMAKE_CXX_STANDARD=$(GSL_CXX_STANDARD) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) .. '
- task: CMake@1
name: Build
inputs:
workingDirectory: build
cmakeArgs: '--build . '
- script: ctest . --output-on-failure --no-compress-output
name: CTest
workingDirectory: build
failOnStderr: true
+8 -2
View File
@@ -78,6 +78,7 @@ if(MSVC) # MSVC or simulating MSVC
-Wno-shift-sign-overflow # GTest gtest-port.h
-Wno-undef # GTest
-Wno-used-but-marked-unused # GTest EXPECT_DEATH
-Wno-global-constructors
$<$<EQUAL:${GSL_CXX_STANDARD},14>: # no support for [[maybe_unused]]
-Wno-unused-member-function
-Wno-unused-variable
@@ -109,6 +110,7 @@ else()
-Wno-unknown-attributes
-Wno-used-but-marked-unused # GTest EXPECT_DEATH
-Wno-weak-vtables
-Wno-global-constructors
$<$<EQUAL:${GSL_CXX_STANDARD},14>: # no support for [[maybe_unused]]
-Wno-unused-member-function
-Wno-unused-variable
@@ -130,7 +132,8 @@ else()
$<$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,6>>:
-Wduplicated-cond # duplicated if-else conditions
-Wmisleading-indentation
-Wnull-dereference
-Wno-null-dereference
-Wno-array-bounds
$<$<EQUAL:${GSL_CXX_STANDARD},14>: # no support for [[maybe_unused]]
-Wno-unused-variable
>
@@ -212,6 +215,7 @@ if(MSVC) # MSVC or simulating MSVC
-Wno-c++98-compat-pedantic
-Wno-missing-prototypes
-Wno-unknown-attributes
-Wno-global-constructors
>
)
else()
@@ -234,6 +238,7 @@ else()
-Wno-missing-prototypes
-Wno-unknown-attributes
-Wno-weak-vtables
-Wno-global-constructors
>
$<$<CXX_COMPILER_ID:GNU>:
-Wdouble-promotion # float implicit to double
@@ -242,7 +247,8 @@ else()
$<$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,6>>:
-Wduplicated-cond # duplicated if-else conditions
-Wmisleading-indentation
-Wnull-dereference
-Wno-null-dereference
-Wno-array-bounds
>
$<$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,7>>:
-Wduplicated-branches # identical if-else branches
+1 -1
View File
@@ -15,7 +15,7 @@
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include <gsl/gsl_algorithm> // for copy
#include <gsl/algorithm> // for copy
#include <gsl/span> // for span
#include <array> // for array
#include <cstddef> // for size_t
+3 -3
View File
@@ -15,7 +15,7 @@
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include <gsl/gsl_assert> // for fail_fast (ptr only), Ensures, Expects
#include <gsl/assert> // for fail_fast (ptr only), contracts
using namespace gsl;
@@ -25,14 +25,14 @@ static constexpr char deathstring[] = "Expected Death";
int f(int i)
{
Expects(i > 0 && i < 10);
Expects(i > 0 && i < 10, Testing);
return i;
}
int g(int i)
{
i++;
Ensures(i > 0 && i < 10);
Ensures(i > 0 && i < 10, Testing);
return i;
}
} // namespace
+1 -1
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_util> // for at
#include <gsl/util> // for at
#include <array> // for array
#include <cstddef> // for size_t
+1 -1
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for to_byte, to_integer, byte, operator&, ope...
#include <gsl/byte> // for to_byte, to_integer, byte, operator&, ope...
using namespace std;
using namespace gsl;
+2 -2
View File
@@ -16,8 +16,8 @@
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#include <gsl/multi_span> // for multi_span, contiguous_span_iterator, dim
#include <algorithm> // for fill, for_each
+15
View File
@@ -533,3 +533,18 @@ TEST(notnull_tests, TestMakeNotNull)
}
#endif
}
TEST(notnull_tests, TestStdHash)
{
int x = 42;
int y = 99;
not_null<int*> nn{&x};
const not_null<int*> cnn{&x};
std::hash<not_null<int*>> hash_nn;
std::hash<int*> hash_intptr;
EXPECT_TRUE(hash_nn(nn) == hash_intptr(&x));
EXPECT_FALSE(hash_nn(nn) == hash_intptr(&y));
EXPECT_FALSE(hash_nn(nn) == hash_intptr(nullptr));
}
+1 -1
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/byte> // for byte
#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <array> // for array
+1 -1
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_util> // for narrow_cast, at
#include <gsl/util> // for narrow_cast, at
#include <gsl/span_ext> // for operator==, operator!=, make_span
#include <array> // for array
+2 -2
View File
@@ -16,8 +16,8 @@
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast, at
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast, at
#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <array> // for array
+2 -2
View File
@@ -15,8 +15,8 @@
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#include <gsl/multi_span> // for strided_span, index, multi_span, strided_...
#include <iostream> // for size_t
+5 -5
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_assert> // for Expects, fail_fast (ptr only)
#include <gsl/assert> // for contracts, fail_fast (ptr only)
#include <gsl/pointers> // for owner
#include <gsl/span> // for span, dynamic_extent
#include <gsl/string_span> // for basic_string_span, operator==, ensure_z
@@ -82,7 +82,7 @@ void use(basic_string_span<T, gsl::dynamic_extent>)
czstring_span<> CreateTempName(string_span<> span)
{
Expects(span.size() > 1);
Expects(span.size() > 1, Testing);
std::size_t last = 0;
if (span.size() > 4) {
@@ -99,7 +99,7 @@ czstring_span<> CreateTempName(string_span<> span)
cwzstring_span<> CreateTempNameW(wstring_span<> span)
{
Expects(span.size() > 1);
Expects(span.size() > 1, Testing);
std::size_t last = 0;
if (span.size() > 4) {
@@ -116,7 +116,7 @@ cwzstring_span<> CreateTempNameW(wstring_span<> span)
cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
{
Expects(span.size() > 1);
Expects(span.size() > 1, Testing);
std::size_t last = 0;
if (span.size() > 4) {
@@ -133,7 +133,7 @@ cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
cu32zstring_span<> CreateTempNameU32(u32string_span<> span)
{
Expects(span.size() > 1);
Expects(span.size() > 1, Testing);
std::size_t last = 0;
if (span.size() > 4) {
+2 -2
View File
@@ -16,8 +16,8 @@
#include <gtest/gtest.h>
#include <gsl/gsl_util> // finally, narrow_cast
#include <gsl/gsl_narrow> // for narrow, narrowing_error
#include <gsl/util> // finally, narrow_cast
#include <gsl/narrow> // for narrow, narrowing_error
#include <algorithm> // for move
#include <functional> // for reference_wrapper, _Bind_helper<>::type
#include <limits> // for numeric_limits