forked from microsoft/GSL
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95a32d75a2 | |||
| ed762459cf | |||
| 2b9f1033aa | |||
| 3bdc037c23 | |||
| 5458cd79b3 | |||
| 84aeb59f26 | |||
| d9fa328f89 | |||
| d0052f6320 | |||
| 3b3478eaf8 | |||
| e427b02c89 | |||
| 25bb4bd948 | |||
| 1c509ad8e1 | |||
| eca0eca6f1 | |||
| a47352cb2a | |||
| d15cb5fdbe | |||
| a6cef6bc6c | |||
| ec6cd75d57 | |||
| 0140ab1d73 | |||
| 475b785d2c | |||
| 959ce58bbc | |||
| 804a14fe8b | |||
| 00d4a5aab6 | |||
| 9150ce9a95 | |||
| a150aaa4ed | |||
| e8978c01ab | |||
| 2c3ab0211c | |||
| 179fba51f5 | |||
| d74ae54b60 | |||
| b6c57e2403 | |||
| 736b62a838 |
@@ -1,9 +1,9 @@
|
||||
name: CI_Android
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
Android:
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
echo "Emulator starting"
|
||||
|
||||
- name: Configure
|
||||
run: cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=16 -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Debug ..
|
||||
run: cmake -Werror=dev -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=16 -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Debug ..
|
||||
|
||||
- name: Build
|
||||
run: cmake --build . --parallel
|
||||
@@ -47,4 +47,4 @@ jobs:
|
||||
adb shell find /data/local/tmp/tests -maxdepth 1 -exec chmod +x {} \\\;
|
||||
|
||||
- name: Test
|
||||
run: adb shell find /data/local/tmp/tests -name "*_tests" -maxdepth 1 -exec {} \\\;
|
||||
run: adb shell find /data/local/tmp/tests -name "*_tests" -maxdepth 1 -exec {} \\\;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
name: CI_iOS
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
iOS:
|
||||
@@ -21,6 +21,7 @@ jobs:
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake \
|
||||
-Werror=dev \
|
||||
-GXcode \
|
||||
-DCMAKE_SYSTEM_NAME=iOS \
|
||||
"-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
|
||||
|
||||
+46
-112
@@ -1,127 +1,61 @@
|
||||
cmake_minimum_required(VERSION 3.1.3...3.16)
|
||||
|
||||
project(GSL VERSION 3.1.0 LANGUAGES CXX)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
include(guidelineSupportLibrary)
|
||||
|
||||
include(ExternalProject)
|
||||
find_package(Git)
|
||||
project(GSL
|
||||
VERSION 3.1.0
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
# Use GNUInstallDirs to provide the right locations on all platforms
|
||||
# Must include after the project call due to GNUInstallDirs requiring a language be enabled (IE. CXX)
|
||||
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
|
||||
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)
|
||||
|
||||
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()
|
||||
|
||||
# add definitions to the library and targets that consume it
|
||||
target_compile_definitions(GSL INTERFACE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:
|
||||
# remove unnecessary warnings about unchecked iterators
|
||||
_SCL_SECURE_NO_WARNINGS
|
||||
# remove deprecation warnings about std::uncaught_exception() (from catch)
|
||||
_SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING
|
||||
>
|
||||
)
|
||||
|
||||
# add include folders to the library and targets that consume it
|
||||
# the SYSTEM keyword suppresses warnings for users of the library
|
||||
if(GSL_STANDALONE_PROJECT)
|
||||
target_include_directories(GSL INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
else()
|
||||
target_include_directories(GSL SYSTEM INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.7.8)
|
||||
if (MSVC_IDE)
|
||||
option(GSL_VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE)
|
||||
else()
|
||||
set(GSL_VS_ADD_NATIVE_VISUALIZERS FALSE CACHE INTERNAL "Native visualizers are Visual Studio extension" FORCE)
|
||||
endif()
|
||||
|
||||
# add natvis file to the library so it will automatically be loaded into Visual Studio
|
||||
if(GSL_VS_ADD_NATIVE_VISUALIZERS)
|
||||
target_sources(GSL INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GSL.natvis>
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
install(TARGETS GSL EXPORT Microsoft.GSLConfig)
|
||||
install(
|
||||
DIRECTORY include/gsl
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
# Make library importable by other projects
|
||||
install(EXPORT Microsoft.GSLConfig NAMESPACE Microsoft.GSL:: DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL)
|
||||
export(TARGETS GSL NAMESPACE Microsoft.GSL:: FILE Microsoft.GSLConfig.cmake)
|
||||
|
||||
# Add find_package() versioning support. The version for
|
||||
# generated Microsoft.GSLConfigVersion.cmake will be used from
|
||||
# last project() command. The version's compatibility is set between all
|
||||
# minor versions (as it was in prev. GSL releases).
|
||||
include(CMakePackageConfigHelpers)
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.14.0")
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
else()
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake
|
||||
COMPATIBILITY SameMajorVersion
|
||||
ARCH_INDEPENDENT
|
||||
)
|
||||
endif()
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL)
|
||||
|
||||
# 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)
|
||||
|
||||
option(GSL_TEST "Generate tests." ${GSL_STANDALONE_PROJECT})
|
||||
# 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()
|
||||
|
||||
### Project options
|
||||
option(GSL_INSTALL "Generate and install GSL target" ${GSL_STANDALONE_PROJECT})
|
||||
option(GSL_TEST "Build and perform GSL tests" ${GSL_STANDALONE_PROJECT})
|
||||
|
||||
# This GSL implementation generally assumes a platform that implements C++14 support.
|
||||
set(gsl_min_cxx_standard "14")
|
||||
|
||||
if (GSL_STANDALONE_PROJECT)
|
||||
gsl_set_default_cxx_standard(${gsl_min_cxx_standard})
|
||||
else()
|
||||
gsl_client_set_cxx_standard(${gsl_min_cxx_standard})
|
||||
endif()
|
||||
|
||||
# Setup include directory
|
||||
add_subdirectory(include)
|
||||
|
||||
# Add natvis file
|
||||
gsl_add_native_visualizer_support()
|
||||
|
||||
# Add packaging support
|
||||
gsl_create_packaging_file()
|
||||
|
||||
if (GSL_INSTALL)
|
||||
# Setup install/export logic
|
||||
gsl_install_logic()
|
||||
endif()
|
||||
|
||||
if (GSL_TEST)
|
||||
enable_testing()
|
||||
if(IOS)
|
||||
add_compile_definitions(
|
||||
GTEST_HAS_DEATH_TEST=1
|
||||
)
|
||||
endif()
|
||||
add_subdirectory(tests)
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ Please submit a Contributor License Agreement (CLA) before submitting a pull req
|
||||
Your pull request should:
|
||||
|
||||
* Include a description of what your change intends to do
|
||||
* Be a child commit of a reasonably recent commit in the **master** branch
|
||||
* Be a child commit of a reasonably recent commit in the **main** branch
|
||||
* Requests need not be a single commit, but should be a linear sequence of commits (i.e. no merge commits in your PR)
|
||||
* It is desirable, but not necessary, for the tests to pass at each commit. Please see [README.md](./README.md) for instructions to build the test suite.
|
||||
* Have clear commit messages
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# GSL: Guidelines Support Library
|
||||
[](https://travis-ci.org/Microsoft/GSL) [](https://ci.appveyor.com/project/neilmacintosh/GSL)
|
||||
[](https://dev.azure.com/cppstat/GSL/_build/latest?definitionId=1&branchName=main)
|
||||
|
||||
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,6 +29,15 @@ owner | ☑ | an alias for a raw pointer
|
||||
not_null | ☑ | restricts a pointer / smart pointer to hold non-null values
|
||||
span | ☑ | 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 | ☐ | spans a range starting from a pointer to the first place for which the predicate is true
|
||||
basic_zstring | ☑ | A pointer to a C-string (zero-terminated array) with a templated char type
|
||||
zstring | ☑ | An alias to `basic_zstring` with a char type of char
|
||||
czstring | ☑ | An alias to `basic_zstring` with a char type of const char
|
||||
wzstring | ☑ | An alias to `basic_zstring` with a char type of wchar_t
|
||||
cwzstring | ☑ | An alias to `basic_zstring` with a char type of const wchar_t
|
||||
u16zstring | ☑ | An alias to `basic_zstring` with a char type of char16_t
|
||||
cu16zstring | ☑ | An alias to `basic_zstring` with a char type of const char16_t
|
||||
u32zstring | ☑ | An alias to `basic_zstring` with a char type of char32_t
|
||||
cu32zstring | ☑ | An alias to `basic_zstring` with a char type of const char32_t
|
||||
[**2. Owners**][cg-owners] | |
|
||||
unique_ptr | ☑ | an alias to `std::unique_ptr`
|
||||
shared_ptr | ☑ | an alias to `std::shared_ptr`
|
||||
@@ -57,15 +66,6 @@ Feature | Supported? | Description
|
||||
strict_not_null | ☑ | A stricter version of `not_null` with explicit constructors
|
||||
multi_span | ☐ | Deprecated. Multi-dimensional span.
|
||||
strided_span | ☐ | Deprecated. Support for this type has been discontinued.
|
||||
basic_zstring | ☐ | Deprecated. A pointer to a C-string (zero-terminated array) with a templated char type
|
||||
zstring | ☐ | Deprecated. An alias to `basic_zstring` with a char type of char
|
||||
czstring | ☐ | Deprecated. An alias to `basic_zstring` with a char type of const char
|
||||
wzstring | ☐ | Deprecated. An alias to `basic_zstring` with a char type of wchar_t
|
||||
cwzstring | ☐ | Deprecated. An alias to `basic_zstring` with a char type of const wchar_t
|
||||
u16zstring | ☐ | Deprecated. An alias to `basic_zstring` with a char type of char16_t
|
||||
cu16zstring | ☐ | Deprecated. An alias to `basic_zstring` with a char type of const char16_t
|
||||
u32zstring | ☐ | Deprecated. An alias to `basic_zstring` with a char type of char32_t
|
||||
cu32zstring | ☐ | Deprecated. An alias to `basic_zstring` with a char type of const char32_t
|
||||
basic_string_span | ☐ | Deprecated. Like `span` but for strings with a templated char type
|
||||
string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of char
|
||||
cstring_span | ☐ | 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 | [](https://travis-ci.org/Microsoft/GSL)
|
||||
GCC |9 & 8| [](https://travis-ci.org/Microsoft/GSL)
|
||||
Clang |11 & 10| [](https://travis-ci.org/Microsoft/GSL)
|
||||
Visual Studio with MSVC | VS2017 (15.9) & VS2019 (16.4) | [](https://ci.appveyor.com/project/neilmacintosh/GSL)
|
||||
Visual Studio with LLVM | VS2017 (Clang 9) & VS2019 (Clang 10) | [](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!
|
||||
@@ -181,5 +178,36 @@ The library provides a Config file for CMake, once installed it can be found via
|
||||
Which, when successful, will add library target called `Microsoft.GSL::GSL` which you can use via the usual
|
||||
`target_link_libraries` mechanism.
|
||||
|
||||
### FetchContent
|
||||
|
||||
If you are using cmake version 3.11+ you can use the offical FetchContent module.
|
||||
This allows you to easily incorporate GSL into your project.
|
||||
|
||||
```cmake
|
||||
# NOTE: This example uses cmake version 3.14 (FetchContent_MakeAvailable).
|
||||
# Since it streamlines the FetchContent process
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# In this example we are picking a specific tag.
|
||||
# You can also pick a specific commit, if you need to.
|
||||
FetchContent_Declare(GSL
|
||||
GIT_REPOSITORY "https://github.com/microsoft/GSL"
|
||||
GIT_TAG "v3.1.0"
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(GSL)
|
||||
|
||||
# Now you can link against the GSL interface library
|
||||
add_executable(foobar)
|
||||
|
||||
# Link against the interface library (IE header only library)
|
||||
target_link_libraries(foobar PRIVATE GSL)
|
||||
```
|
||||
|
||||
## Debugging visualization support
|
||||
For Visual Studio users, the file [GSL.natvis](./GSL.natvis) in the root directory of the repository can be added to your project if you would like more helpful visualization of GSL types in the Visual Studio debugger than would be offered by default.
|
||||
|
||||
If you are using cmake this will be done automatically for you.
|
||||
See 'GSL_VS_ADD_NATIVE_VISUALIZERS'
|
||||
|
||||
-114
@@ -1,114 +0,0 @@
|
||||
shallow_clone: true
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
image:
|
||||
- Visual Studio 2017
|
||||
- Visual Studio 2019
|
||||
|
||||
environment:
|
||||
NINJA_TAG: v1.8.2
|
||||
NINJA_SHA512: 9B9CE248240665FCD6404B989F3B3C27ED9682838225E6DC9B67B551774F251E4FF8A207504F941E7C811E7A8BE1945E7BCB94472A335EF15E23A0200A32E6D5
|
||||
NINJA_PATH: C:\Tools\ninja\ninja-%NINJA_TAG%
|
||||
VCVAR2017: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat'
|
||||
VCVAR2019: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat'
|
||||
matrix:
|
||||
- GSL_CXX_STANDARD: 14
|
||||
USE_TOOLSET: MSVC
|
||||
USE_GENERATOR: MSBuild
|
||||
- GSL_CXX_STANDARD: 17
|
||||
USE_TOOLSET: MSVC
|
||||
USE_GENERATOR: MSBuild
|
||||
- GSL_CXX_STANDARD: 14
|
||||
USE_TOOLSET: LLVM
|
||||
USE_GENERATOR: Ninja
|
||||
- GSL_CXX_STANDARD: 17
|
||||
USE_TOOLSET: LLVM
|
||||
USE_GENERATOR: Ninja
|
||||
|
||||
cache:
|
||||
- C:\cmake-3.14.4-win32-x86
|
||||
- C:\Tools\ninja
|
||||
|
||||
install:
|
||||
- ps: |
|
||||
if (![IO.File]::Exists("$env:NINJA_PATH\ninja.exe")) {
|
||||
Start-FileDownload `
|
||||
"https://github.com/ninja-build/ninja/releases/download/$env:NINJA_TAG/ninja-win.zip"
|
||||
$hash = (Get-FileHash ninja-win.zip -Algorithm SHA512).Hash
|
||||
if ($env:NINJA_SHA512 -eq $hash) {
|
||||
7z e -y -bso0 ninja-win.zip -o"$env:NINJA_PATH"
|
||||
} else { Write-Warning "Ninja download hash changed!"; Write-Output "$hash" }
|
||||
}
|
||||
if ([IO.File]::Exists("$env:NINJA_PATH\ninja.exe")) {
|
||||
$env:PATH = "$env:NINJA_PATH;$env:PATH"
|
||||
} else { Write-Warning "Failed to find ninja.exe in expected location." }
|
||||
if ($env:USE_TOOLSET -ne "LLVM") {
|
||||
if (![IO.File]::Exists("C:\cmake-3.14.0-win32-x86\bin\cmake.exe")) {
|
||||
Start-FileDownload 'https://cmake.org/files/v3.14/cmake-3.14.4-win32-x86.zip'
|
||||
7z x -y -bso0 cmake-3.14.4-win32-x86.zip -oC:\
|
||||
}
|
||||
$env:PATH="C:\cmake-3.14.4-win32-x86\bin;$env:PATH"
|
||||
}
|
||||
|
||||
before_build:
|
||||
- ps: |
|
||||
if ("$env:USE_GENERATOR" -eq "Ninja") {
|
||||
$GeneratorFlags = '-k 10'
|
||||
$Architecture = $env:PLATFORM
|
||||
if ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2017") {
|
||||
$env:VCVARSALL = "`"$env:VCVAR2017`" $Architecture"
|
||||
} else {
|
||||
$env:VCVARSALL = "`"$env:VCVAR2019`" $Architecture"
|
||||
}
|
||||
$env:CMakeGenFlags = "-G Ninja -DGSL_CXX_STANDARD=$env:GSL_CXX_STANDARD"
|
||||
} else {
|
||||
$GeneratorFlags = '/m /v:minimal'
|
||||
if ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2017") {
|
||||
$Generator = 'Visual Studio 15 2017'
|
||||
} else {
|
||||
$Generator = 'Visual Studio 16 2019'
|
||||
}
|
||||
if ("$env:PLATFORM" -eq "x86") {
|
||||
$Architecture = "Win32"
|
||||
} else {
|
||||
$Architecture = "x64"
|
||||
}
|
||||
if ("$env:USE_TOOLSET" -eq "LLVM") {
|
||||
$env:CMakeGenFlags = "-G `"$Generator`" -A $Architecture -T llvm -DGSL_CXX_STANDARD=$env:GSL_CXX_STANDARD"
|
||||
} else {
|
||||
$env:CMakeGenFlags = "-G `"$Generator`" -A $Architecture -DGSL_CXX_STANDARD=$env:GSL_CXX_STANDARD"
|
||||
}
|
||||
}
|
||||
if ("$env:USE_TOOLSET" -eq "LLVM") {
|
||||
$env:CC = "clang-cl"
|
||||
$env:CXX = "clang-cl"
|
||||
if ("$env:PLATFORM" -eq "x86") {
|
||||
$env:CFLAGS = "-m32";
|
||||
$env:CXXFLAGS = "-m32";
|
||||
} else {
|
||||
$env:CFLAGS = "-m64";
|
||||
$env:CXXFLAGS = "-m64";
|
||||
}
|
||||
}
|
||||
$env:CMakeBuildFlags = "--config $env:CONFIGURATION -- $GeneratorFlags"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if %USE_GENERATOR%==Ninja (call %VCVARSALL%)
|
||||
- echo %CMakeGenFlags%
|
||||
- cmake .. %CMakeGenFlags%
|
||||
|
||||
build_script:
|
||||
- echo %CMakeBuildFlags%
|
||||
- cmake --build . %CMakeBuildFlags%
|
||||
|
||||
test_script:
|
||||
- ctest -j2
|
||||
|
||||
deploy: off
|
||||
@@ -0,0 +1,68 @@
|
||||
trigger:
|
||||
- main
|
||||
|
||||
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
|
||||
@@ -0,0 +1,116 @@
|
||||
# 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 (CMAKE_VERSION VERSION_GREATER 3.10 OR CMAKE_VERSION VERSION_EQUAL 3.10)
|
||||
include_guard()
|
||||
else()
|
||||
if (DEFINED guideline_support_library_include_guard)
|
||||
return()
|
||||
endif()
|
||||
set(guideline_support_library_include_guard ON)
|
||||
endif()
|
||||
|
||||
# Necessary for 'write_basic_package_version_file'
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
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()
|
||||
|
||||
# Adding the GSL.natvis files improves the debugging experience for users of this library.
|
||||
function(gsl_add_native_visualizer_support)
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.7.8)
|
||||
if (MSVC_IDE)
|
||||
option(GSL_VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE)
|
||||
else()
|
||||
set(GSL_VS_ADD_NATIVE_VISUALIZERS FALSE CACHE INTERNAL "Native visualizers are Visual Studio extension" FORCE)
|
||||
endif()
|
||||
|
||||
# add natvis file to the library so it will automatically be loaded into Visual Studio
|
||||
if(GSL_VS_ADD_NATIVE_VISUALIZERS)
|
||||
target_sources(GSL INTERFACE $<BUILD_INTERFACE:${GSL_SOURCE_DIR}/GSL.natvis>)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(gsl_install_logic)
|
||||
install(TARGETS GSL EXPORT Microsoft.GSLConfig)
|
||||
install(
|
||||
DIRECTORY include/gsl
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
# Make library importable by other projects
|
||||
install(EXPORT Microsoft.GSLConfig NAMESPACE Microsoft.GSL:: DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL)
|
||||
export(TARGETS GSL NAMESPACE Microsoft.GSL:: FILE Microsoft.GSLConfig.cmake)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL)
|
||||
endfunction()
|
||||
|
||||
# Add find_package() versioning support. The version for
|
||||
# generated Microsoft.GSLConfigVersion.cmake will be used from
|
||||
# last project() command. The version's compatibility is set between all
|
||||
# minor versions (as it was in prev. GSL releases).
|
||||
function(gsl_create_packaging_file)
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.14.0")
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
else()
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake
|
||||
COMPATIBILITY SameMajorVersion
|
||||
ARCH_INDEPENDENT
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
# Add include folders to the library and targets that consume it
|
||||
# the SYSTEM keyword suppresses warnings for users of the library
|
||||
#
|
||||
# By adding this directory as an include directory the user gets a
|
||||
# namespace effect.
|
||||
#
|
||||
# IE:
|
||||
# #include <gsl/gsl>
|
||||
if(GSL_STANDALONE_PROJECT)
|
||||
target_include_directories(GSL INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
else()
|
||||
target_include_directories(GSL SYSTEM INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
endif()
|
||||
@@ -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 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());
|
||||
// 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
|
||||
@@ -0,0 +1,135 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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
|
||||
@@ -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
|
||||
+11
-8
@@ -17,13 +17,16 @@
|
||||
#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> // Ensures/Expects
|
||||
#include <gsl/byte> // byte
|
||||
#include <gsl/pointers> // owner, not_null
|
||||
#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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 Expects
|
||||
#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
|
||||
+50
-29
@@ -17,27 +17,32 @@
|
||||
#ifndef GSL_POINTERS_H
|
||||
#define GSL_POINTERS_H
|
||||
|
||||
#include <gsl/gsl_assert> // for Ensures, Expects
|
||||
#include <gsl/assert> // for Ensures, Expects
|
||||
|
||||
#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,7 +68,8 @@ 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))
|
||||
@@ -79,8 +85,7 @@ public:
|
||||
|
||||
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;
|
||||
@@ -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
|
||||
|
||||
+67
-58
@@ -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 Expects
|
||||
#include <gsl/byte> // for byte
|
||||
#include <gsl/util> // for narrow_cast
|
||||
|
||||
#include <array> // for array
|
||||
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
|
||||
@@ -152,6 +152,9 @@ namespace details
|
||||
{
|
||||
Expects(begin_ && current_ && end_);
|
||||
Expects(current_ < end_);
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
++current_;
|
||||
return *this;
|
||||
}
|
||||
@@ -183,6 +186,9 @@ namespace details
|
||||
if (n != 0) Expects(begin_ && current_ && end_);
|
||||
if (n > 0) Expects(end_ - current_ >= n);
|
||||
if (n < 0) Expects(current_ - begin_ >= -n);
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
current_ += n;
|
||||
return *this;
|
||||
}
|
||||
@@ -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()))
|
||||
{}
|
||||
@@ -565,7 +575,8 @@ public:
|
||||
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;
|
||||
using type =
|
||||
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type;
|
||||
return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
|
||||
}
|
||||
|
||||
@@ -581,9 +592,8 @@ public:
|
||||
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>{});
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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) )
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+15
-33
@@ -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 Ensures, Expects
|
||||
#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
|
||||
{
|
||||
@@ -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(
|
||||
|
||||
@@ -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 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;
|
||||
|
||||
// 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));
|
||||
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()));
|
||||
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()));
|
||||
return *(cont.begin() + i);
|
||||
}
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // GSL_UTIL_H
|
||||
@@ -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
|
||||
@@ -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) -Werror=dev .. '
|
||||
|
||||
- task: CMake@1
|
||||
name: Build
|
||||
inputs:
|
||||
workingDirectory: build
|
||||
cmakeArgs: '--build . '
|
||||
|
||||
- script: ctest . --output-on-failure --no-compress-output
|
||||
name: CTest
|
||||
workingDirectory: build
|
||||
failOnStderr: true
|
||||
+19
-5
@@ -1,13 +1,23 @@
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
project(GSLTests CXX)
|
||||
enable_testing() # again, for support standalone testing
|
||||
|
||||
include(FindPkgConfig)
|
||||
include(ExternalProject)
|
||||
|
||||
# will make visual studio generated project group files
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
if(IOS)
|
||||
add_compile_definitions(GTEST_HAS_DEATH_TEST=1)
|
||||
endif()
|
||||
|
||||
pkg_search_module(GTestMain gtest_main)
|
||||
if (NOT GTestMain_FOUND)
|
||||
# No pre-installed GTest is available, try to download it using Git.
|
||||
find_package(Git REQUIRED QUIET)
|
||||
|
||||
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||
@@ -37,6 +47,13 @@ if (NOT GTestMain_FOUND)
|
||||
)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
# CMake has been started independently in this directory with tests. Do
|
||||
# import the globally installed Guidelines Support Library and test it
|
||||
# instead of the current version from the include/ folder.
|
||||
find_package(Microsoft.GSL REQUIRED)
|
||||
endif()
|
||||
|
||||
if (MSVC AND (GSL_CXX_STANDARD EQUAL 17))
|
||||
set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-)
|
||||
endif()
|
||||
@@ -152,7 +169,7 @@ set_property(TARGET PROPERTY FOLDER "GSL_tests")
|
||||
function(add_gsl_test name)
|
||||
add_executable(${name} ${name}.cpp)
|
||||
target_link_libraries(${name}
|
||||
GSL
|
||||
Microsoft.GSL::GSL
|
||||
gsl_tests_config
|
||||
${GTestMain_LIBRARIES}
|
||||
)
|
||||
@@ -167,11 +184,8 @@ endfunction()
|
||||
add_gsl_test(span_tests)
|
||||
add_gsl_test(span_ext_tests)
|
||||
add_gsl_test(span_compatibility_tests)
|
||||
add_gsl_test(multi_span_tests)
|
||||
add_gsl_test(strided_span_tests)
|
||||
add_gsl_test(string_span_tests)
|
||||
add_gsl_test(at_tests)
|
||||
add_gsl_test(bounds_tests)
|
||||
add_gsl_test(notnull_tests)
|
||||
add_gsl_test(assertion_tests)
|
||||
add_gsl_test(utils_tests)
|
||||
@@ -257,7 +271,7 @@ endif(MSVC)
|
||||
function(add_gsl_test_noexcept name)
|
||||
add_executable(${name} ${name}.cpp)
|
||||
target_link_libraries(${name}
|
||||
GSL
|
||||
Microsoft.GSL::GSL
|
||||
gsl_tests_config_noexcept
|
||||
${GTestMain_LIBRARIES}
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ project(googletest-download NONE)
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e
|
||||
GIT_TAG 389cb68b87193358358ae87cc56d257fd0d80189
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
|
||||
CONFIGURE_COMMAND ""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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), Ensures, Expects
|
||||
|
||||
using namespace gsl;
|
||||
|
||||
|
||||
+1
-1
@@ -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,102 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <gsl/multi_span> // for static_bounds, static_bounds_dynamic_range_t
|
||||
|
||||
#include <cstddef> // for ptrdiff_t, size_t
|
||||
|
||||
using namespace std;
|
||||
using namespace gsl;
|
||||
|
||||
namespace
|
||||
{
|
||||
void use(std::ptrdiff_t&) {}
|
||||
}
|
||||
|
||||
TEST(bounds_tests, basic_bounds)
|
||||
{
|
||||
for (auto point : static_bounds<dynamic_range, 3, 4>{2}) {
|
||||
for (decltype(point)::size_type j = 0;
|
||||
j < static_cast<decltype(point)::size_type>(decltype(point)::rank); j++)
|
||||
{
|
||||
use(j);
|
||||
use(point[static_cast<std::size_t>(j)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(bounds_tests, bounds_basic)
|
||||
{
|
||||
static_bounds<3, 4, 5> b;
|
||||
const auto a = b.slice();
|
||||
(void) a;
|
||||
static_bounds<4, dynamic_range, 2> x{4};
|
||||
x.slice().slice();
|
||||
}
|
||||
|
||||
TEST(bounds_tests, arrayview_iterator)
|
||||
{
|
||||
static_bounds<4, dynamic_range, 2> bounds{3};
|
||||
|
||||
const auto itr = bounds.begin();
|
||||
(void) itr;
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
multi_span<int, 4, dynamic_range, 2> av(nullptr, bounds);
|
||||
|
||||
auto itr2 = av.cbegin();
|
||||
|
||||
for (auto& v : av) {
|
||||
v = 4;
|
||||
}
|
||||
fill(av.begin(), av.end(), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(bounds_tests, bounds_convertible)
|
||||
{
|
||||
static_bounds<7, 4, 2> b1;
|
||||
static_bounds<7, dynamic_range, 2> b2 = b1;
|
||||
(void) b2;
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
static_bounds<7, dynamic_range, 1> b4 = b2;
|
||||
#endif
|
||||
|
||||
static_bounds<dynamic_range, dynamic_range, dynamic_range> b3 = b1;
|
||||
static_bounds<7, 4, 2> b4 = b3;
|
||||
(void) b4;
|
||||
|
||||
static_bounds<dynamic_range> b5;
|
||||
static_bounds<34> b6;
|
||||
|
||||
std::set_terminate([] {
|
||||
std::cerr << "Expected Death. bounds_convertible";
|
||||
std::abort();
|
||||
});
|
||||
|
||||
b5 = static_bounds<20>();
|
||||
EXPECT_DEATH(b6 = b5, ".*");
|
||||
b5 = static_bounds<34>();
|
||||
b6 = b5;
|
||||
|
||||
EXPECT_TRUE(b5 == b6);
|
||||
EXPECT_TRUE(b5.size() == b6.size());
|
||||
}
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
copy(src_span_static, dst_span_static);
|
||||
#endif
|
||||
@@ -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;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,790 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gsl/gsl_byte> // for byte
|
||||
#include <gsl/gsl_util> // for narrow_cast
|
||||
#include <gsl/multi_span> // for strided_span, index, multi_span, strided_...
|
||||
|
||||
#include <iostream> // for size_t
|
||||
#include <iterator> // for begin, end
|
||||
#include <numeric> // for iota
|
||||
#include <type_traits> // for integral_constant<>::value, is_convertible
|
||||
#include <vector> // for vector
|
||||
|
||||
using namespace std;
|
||||
using namespace gsl;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static constexpr char deathstring[] = "Expected Death";
|
||||
|
||||
struct BaseClass
|
||||
{
|
||||
};
|
||||
struct DerivedClass : BaseClass
|
||||
{
|
||||
};
|
||||
|
||||
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
void iterate_every_other_element(multi_span<int, dynamic_range> av)
|
||||
{
|
||||
// pick every other element
|
||||
|
||||
auto length = av.size() / 2;
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1800
|
||||
auto bounds = strided_bounds<1>({length}, {2});
|
||||
#else
|
||||
auto bounds = strided_bounds<1>(multi_span_index<1>{length}, multi_span_index<1>{2});
|
||||
#endif
|
||||
strided_span<int, 1> strided(&av.data()[1], av.size() - 1, bounds);
|
||||
|
||||
EXPECT_TRUE(strided.size() == length);
|
||||
EXPECT_TRUE(strided.bounds().index_bounds()[0] == length);
|
||||
for (auto i = 0; i < strided.size(); ++i) {
|
||||
EXPECT_TRUE(strided[i] == av[2 * i + 1]);
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
for (auto num : strided) {
|
||||
EXPECT_TRUE(num == av[2 * idx + 1]);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
|
||||
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
|
||||
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // TODO: does not work
|
||||
void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_range> av)
|
||||
{
|
||||
const int expected[6] = {2, 3, 10, 11, 18, 19};
|
||||
auto section = av.section({0, 1, 0}, {3, 1, 2});
|
||||
|
||||
for (auto i = 0; i < section.extent<0>(); ++i) {
|
||||
for (auto j = 0; j < section.extent<1>(); ++j)
|
||||
for (auto k = 0; k < section.extent<2>(); ++k) {
|
||||
auto idx = multi_span_index<3>{i, j, k}; // avoid braces in the EXPECT_TRUE macro
|
||||
EXPECT_TRUE(section[idx] == expected[2 * i + 2 * j + k]);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = 0; i < section.extent<0>(); ++i) {
|
||||
for (auto j = 0; j < section.extent<1>(); ++j)
|
||||
for (auto k = 0; k < section.extent<2>(); ++k)
|
||||
EXPECT_TRUE(section[i][j][k] == expected[2 * i + 2 * j + k]);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (const auto num : section) {
|
||||
EXPECT_TRUE(num == expected[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, span_section_test)
|
||||
{
|
||||
int a[30][4][5];
|
||||
|
||||
const auto av = as_multi_span(a);
|
||||
const auto sub = av.section({15, 0, 0}, gsl::multi_span_index<3>{2, 2, 2});
|
||||
const auto subsub = sub.section({1, 0, 0}, gsl::multi_span_index<3>{1, 1, 1});
|
||||
(void) subsub;
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, span_section)
|
||||
{
|
||||
std::vector<int> data(5 * 10);
|
||||
std::iota(begin(data), end(data), 0);
|
||||
const multi_span<int, 5, 10> av = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>());
|
||||
|
||||
const strided_span<int, 2> av_section_1 = av.section({1, 2}, {3, 4});
|
||||
EXPECT_TRUE(!av_section_1.empty());
|
||||
EXPECT_TRUE((av_section_1[{0, 0}] == 12));
|
||||
EXPECT_TRUE((av_section_1[{0, 1}] == 13));
|
||||
EXPECT_TRUE((av_section_1[{1, 0}] == 22));
|
||||
EXPECT_TRUE((av_section_1[{2, 3}] == 35));
|
||||
|
||||
const strided_span<int, 2> av_section_2 = av_section_1.section({1, 2}, {2, 2});
|
||||
EXPECT_TRUE(!av_section_2.empty());
|
||||
EXPECT_TRUE((av_section_2[{0, 0}] == 24));
|
||||
EXPECT_TRUE((av_section_2[{0, 1}] == 25));
|
||||
EXPECT_TRUE((av_section_2[{1, 0}] == 34));
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, strided_span_constructors)
|
||||
{
|
||||
// EXPECT_TRUE stride constructor
|
||||
{
|
||||
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
const int carr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
|
||||
strided_span<int, 1> sav1{arr, {{9}, {1}}}; // T -> T
|
||||
EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{9});
|
||||
EXPECT_TRUE(sav1.bounds().stride() == 1);
|
||||
EXPECT_TRUE(sav1[0] == 1);
|
||||
EXPECT_TRUE(sav1[8] == 9);
|
||||
|
||||
strided_span<const int, 1> sav2{carr, {{4}, {2}}}; // const T -> const T
|
||||
EXPECT_TRUE(sav2.bounds().index_bounds() == multi_span_index<1>{4});
|
||||
EXPECT_TRUE(sav2.bounds().strides() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav2[0] == 1);
|
||||
EXPECT_TRUE(sav2[3] == 7);
|
||||
|
||||
strided_span<int, 2> sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T
|
||||
EXPECT_TRUE((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2}));
|
||||
EXPECT_TRUE((sav3.bounds().strides() == multi_span_index<2>{6, 2}));
|
||||
EXPECT_TRUE((sav3[{0, 0}]) == 1);
|
||||
EXPECT_TRUE((sav3[{0, 1}]) == 3);
|
||||
EXPECT_TRUE((sav3[{1, 0}]) == 7);
|
||||
}
|
||||
|
||||
// EXPECT_TRUE multi_span constructor
|
||||
{
|
||||
int arr[] = {1, 2};
|
||||
|
||||
// From non-cv-qualified source
|
||||
{
|
||||
const multi_span<int> src = arr;
|
||||
|
||||
strided_span<int, 1> sav{src, {2, 1}};
|
||||
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav[1] == 2);
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1800
|
||||
// strided_span<const int, 1> sav_c{ {src}, {2, 1} };
|
||||
strided_span<const int, 1> sav_c{multi_span<const int>{src},
|
||||
strided_bounds<1>{2, 1}};
|
||||
#else
|
||||
strided_span<const int, 1> sav_c{multi_span<const int>{src},
|
||||
strided_bounds<1>{2, 1}};
|
||||
#endif
|
||||
EXPECT_TRUE(sav_c.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav_c.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav_c[1] == 2);
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1800
|
||||
strided_span<volatile int, 1> sav_v{src, {2, 1}};
|
||||
#else
|
||||
strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src},
|
||||
strided_bounds<1>{2, 1}};
|
||||
#endif
|
||||
EXPECT_TRUE(sav_v.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav_v.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav_v[1] == 2);
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1800
|
||||
strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
|
||||
#else
|
||||
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
|
||||
strided_bounds<1>{2, 1}};
|
||||
#endif
|
||||
EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav_cv[1] == 2);
|
||||
}
|
||||
|
||||
// From const-qualified source
|
||||
{
|
||||
const multi_span<const int> src{arr};
|
||||
|
||||
strided_span<const int, 1> sav_c{src, {2, 1}};
|
||||
EXPECT_TRUE(sav_c.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav_c.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav_c[1] == 2);
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1800
|
||||
strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
|
||||
#else
|
||||
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
|
||||
strided_bounds<1>{2, 1}};
|
||||
#endif
|
||||
|
||||
EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav_cv[1] == 2);
|
||||
}
|
||||
|
||||
// From volatile-qualified source
|
||||
{
|
||||
const multi_span<volatile int> src{arr};
|
||||
|
||||
strided_span<volatile int, 1> sav_v{src, {2, 1}};
|
||||
EXPECT_TRUE(sav_v.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav_v.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav_v[1] == 2);
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1800
|
||||
strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
|
||||
#else
|
||||
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
|
||||
strided_bounds<1>{2, 1}};
|
||||
#endif
|
||||
EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav_cv[1] == 2);
|
||||
}
|
||||
|
||||
// From cv-qualified source
|
||||
{
|
||||
const multi_span<const volatile int> src{arr};
|
||||
|
||||
strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
|
||||
EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav_cv[1] == 2);
|
||||
}
|
||||
}
|
||||
|
||||
// EXPECT_TRUE const-casting constructor
|
||||
{
|
||||
int arr[2] = {4, 5};
|
||||
|
||||
const multi_span<int, 2> av(arr, 2);
|
||||
multi_span<const int, 2> av2{av};
|
||||
EXPECT_TRUE(av2[1] == 5);
|
||||
|
||||
static_assert(
|
||||
std::is_convertible<const multi_span<int, 2>, multi_span<const int, 2>>::value,
|
||||
"ctor is not implicit!");
|
||||
|
||||
const strided_span<int, 1> src{arr, {2, 1}};
|
||||
strided_span<const int, 1> sav{src};
|
||||
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav.bounds().stride() == 1);
|
||||
EXPECT_TRUE(sav[1] == 5);
|
||||
|
||||
static_assert(
|
||||
std::is_convertible<const strided_span<int, 1>, strided_span<const int, 1>>::value,
|
||||
"ctor is not implicit!");
|
||||
}
|
||||
|
||||
// EXPECT_TRUE copy constructor
|
||||
{
|
||||
int arr1[2] = {3, 4};
|
||||
const strided_span<int, 1> src1{arr1, {2, 1}};
|
||||
strided_span<int, 1> sav1{src1};
|
||||
|
||||
EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav1.bounds().stride() == 1);
|
||||
EXPECT_TRUE(sav1[0] == 3);
|
||||
|
||||
int arr2[6] = {1, 2, 3, 4, 5, 6};
|
||||
const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
|
||||
strided_span<const int, 2> sav2{src2};
|
||||
EXPECT_TRUE((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
|
||||
EXPECT_TRUE((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
|
||||
EXPECT_TRUE((sav2[{0, 0}]) == 1);
|
||||
EXPECT_TRUE((sav2[{2, 0}]) == 5);
|
||||
}
|
||||
|
||||
// EXPECT_TRUE const-casting assignment operator
|
||||
{
|
||||
int arr1[2] = {1, 2};
|
||||
int arr2[6] = {3, 4, 5, 6, 7, 8};
|
||||
|
||||
const strided_span<int, 1> src{arr1, {{2}, {1}}};
|
||||
strided_span<const int, 1> sav{arr2, {{3}, {2}}};
|
||||
strided_span<const int, 1>& sav_ref = (sav = src);
|
||||
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav[0] == 1);
|
||||
EXPECT_TRUE(&sav_ref == &sav);
|
||||
}
|
||||
|
||||
// EXPECT_TRUE copy assignment operator
|
||||
{
|
||||
int arr1[2] = {3, 4};
|
||||
int arr1b[1] = {0};
|
||||
const strided_span<int, 1> src1{arr1, {2, 1}};
|
||||
strided_span<int, 1> sav1{arr1b, {1, 1}};
|
||||
strided_span<int, 1>& sav1_ref = (sav1 = src1);
|
||||
EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav1.bounds().strides() == multi_span_index<1>{1});
|
||||
EXPECT_TRUE(sav1[0] == 3);
|
||||
EXPECT_TRUE(&sav1_ref == &sav1);
|
||||
|
||||
const int arr2[6] = {1, 2, 3, 4, 5, 6};
|
||||
const int arr2b[1] = {0};
|
||||
const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
|
||||
strided_span<const int, 2> sav2{arr2b, {{1, 1}, {1, 1}}};
|
||||
strided_span<const int, 2>& sav2_ref = (sav2 = src2);
|
||||
EXPECT_TRUE((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
|
||||
EXPECT_TRUE((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
|
||||
EXPECT_TRUE((sav2[{0, 0}] == 1));
|
||||
EXPECT_TRUE((sav2[{2, 0}] == 5));
|
||||
EXPECT_TRUE(&sav2_ref == &sav2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, strided_span_slice)
|
||||
{
|
||||
std::vector<int> data(5 * 10);
|
||||
std::iota(begin(data), end(data), 0);
|
||||
const multi_span<int, 5, 10> src =
|
||||
as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>());
|
||||
|
||||
const strided_span<int, 2> sav{src, {{5, 10}, {10, 1}}};
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
const strided_span<const int, 2> csav{{src}, {{5, 10}, {10, 1}}};
|
||||
#endif
|
||||
const strided_span<const int, 2> csav{multi_span<const int, 5, 10>{src},
|
||||
{{5, 10}, {10, 1}}};
|
||||
|
||||
strided_span<int, 1> sav_sl = sav[2];
|
||||
EXPECT_TRUE(sav_sl[0] == 20);
|
||||
EXPECT_TRUE(sav_sl[9] == 29);
|
||||
|
||||
strided_span<const int, 1> csav_sl = sav[3];
|
||||
EXPECT_TRUE(csav_sl[0] == 30);
|
||||
EXPECT_TRUE(csav_sl[9] == 39);
|
||||
|
||||
EXPECT_TRUE(sav[4][0] == 40);
|
||||
EXPECT_TRUE(sav[4][9] == 49);
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, strided_span_column_major)
|
||||
{
|
||||
// strided_span may be used to accommodate more peculiar
|
||||
// use cases, such as column-major multidimensional array
|
||||
// (aka. "FORTRAN" layout).
|
||||
|
||||
int cm_array[3 * 5] = {1, 4, 7, 10, 13, 2, 5, 8, 11, 14, 3, 6, 9, 12, 15};
|
||||
strided_span<int, 2> cm_sav{cm_array, {{5, 3}, {1, 5}}};
|
||||
|
||||
// Accessing elements
|
||||
EXPECT_TRUE((cm_sav[{0, 0}] == 1));
|
||||
EXPECT_TRUE((cm_sav[{0, 1}] == 2));
|
||||
EXPECT_TRUE((cm_sav[{1, 0}] == 4));
|
||||
EXPECT_TRUE((cm_sav[{4, 2}] == 15));
|
||||
|
||||
// Slice
|
||||
strided_span<int, 1> cm_sl = cm_sav[3];
|
||||
|
||||
EXPECT_TRUE(cm_sl[0] == 10);
|
||||
EXPECT_TRUE(cm_sl[1] == 11);
|
||||
EXPECT_TRUE(cm_sl[2] == 12);
|
||||
|
||||
// Section
|
||||
strided_span<int, 2> cm_sec = cm_sav.section({2, 1}, {3, 2});
|
||||
|
||||
EXPECT_TRUE((cm_sec.bounds().index_bounds() == multi_span_index<2>{3, 2}));
|
||||
EXPECT_TRUE((cm_sec[{0, 0}] == 8));
|
||||
EXPECT_TRUE((cm_sec[{0, 1}] == 9));
|
||||
EXPECT_TRUE((cm_sec[{1, 0}] == 11));
|
||||
EXPECT_TRUE((cm_sec[{2, 1}] == 15));
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, strided_span_bounds)
|
||||
{
|
||||
int arr[] = {0, 1, 2, 3};
|
||||
multi_span<int> av(arr);
|
||||
|
||||
std::set_terminate([] {
|
||||
std::cerr << "Expected Death. strided_span_bounds";
|
||||
std::abort();
|
||||
});
|
||||
|
||||
{
|
||||
// incorrect sections
|
||||
|
||||
EXPECT_DEATH(av.section(0, 0)[0], deathstring);
|
||||
EXPECT_DEATH(av.section(1, 0)[0], deathstring);
|
||||
EXPECT_DEATH(av.section(1, 1)[1], deathstring);
|
||||
|
||||
EXPECT_DEATH(av.section(2, 5), deathstring);
|
||||
EXPECT_DEATH(av.section(5, 2), deathstring);
|
||||
EXPECT_DEATH(av.section(5, 0), deathstring);
|
||||
EXPECT_DEATH(av.section(0, 5), deathstring);
|
||||
EXPECT_DEATH(av.section(5, 5), deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// zero stride
|
||||
strided_span<int, 1> sav{av, {{4}, {}}};
|
||||
EXPECT_TRUE(sav[0] == 0);
|
||||
EXPECT_TRUE(sav[3] == 0);
|
||||
EXPECT_DEATH(sav[4], deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// zero extent
|
||||
strided_span<int, 1> sav{av, {{}, {1}}};
|
||||
EXPECT_DEATH(sav[0], deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// zero extent and stride
|
||||
strided_span<int, 1> sav{av, {{}, {}}};
|
||||
EXPECT_DEATH(sav[0], deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// strided array ctor with matching strided bounds
|
||||
strided_span<int, 1> sav{arr, {4, 1}};
|
||||
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{4});
|
||||
EXPECT_TRUE(sav[3] == 3);
|
||||
EXPECT_DEATH(sav[4], deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// strided array ctor with smaller strided bounds
|
||||
strided_span<int, 1> sav{arr, {2, 1}};
|
||||
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav[1] == 1);
|
||||
EXPECT_DEATH(sav[2], deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// strided array ctor with fitting irregular bounds
|
||||
strided_span<int, 1> sav{arr, {2, 3}};
|
||||
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
|
||||
EXPECT_TRUE(sav[0] == 0);
|
||||
EXPECT_TRUE(sav[1] == 3);
|
||||
EXPECT_DEATH(sav[2], deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// bounds cross data boundaries - from static arrays
|
||||
EXPECT_DEATH((strided_span<int, 1>{arr, {3, 2}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{arr, {3, 3}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{arr, {4, 5}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{arr, {5, 1}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{arr, {5, 5}}), deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// bounds cross data boundaries - from array view
|
||||
EXPECT_DEATH((strided_span<int, 1>{av, {3, 2}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av, {3, 3}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av, {4, 5}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av, {5, 1}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av, {5, 5}}), deathstring);
|
||||
}
|
||||
|
||||
{
|
||||
// bounds cross data boundaries - from dynamic arrays
|
||||
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {3, 2}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {3, 3}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {4, 5}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {5, 1}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {5, 5}}), deathstring);
|
||||
EXPECT_DEATH((strided_span<int, 1>{av.data(), 2, {2, 2}}), deathstring);
|
||||
}
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
strided_span<int, 1> sav0{av.data(), {3, 2}};
|
||||
strided_span<int, 1> sav1{arr, {1}};
|
||||
strided_span<int, 1> sav2{arr, {1, 1, 1}};
|
||||
strided_span<int, 1> sav3{av, {1}};
|
||||
strided_span<int, 1> sav4{av, {1, 1, 1}};
|
||||
strided_span<int, 2> sav5{av.as_multi_span(dim<2>(), dim<2>()), {1}};
|
||||
strided_span<int, 2> sav6{av.as_multi_span(dim<2>(), dim<2>()), {1, 1, 1}};
|
||||
strided_span<int, 2> sav7{av.as_multi_span(dim<2>(), dim<2>()),
|
||||
{{1, 1}, {1, 1}, {1, 1}}};
|
||||
|
||||
multi_span_index<1> index{0, 1};
|
||||
strided_span<int, 1> sav8{arr, {1, {1, 1}}};
|
||||
strided_span<int, 1> sav9{arr, {{1, 1}, {1, 1}}};
|
||||
strided_span<int, 1> sav10{av, {1, {1, 1}}};
|
||||
strided_span<int, 1> sav11{av, {{1, 1}, {1, 1}}};
|
||||
strided_span<int, 2> sav12{av.as_multi_span(dim<2>(), dim<2>()), {{1}, {1}}};
|
||||
strided_span<int, 2> sav13{av.as_multi_span(dim<2>(), dim<2>()), {{1}, {1, 1, 1}}};
|
||||
strided_span<int, 2> sav14{av.as_multi_span(dim<2>(), dim<2>()), {{1, 1, 1}, {1}}};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, strided_span_type_conversion)
|
||||
{
|
||||
int arr[] = {0, 1, 2, 3};
|
||||
multi_span<int> av(arr);
|
||||
|
||||
std::set_terminate([] {
|
||||
std::cerr << "Expected Death. strided_span_type_conversion";
|
||||
std::abort();
|
||||
});
|
||||
|
||||
{
|
||||
strided_span<int, 1> sav{av.data(), av.size(), {av.size() / 2, 2}};
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
strided_span<long, 1> lsav1 = sav.as_strided_span<long, 1>();
|
||||
#endif
|
||||
}
|
||||
{
|
||||
strided_span<int, 1> sav{av, {av.size() / 2, 2}};
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
strided_span<long, 1> lsav1 = sav.as_strided_span<long, 1>();
|
||||
#endif
|
||||
}
|
||||
|
||||
multi_span<const byte, dynamic_range> bytes = as_bytes(av);
|
||||
|
||||
// retype strided array with regular strides - from raw data
|
||||
{
|
||||
strided_bounds<2> bounds{{2, bytes.size() / 4}, {bytes.size() / 2, 1}};
|
||||
strided_span<const byte, 2> sav2{bytes.data(), bytes.size(), bounds};
|
||||
strided_span<const int, 2> sav3 = sav2.as_strided_span<const int>();
|
||||
EXPECT_TRUE(sav3[0][0] == 0);
|
||||
EXPECT_TRUE(sav3[1][0] == 2);
|
||||
EXPECT_DEATH(sav3[1][1], deathstring);
|
||||
EXPECT_DEATH(sav3[0][1], deathstring);
|
||||
}
|
||||
|
||||
// retype strided array with regular strides - from multi_span
|
||||
{
|
||||
strided_bounds<2> bounds{{2, bytes.size() / 4}, {bytes.size() / 2, 1}};
|
||||
multi_span<const byte, 2, dynamic_range> bytes2 =
|
||||
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
|
||||
strided_span<const byte, 2> sav2{bytes2, bounds};
|
||||
strided_span<int, 2> sav3 = sav2.as_strided_span<int>();
|
||||
EXPECT_TRUE(sav3[0][0] == 0);
|
||||
EXPECT_TRUE(sav3[1][0] == 2);
|
||||
EXPECT_DEATH(sav3[1][1], deathstring);
|
||||
EXPECT_DEATH(sav3[0][1], deathstring);
|
||||
}
|
||||
|
||||
// retype strided array with not enough elements - last dimension of the array is too small
|
||||
{
|
||||
strided_bounds<2> bounds{{4, 2}, {4, 1}};
|
||||
multi_span<const byte, 2, dynamic_range> bytes2 =
|
||||
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
|
||||
strided_span<const byte, 2> sav2{bytes2, bounds};
|
||||
EXPECT_DEATH(sav2.as_strided_span<int>(), deathstring);
|
||||
}
|
||||
|
||||
// retype strided array with not enough elements - strides are too small
|
||||
{
|
||||
strided_bounds<2> bounds{{4, 2}, {2, 1}};
|
||||
multi_span<const byte, 2, dynamic_range> bytes2 =
|
||||
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
|
||||
strided_span<const byte, 2> sav2{bytes2, bounds};
|
||||
EXPECT_DEATH(sav2.as_strided_span<int>(), deathstring);
|
||||
}
|
||||
|
||||
// retype strided array with not enough elements - last dimension does not divide by the new
|
||||
// typesize
|
||||
{
|
||||
strided_bounds<2> bounds{{2, 6}, {4, 1}};
|
||||
multi_span<const byte, 2, dynamic_range> bytes2 =
|
||||
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
|
||||
strided_span<const byte, 2> sav2{bytes2, bounds};
|
||||
EXPECT_DEATH(sav2.as_strided_span<int>(), deathstring);
|
||||
}
|
||||
|
||||
// retype strided array with not enough elements - strides does not divide by the new
|
||||
// typesize
|
||||
{
|
||||
strided_bounds<2> bounds{{2, 1}, {6, 1}};
|
||||
multi_span<const byte, 2, dynamic_range> bytes2 =
|
||||
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
|
||||
strided_span<const byte, 2> sav2{bytes2, bounds};
|
||||
EXPECT_DEATH(sav2.as_strided_span<int>(), deathstring);
|
||||
}
|
||||
|
||||
// retype strided array with irregular strides - from raw data
|
||||
{
|
||||
strided_bounds<1> bounds{bytes.size() / 2, 2};
|
||||
strided_span<const byte, 1> sav2{bytes.data(), bytes.size(), bounds};
|
||||
EXPECT_DEATH(sav2.as_strided_span<int>(), deathstring);
|
||||
}
|
||||
|
||||
// retype strided array with irregular strides - from multi_span
|
||||
{
|
||||
strided_bounds<1> bounds{bytes.size() / 2, 2};
|
||||
strided_span<const byte, 1> sav2{bytes, bounds};
|
||||
EXPECT_DEATH(sav2.as_strided_span<int>(), deathstring);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, empty_strided_spans)
|
||||
{
|
||||
std::set_terminate([] {
|
||||
std::cerr << "Expected Death. empty_strided_spans";
|
||||
std::abort();
|
||||
});
|
||||
|
||||
{
|
||||
multi_span<int, 0> empty_av(nullptr);
|
||||
strided_span<int, 1> empty_sav{empty_av, {0, 1}};
|
||||
|
||||
EXPECT_TRUE(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
|
||||
EXPECT_TRUE(empty_sav.empty());
|
||||
EXPECT_DEATH(empty_sav[0], deathstring);
|
||||
EXPECT_DEATH(empty_sav.begin()[0], deathstring);
|
||||
EXPECT_DEATH(empty_sav.cbegin()[0], deathstring);
|
||||
|
||||
for (const auto& v : empty_sav) {
|
||||
(void) v;
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
strided_span<int, 1> empty_sav{nullptr, 0, {0, 1}};
|
||||
|
||||
EXPECT_TRUE(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
|
||||
EXPECT_DEATH(empty_sav[0], deathstring);
|
||||
EXPECT_DEATH(empty_sav.begin()[0], deathstring);
|
||||
EXPECT_DEATH(empty_sav.cbegin()[0], deathstring);
|
||||
|
||||
for (const auto& v : empty_sav) {
|
||||
(void) v;
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, strided_span_section_iteration)
|
||||
{
|
||||
int arr[8] = {4, 0, 5, 1, 6, 2, 7, 3};
|
||||
|
||||
// static bounds
|
||||
{
|
||||
multi_span<int, 8> av(arr, 8);
|
||||
iterate_every_other_element(av);
|
||||
}
|
||||
|
||||
// dynamic bounds
|
||||
{
|
||||
multi_span<int, dynamic_range> av(arr, 8);
|
||||
iterate_every_other_element(av);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, dynamic_strided_span_section_iteration)
|
||||
{
|
||||
auto arr = new int[8];
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
arr[2 * i] = 4 + i;
|
||||
arr[2 * i + 1] = i;
|
||||
}
|
||||
|
||||
auto av = as_multi_span(arr, 8);
|
||||
iterate_every_other_element(av);
|
||||
|
||||
delete[] arr;
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, strided_span_section_iteration_3d)
|
||||
{
|
||||
int arr[3][4][2]{};
|
||||
for (auto i = 0; i < 3; ++i) {
|
||||
for (auto j = 0; j < 4; ++j)
|
||||
for (auto k = 0; k < 2; ++k) arr[i][j][k] = 8 * i + 2 * j + k;
|
||||
}
|
||||
|
||||
{
|
||||
multi_span<int, 3, 4, 2> av = arr;
|
||||
iterate_second_slice(av);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, dynamic_strided_span_section_iteration_3d)
|
||||
{
|
||||
const auto height = 12, width = 2;
|
||||
const auto size = height * width;
|
||||
|
||||
auto arr = new int[static_cast<std::size_t>(size)];
|
||||
for (auto i = 0; i < size; ++i) {
|
||||
arr[i] = i;
|
||||
}
|
||||
|
||||
{
|
||||
auto av = as_multi_span(as_multi_span(arr, 24), dim<3>(), dim<4>(), dim<2>());
|
||||
iterate_second_slice(av);
|
||||
}
|
||||
|
||||
{
|
||||
auto av = as_multi_span(as_multi_span(arr, 24), dim(3), dim<4>(), dim<2>());
|
||||
iterate_second_slice(av);
|
||||
}
|
||||
|
||||
{
|
||||
auto av = as_multi_span(as_multi_span(arr, 24), dim<3>(), dim(4), dim<2>());
|
||||
iterate_second_slice(av);
|
||||
}
|
||||
|
||||
{
|
||||
auto av = as_multi_span(as_multi_span(arr, 24), dim<3>(), dim<4>(), dim(2));
|
||||
iterate_second_slice(av);
|
||||
}
|
||||
delete[] arr;
|
||||
}
|
||||
|
||||
TEST(strided_span_tests, strided_span_conversion)
|
||||
{
|
||||
std::set_terminate([] {
|
||||
std::cerr << "Expected Death. strided_span_conversion";
|
||||
std::abort();
|
||||
});
|
||||
|
||||
// get an multi_span of 'c' values from the list of X's
|
||||
|
||||
struct X
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
X arr[4] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}};
|
||||
|
||||
int s = sizeof(int) / sizeof(byte);
|
||||
auto d2 = 3 * s;
|
||||
auto d1 = narrow_cast<int>(sizeof(int)) * 12 / d2;
|
||||
|
||||
// convert to 4x12 array of bytes
|
||||
auto av = as_multi_span(as_bytes(as_multi_span(&arr[0], 4)), dim(d1), dim(d2));
|
||||
|
||||
EXPECT_TRUE(av.bounds().index_bounds()[0] == 4);
|
||||
EXPECT_TRUE(av.bounds().index_bounds()[1] == 12);
|
||||
|
||||
// get the last 4 columns
|
||||
auto section = av.section({0, 2 * s}, {4, s}); // { { arr[0].c[0], arr[0].c[1], arr[0].c[2],
|
||||
// arr[0].c[3] } , { arr[1].c[0], ... } , ...
|
||||
// }
|
||||
|
||||
// convert to array 4x1 array of integers
|
||||
auto cs = section.as_strided_span<int>(); // { { arr[0].c }, {arr[1].c } , ... }
|
||||
|
||||
EXPECT_TRUE(cs.bounds().index_bounds()[0] == 4);
|
||||
EXPECT_TRUE(cs.bounds().index_bounds()[1] == 1);
|
||||
|
||||
// transpose to 1x4 array
|
||||
strided_bounds<2> reverse_bounds{
|
||||
{cs.bounds().index_bounds()[1], cs.bounds().index_bounds()[0]},
|
||||
{cs.bounds().strides()[1], cs.bounds().strides()[0]}};
|
||||
|
||||
strided_span<int, 2> transposed{cs.data(), cs.bounds().total_size(), reverse_bounds};
|
||||
|
||||
// slice to get a one-dimensional array of c's
|
||||
strided_span<int, 1> result = transposed[0];
|
||||
|
||||
EXPECT_TRUE(result.bounds().index_bounds()[0] == 4);
|
||||
EXPECT_DEATH(result.bounds().index_bounds()[1], deathstring);
|
||||
|
||||
int i = 0;
|
||||
for (auto& num : result) {
|
||||
EXPECT_TRUE(num == arr[i].c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <gsl/gsl_assert> // for Expects, fail_fast (ptr only)
|
||||
#include <gsl/assert> // for Expects, 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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user