aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2018-08-30 11:26:50 -0700
committerElliott Hughes <enh@google.com>2018-08-30 11:30:26 -0700
commit9f5bbf2d4208f1f543fd20d05ac62826d809599d (patch)
tree06a5b757097cae82de4650a1509977702bc2c7b4
parent2077ce50f59fc2559546f901360a173b33f2cf4e (diff)
parent1995e86d1ad70519465374fb4876c6ef7c9f8c61 (diff)
downloadplatform_external_Microsoft-GSL-9f5bbf2d4208f1f543fd20d05ac62826d809599d.tar.gz
platform_external_Microsoft-GSL-9f5bbf2d4208f1f543fd20d05ac62826d809599d.tar.bz2
platform_external_Microsoft-GSL-9f5bbf2d4208f1f543fd20d05ac62826d809599d.zip
Bug: https://issuetracker.google.com/113072504 Change-Id: I44441d1be2d5e40d66c61e9c60f04d6279b2e5f7
-rw-r--r--.clang-format15
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml272
-rw-r--r--CMakeLists.txt63
-rw-r--r--CMakeSettings.json18
-rw-r--r--GSL.natvis2
-rw-r--r--METADATA11
-rw-r--r--README.md3
-rw-r--r--appveyor.yml13
-rw-r--r--include/gsl/gsl177
-rw-r--r--include/gsl/gsl_algorithm18
-rw-r--r--include/gsl/gsl_assert90
-rw-r--r--include/gsl/gsl_byte85
-rw-r--r--include/gsl/gsl_util100
-rw-r--r--include/gsl/multi_span895
-rw-r--r--include/gsl/pointers198
-rw-r--r--include/gsl/span475
-rw-r--r--include/gsl/string_span376
-rw-r--r--samples/gsl_transition130
-rw-r--r--tests/CMakeLists.txt102
-rw-r--r--tests/algorithm_tests.cpp63
-rw-r--r--tests/assertion_tests.cpp10
-rw-r--r--tests/at_tests.cpp35
-rw-r--r--tests/bounds_tests.cpp26
-rw-r--r--tests/byte_tests.cpp33
-rw-r--r--tests/multi_span_tests.cpp294
-rw-r--r--tests/no_exception_ensure_tests.cpp53
-rw-r--r--tests/no_exception_throw_tests.cpp52
-rw-r--r--tests/notnull_tests.cpp223
-rw-r--r--tests/owner_tests.cpp15
-rw-r--r--tests/sloppy_notnull_tests.cpp124
-rw-r--r--tests/span_tests.cpp565
-rw-r--r--tests/strided_span_tests.cpp152
-rw-r--r--tests/string_span_tests.cpp308
-rw-r--r--tests/test.cpp8
-rw-r--r--tests/utils_tests.cpp25
36 files changed, 3296 insertions, 1734 deletions
diff --git a/.clang-format b/.clang-format
index 78696f5..c12d3bf 100644
--- a/.clang-format
+++ b/.clang-format
@@ -5,7 +5,19 @@ IndentWidth: 4
AccessModifierOffset: -4
NamespaceIndentation: Inner
-BreakBeforeBraces: Allman
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterNamespace: true
+ AfterEnum: true
+ AfterStruct: true
+ AfterClass: true
+ SplitEmptyFunction: false
+ AfterControlStatement: true
+ AfterFunction: true
+ AfterUnion: true
+ BeforeElse: true
+
+
AlwaysBreakTemplateDeclarations: true
BreakConstructorInitializersBeforeComma: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
@@ -19,3 +31,4 @@ AlignConsecutiveAssignments: false
AlignTrailingComments: true
SpaceAfterCStyleCast: true
+CommentPragmas: '^ NO-FORMAT:'
diff --git a/.gitignore b/.gitignore
index cbb4a5c..326971f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
CMakeFiles
build
-include/catch
tests/CMakeFiles
tests/Debug
*.opensdf
diff --git a/.travis.yml b/.travis.yml
index 82b8ec2..d583eb9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,154 +2,272 @@
language: cpp
sudo: false
+notifications:
+ email: false
+
+# Use Linux unless specified otherwise
+os: linux
+dist: trusty
cache:
directories:
- - ${TRAVIS_BUILD_DIR}/deps/cmake
- - ${TRAVIS_BUILD_DIR}/deps/llvm-3.5.2/install
- - ${TRAVIS_BUILD_DIR}/deps/llvm-3.6.2/install
- - ${TRAVIS_BUILD_DIR}/deps/llvm-3.7.1/install
- - ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.1/install
- - ${TRAVIS_BUILD_DIR}/deps/llvm-3.9.1/install
+ - ${TRAVIS_BUILD_DIR}/deps
matrix:
include:
- - env: BUILD_TYPE=Debug
+
+ ##########################################################################
+ # Clang on OSX
+ # Travis seems to take longer to start OSX instances,
+ # so leave this first for the overall build to be faster
+ ##########################################################################
+
+ # XCode 8.3
+ - env: COMPILER=clang++ BUILD_TYPE=Debug GSL_CXX_STANDARD=14
os: osx
- osx_image: xcode8
+ osx_image: xcode8.3
compiler: clang
- - env: BUILD_TYPE=Release
+
+ - env: COMPILER=clang++ BUILD_TYPE=Release GSL_CXX_STANDARD=14
+ os: osx
+ osx_image: xcode8.3
+ compiler: clang
+
+ # XCode 9.1
+ - env: COMPILER=clang++ BUILD_TYPE=Debug GSL_CXX_STANDARD=14
os: osx
- osx_image: xcode8
+ osx_image: xcode9.1
compiler: clang
- - env: CLANG_VERSION=3.6 BUILD_TYPE=Debug
- os: linux
+
+ - env: COMPILER=clang++ BUILD_TYPE=Release GSL_CXX_STANDARD=14
+ os: osx
+ osx_image: xcode9.1
+ compiler: clang
+
+ ##########################################################################
+ # Clang on Linux
+ ##########################################################################
+
+ # Clang 3.6
+ - env: COMPILER=clang++-3.6 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang36
apt:
packages:
- clang-3.6
- g++-5
- sources: &sources
+ sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6
- - env: CLANG_VERSION=3.6 BUILD_TYPE=Release
- os: linux
+
+ - env: COMPILER=clang++-3.6 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang36
- - env: CLANG_VERSION=3.7 BUILD_TYPE=Debug
- os: linux
+
+ # Clang 3.7
+ - env: COMPILER=clang++-3.7 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang37
apt:
packages:
- clang-3.7
- g++-5
- sources: &sources
+ sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
- - env: CLANG_VERSION=3.7 BUILD_TYPE=Release
- os: linux
+
+ - env: COMPILER=clang++-3.7 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang37
- - env: CLANG_VERSION=3.8 BUILD_TYPE=Debug
- os: linux
+
+ # Clang 3.8
+ - env: COMPILER=clang++-3.8 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang38
apt:
packages:
- clang-3.8
- g++-5
- sources: &sources
+ sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
- - env: CLANG_VERSION=3.8 BUILD_TYPE=Release
- os: linux
+
+ - env: COMPILER=clang++-3.8 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang38
- - env: CLANG_VERSION=3.9 BUILD_TYPE=Debug
- os: linux
+
+ # Clang 3.9
+ - env: COMPILER=clang++-3.9 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang39
apt:
packages:
- clang-3.9
- g++-5
- sources: &sources
+ sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
- - env: CLANG_VERSION=3.9 BUILD_TYPE=Release
- os: linux
+
+ - env: COMPILER=clang++-3.9 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang39
- - env: GCC_VERSION=5 BUILD_TYPE=Debug
- os: linux
+
+ # Clang 4.0
+ - env: COMPILER=clang++-4.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
+ addons: &clang40
+ apt:
+ packages:
+ - clang-4.0
+ - g++-5
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-4.0
+
+ - env: COMPILER=clang++-4.0 BUILD_TYPE=Release GSL_CXX_STANDARD=14
+ addons: *clang40
+
+ # Clang 5.0
+ - env: COMPILER=clang++-5.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
+ addons: &clang50
+ apt:
+ packages:
+ - clang-5.0
+ - g++-7
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-5.0
+ - sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main'
+ key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
+
+ - env: COMPILER=clang++-5.0 BUILD_TYPE=Release GSL_CXX_STANDARD=14
+ addons: *clang50
+
+ - env: COMPILER=clang++-5.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
+ addons: *clang50
+
+ - env: COMPILER=clang++-5.0 BUILD_TYPE=Release GSL_CXX_STANDARD=17
+ addons: *clang50
+
+ # Clang 6.0
+ - env: COMPILER=clang++-6.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
+ addons: &clang60
+ apt:
+ packages:
+ - clang-6.0
+ - g++-7
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-6.0
+ - sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-6.0 main'
+ key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
+
+ - env: COMPILER=clang++-6.0 BUILD_TYPE=Release GSL_CXX_STANDARD=14
+ addons: *clang60
+
+ # Clang 6.0 c++17
+ - env: COMPILER=clang++-6.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
+ addons: *clang60
+
+ - env: COMPILER=clang++-6.0 BUILD_TYPE=Release GSL_CXX_STANDARD=17
+ addons: *clang60
+
+ ##########################################################################
+ # GCC on Linux
+ ##########################################################################
+
+ # GCC 5
+ - env: COMPILER=g++-5 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &gcc5
apt:
packages: g++-5
- sources: *sources
- - env: GCC_VERSION=5 BUILD_TYPE=Release
- os: linux
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - env: COMPILER=g++-5 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *gcc5
- - env: GCC_VERSION=6 BUILD_TYPE=Debug
- os: linux
+
+ # GCC 6
+ - env: COMPILER=g++-6 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &gcc6
apt:
packages: g++-6
- sources: *sources
- - env: GCC_VERSION=6 BUILD_TYPE=Release
- os: linux
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - env: COMPILER=g++-6 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *gcc6
+ # GCC 7
+ - env: COMPILER=g++-7 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
+ addons: &gcc7
+ apt:
+ packages: g++-7
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - env: COMPILER=g++-7 BUILD_TYPE=Release GSL_CXX_STANDARD=14
+ addons: *gcc7
+
+ # GCC 7 c++17
+ - env: COMPILER=g++-7 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
+ addons: *gcc7
+
+ - env: COMPILER=g++-7 BUILD_TYPE=Release GSL_CXX_STANDARD=17
+ addons: *gcc7
+
install:
- - if [[ -n "$CLANG_VERSION" ]]; then export CXX=clang++-$CLANG_VERSION CC=clang-$CLANG_VERSION; fi
- - if [[ -n "$GCC_VERSION" ]]; then export CXX=g++-$GCC_VERSION CC=gcc-$GCC_VERSION; fi
- - JOBS=2
+ # Set the ${CXX} variable properly
+ - export CXX=${COMPILER}
+ - ${CXX} --version
+
+ # Dependencies required by the CI are installed in ${TRAVIS_BUILD_DIR}/deps/
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- - mkdir -p "${DEPS_DIR}" && cd "${DEPS_DIR}"
+ - mkdir -p "${DEPS_DIR}"
+ - cd "${DEPS_DIR}"
+
+ # Travis machines have 2 cores
+ - JOBS=2
############################################################################
# Install a recent CMake (unless already installed on OS X)
############################################################################
+ - CMAKE_VERSION=3.7.2
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
- if [[ -z "$(ls -A ${DEPS_DIR}/cmake/bin)" ]]; then
- CMAKE_URL="https://cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.tar.gz"
- mkdir -p cmake && travis_retry wget --no-check-certificate --quiet -O - "${CMAKE_URL}" | tar --strip-components=1 -xz -C cmake
- fi
- export PATH="${DEPS_DIR}/cmake/bin:${PATH}"
+ CMAKE_URL="https://cmake.org/files/v${CMAKE_VERSION%.[0-9]}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz"
+ mkdir cmake && travis_retry wget --no-check-certificate -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
+ export PATH=${DEPS_DIR}/cmake/bin:${PATH}
else
- if ! brew ls --version cmake &>/dev/null; then brew install cmake; fi
+ brew install cmake || brew upgrade cmake
fi
+ - cmake --version
############################################################################
# [linux]: Install the right version of libc++
############################################################################
- |
- if [[ -n "$CLANG_VERSION" && "${TRAVIS_OS_NAME}" == "linux" && "${STDLIB}" != "libstdc++" ]]; then
- if [[ "$CLANG_VERSION" == "3.5" ]]; then LLVM_VERSION="3.5.2"; fi
- if [[ "$CLANG_VERSION" == "3.6" ]]; then LLVM_VERSION="3.6.2"; fi
- if [[ "$CLANG_VERSION" == "3.7" ]]; then LLVM_VERSION="3.7.1"; fi
- if [[ "$CLANG_VERSION" == "3.8" ]]; then LLVM_VERSION="3.8.1"; fi
- if [[ "$CLANG_VERSION" == "3.9" ]]; then LLVM_VERSION="3.9.1"; fi
- LLVM_ROOT="${DEPS_DIR}/llvm-${LLVM_VERSION}"
+ LLVM_INSTALL=${DEPS_DIR}/llvm/install
+ # if in linux and compiler clang and llvm not installed
+ if [[ "${TRAVIS_OS_NAME}" == "linux" && "${CXX%%+*}" == "clang" && -n "$(ls -A ${LLVM_INSTALL})" ]]; then
+ if [[ "${CXX}" == "clang++-3.6" ]]; then LLVM_VERSION="3.6.2";
+ elif [[ "${CXX}" == "clang++-3.7" ]]; then LLVM_VERSION="3.7.1";
+ elif [[ "${CXX}" == "clang++-3.8" ]]; then LLVM_VERSION="3.8.1";
+ elif [[ "${CXX}" == "clang++-3.9" ]]; then LLVM_VERSION="3.9.1";
+ fi
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz"
LIBCXX_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz"
LIBCXXABI_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz"
- if [[ -z "$(ls -A ${LLVM_ROOT}/install/include)" ]]; then
- mkdir -p "${LLVM_ROOT}" "${LLVM_ROOT}/build" "${LLVM_ROOT}/projects/libcxx" "${LLVM_ROOT}/projects/libcxxabi"
- travis_retry wget --quiet -O - "${LLVM_URL}" | tar --strip-components=1 -xJ -C "${LLVM_ROOT}"
- travis_retry wget --quiet -O - "${LIBCXX_URL}" | tar --strip-components=1 -xJ -C "${LLVM_ROOT}/projects/libcxx"
- travis_retry wget --quiet -O - "${LIBCXXABI_URL}" | tar --strip-components=1 -xJ -C "${LLVM_ROOT}/projects/libcxxabi"
- (cd "${LLVM_ROOT}/build" && cmake .. -DCMAKE_CXX_COMPILER="$CXX" -DCMAKE_C_COMPILER="$CC" -DCMAKE_INSTALL_PREFIX="${LLVM_ROOT}/install" -DCMAKE_BUILD_TYPE=$BUILD_TYPE)
- (cd "${LLVM_ROOT}/build/projects/libcxx" && make install -j$JOBS)
- (cd "${LLVM_ROOT}/build/projects/libcxxabi" && make install -j$JOBS)
- fi
- export CXXFLAGS="-I ${LLVM_ROOT}/install/include/c++/v1"
- export LDFLAGS="-L ${LLVM_ROOT}/install/lib -lc++ -lc++abi"
- export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${LLVM_ROOT}/install/lib"
+ mkdir -p llvm llvm/build llvm/projects/libcxx llvm/projects/libcxxabi
+ travis_retry wget -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C llvm
+ travis_retry wget -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxx
+ travis_retry wget -O - ${LIBCXXABI_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxxabi
+ (cd llvm/build && cmake .. -DCMAKE_INSTALL_PREFIX=${LLVM_INSTALL})
+ (cd llvm/build/projects/libcxx && make install -j2)
+ (cd llvm/build/projects/libcxxabi && make install -j2)
+ export CXXFLAGS="-isystem ${LLVM_INSTALL}/include/c++/v1"
+ export LDFLAGS="-L ${LLVM_INSTALL}/lib -l c++ -l c++abi"
+ export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${LLVM_INSTALL}/lib"
fi
before_script:
+ # have CMake to generate build files
- cd "${TRAVIS_BUILD_DIR}"
- - cmake . -Bbuild -DCMAKE_CXX_COMPILER="$CXX" -DCMAKE_C_COMPILER="$CC" -DCMAKE_BUILD_TYPE=$BUILD_TYPE
- - cmake --build build -- -j$JOBS
-
+ - mkdir build && cd build
+ - cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DGSL_CXX_STANDARD=$GSL_CXX_STANDARD
+
script:
- - cd build
- - ctest --output-on-failure -j$JOBS
-
-notifications:
- email: false
+ # build and run tests
+ - cmake --build . -- -j${JOBS}
+ - ctest --output-on-failure -j${JOBS}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e62a1d6..b0de85d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,27 +3,39 @@ cmake_minimum_required(VERSION 3.1.3)
project(GSL CXX)
include(ExternalProject)
-find_package(Git REQUIRED)
+find_package(Git)
# 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_MAJOR_VERSION VERSION_LESS 3.7.9)
- if (NOT MSVC)
- include(CheckCXXCompilerFlag)
- CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
- if(COMPILER_SUPPORTS_CXX14)
- target_compile_options(GSL INTERFACE "-std=c++14")
- else()
- message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.")
- endif()
+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 ()
- # set the GSL library to be compiled only with c++14
- target_compile_features(GSL INTERFACE cxx_std_14)
+ 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()
@@ -33,6 +45,8 @@ 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
>
)
@@ -43,15 +57,28 @@ target_include_directories(GSL INTERFACE
>
)
-# add natvis file to the library so it will automatically be loaded into Visual Studio
-target_sources(GSL INTERFACE
- ${CMAKE_CURRENT_SOURCE_DIR}/GSL.natvis
-)
+if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9))
+ if (MSVC_IDE)
+ option(VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE)
+ else()
+ set(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(VS_ADD_NATIVE_VISUALIZERS)
+ target_sources(GSL INTERFACE
+ ${CMAKE_CURRENT_SOURCE_DIR}/GSL.natvis
+ )
+ endif()
+endif()
install(
DIRECTORY include/gsl
DESTINATION include
)
-enable_testing()
-add_subdirectory(tests)
+option(GSL_TEST "Generate tests." ${GSL_STANDALONE_PROJECT})
+if (GSL_TEST)
+ enable_testing()
+ add_subdirectory(tests)
+endif ()
diff --git a/CMakeSettings.json b/CMakeSettings.json
new file mode 100644
index 0000000..2e1ad24
--- /dev/null
+++ b/CMakeSettings.json
@@ -0,0 +1,18 @@
+{
+ "configurations": [
+ {
+ "name": "x64-Debug",
+ "generator": "Ninja",
+ "configurationType": "Debug",
+ "inheritEnvironments": [
+ "msvc_x64_x64"
+ ],
+ "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
+ "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
+ "cmakeCommandArgs": "-DGSL_CXX_STANDARD=17",
+ "buildCommandArgs": "-v",
+ "ctestCommandArgs": "",
+ "codeAnalysisRuleset": "CppCoreCheckRules.ruleset"
+ }
+ ]
+} \ No newline at end of file
diff --git a/GSL.natvis b/GSL.natvis
index e40a8c9..a467a17 100644
--- a/GSL.natvis
+++ b/GSL.natvis
@@ -11,7 +11,7 @@
</Type>
<!-- These types are from the gsl_util header. -->
- <Type Name="gsl::final_act&lt;*&gt;">
+ <Type Name="gsl::final_action&lt;*&gt;">
<DisplayString>{{ invoke = {invoke_}, action = {f_} }}</DisplayString>
<Expand>
<Item Name="[invoke]">invoke_</Item>
diff --git a/METADATA b/METADATA
index 20baf83..15717fb 100644
--- a/METADATA
+++ b/METADATA
@@ -1,11 +1,14 @@
name: "Microsoft-GSL"
-description:
- "The Guideline Support Library (GSL) contains functions and types that are suggested for use by the C++ Core Guidelines maintained by the Standard C++ Foundation. This repo contains Microsoft's implementation of GSL."
-
+description: "The Guideline Support Library (GSL) contains functions and types that are suggested for use by the C++ Core Guidelines maintained by the Standard C++ Foundation. This repo contains Microsoft\'s implementation of GSL."
third_party {
url {
type: GIT
value: "https://github.com/Microsoft/GSL"
}
- version: "2b8d20425e990c5a3e9a0158e2cedacbcdf9e522"
+ version: "1995e86d1ad70519465374fb4876c6ef7c9f8c61"
+ last_upgrade_date {
+ year: 2018
+ month: 8
+ day: 30
+ }
}
diff --git a/README.md b/README.md
index 243b7cd..9fea9ae 100644
--- a/README.md
+++ b/README.md
@@ -28,11 +28,14 @@ The test suite that exercises GSL has been built and passes successfully on the
* Windows using Visual Studio 2017
* Windows using Clang/LLVM 3.6
* Windows using GCC 5.1
+* Windows using Intel C++ Compiler 18.0
* GNU/Linux using Clang/LLVM 3.6
* GNU/Linux using GCC 5.1
* OS X Yosemite using Xcode with Apple Clang 7.0.0.7000072
* OS X Yosemite using GCC-5.2.0
* OS X Sierra 10.12.4 using Apple LLVM version 8.1.0 (Clang-802.0.42)
+* OS X El Capitan (10.11) using Xcode with AppleClang 8.0.0.8000042
+* OS X High Sierra 10.13.2 (17C88) using Apple LLVM version 9.0.0 (clang-900.0.39.2)
* FreeBSD 10.x with Clang/LLVM 3.6
> If you successfully port GSL to another platform, we would love to hear from you. Please submit an issue to let us know. Also please consider
diff --git a/appveyor.yml b/appveyor.yml
index d978a5d..2fc8a16 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -12,6 +12,16 @@ image:
- Visual Studio 2015
- Visual Studio 2017
+environment:
+ matrix:
+ - GSL_CXX_STANDARD: 14
+ - GSL_CXX_STANDARD: 17
+
+matrix:
+ exclude:
+ - image: Visual Studio 2015
+ GSL_CXX_STANDARD: 17
+
cache:
- C:\cmake-3.8.0-win32-x86
@@ -27,6 +37,7 @@ before_build:
- ps: |
mkdir build
cd build
+
if ("$env:APPVEYOR_JOB_NAME" -match "Image: Visual Studio 2015") {
$env:generator="Visual Studio 14 2015"
} else {
@@ -36,7 +47,7 @@ before_build:
$env:generator="$env:generator Win64"
}
echo generator="$env:generator"
- cmake .. -G "$env:generator"
+ cmake .. -G "$env:generator" -DGSL_CXX_STANDARD="$env:GSL_CXX_STANDARD"
build_script:
- cmake --build . --config %CONFIGURATION% -- /m /v:minimal
diff --git a/include/gsl/gsl b/include/gsl/gsl
index 4cb03c5..55862eb 100644
--- a/include/gsl/gsl
+++ b/include/gsl/gsl
@@ -14,177 +14,16 @@
//
///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
#ifndef GSL_GSL_H
#define GSL_GSL_H
-#include <gsl/gsl_assert> // Ensures/Expects
-#include <gsl/gsl_util> // finally()/narrow()/narrow_cast()...
-#include <gsl/multi_span> // multi_span, strided_span...
-#include <gsl/span> // span
-#include <gsl/string_span> // zstring, string_span, zstring_builder...
-
-#include <iostream>
-#include <memory>
-#include <type_traits>
-
-#if defined(_MSC_VER) && _MSC_VER < 1910
-#pragma push_macro("constexpr")
-#define constexpr /*constexpr*/
-
-#endif // defined(_MSC_VER) && _MSC_VER < 1910
-
-namespace gsl
-{
-
-//
-// GSL.owner: ownership pointers
-//
-using std::unique_ptr;
-using std::shared_ptr;
-
-//
-// owner
-//
-// 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
-//
-template <class T, class = std::enable_if_t<std::is_pointer<T>::value>>
-using owner = T;
-
-//
-// not_null
-//
-// Restricts a pointer or smart pointer to only hold non-null values.
-//
-// Has zero size overhead over T.
-//
-// If T is a pointer (i.e. T == U*) then
-// - allow construction from U*
-// - disallow construction from nullptr_t
-// - disallow default construction
-// - ensure construction from null U* fails
-// - allow implicit conversion to U*
-//
-template <class T>
-class not_null
-{
-public:
- static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
-
- template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
- constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
- {
- Expects(ptr_ != nullptr);
- }
-
- template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
- constexpr not_null(const not_null<U>& other) : not_null(other.get())
- {
- }
-
- not_null(const not_null& other) = default;
- not_null& operator=(const not_null& other) = default;
-
- constexpr T get() const
- {
- Ensures(ptr_ != nullptr);
- return ptr_;
- }
-
- constexpr operator T() const { return get(); }
- constexpr T operator->() const { return get(); }
- constexpr decltype(auto) operator*() const { return *get(); }
-
- // prevents compilation when someone attempts to assign a null pointer constant
- not_null(std::nullptr_t) = delete;
- not_null& operator=(std::nullptr_t) = delete;
-
- // unwanted operators...pointers only point to single objects!
- not_null& operator++() = delete;
- not_null& operator--() = delete;
- not_null operator++(int) = delete;
- not_null operator--(int) = delete;
- not_null& operator+=(std::ptrdiff_t) = delete;
- not_null& operator-=(std::ptrdiff_t) = delete;
- void operator[](std::ptrdiff_t) const = delete;
-
-private:
- T ptr_;
-};
-
-template <class T>
-std::ostream& operator<<(std::ostream& os, const not_null<T>& val)
-{
- os << val.get();
- return os;
-}
-
-template <class T, class U>
-auto operator==(const not_null<T>& lhs, const not_null<U>& rhs) -> 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) -> 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) -> 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) -> 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) -> 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) -> decltype(lhs.get() >= rhs.get())
-{
- return lhs.get() >= rhs.get();
-}
-
-// more unwanted operators
-template <class T, class U>
-std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete;
-template <class T>
-not_null<T> operator-(const not_null<T>&, std::ptrdiff_t) = delete;
-template <class T>
-not_null<T> operator+(const not_null<T>&, std::ptrdiff_t) = delete;
-template <class T>
-not_null<T> operator+(std::ptrdiff_t, const not_null<T>&) = delete;
-
-} // namespace gsl
-
-namespace std
-{
-template <class T>
-struct hash<gsl::not_null<T>>
-{
- std::size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
-};
-
-} // namespace std
-
-#if defined(_MSC_VER) && _MSC_VER < 1910
-#undef constexpr
-#pragma pop_macro("constexpr")
-
-#endif // defined(_MSC_VER) && _MSC_VER < 1910
+#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...
#endif // GSL_GSL_H
diff --git a/include/gsl/gsl_algorithm b/include/gsl/gsl_algorithm
index 6e81e50..c2ba31f 100644
--- a/include/gsl/gsl_algorithm
+++ b/include/gsl/gsl_algorithm
@@ -14,30 +14,29 @@
//
///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
#ifndef GSL_ALGORITHM_H
#define GSL_ALGORITHM_H
-#include <gsl/span>
+#include <gsl/gsl_assert> // for Expects
+#include <gsl/span> // for dynamic_extent, span
-#include <algorithm>
+#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
-// blanket turn off warnings from CppCoreCheck for now
-// so people aren't annoyed by them when running the tool.
-// more targeted suppressions will be added in a future update to the GSL
-#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
#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::ptrdiff_t SrcExtent, class DestElementType,
std::ptrdiff_t DestExtent>
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
@@ -49,6 +48,7 @@ void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, 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());
}
diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert
index 43da231..3c952e6 100644
--- a/include/gsl/gsl_assert
+++ b/include/gsl/gsl_assert
@@ -14,13 +14,35 @@
//
///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
#ifndef GSL_CONTRACTS_H
#define GSL_CONTRACTS_H
#include <exception>
-#include <stdexcept>
+#include <stdexcept> // for logic_error
+
+//
+// make suppress attributes parse for some compilers
+// Hopefully temporary until suppresion standardization occurs
+//
+#if defined (_MSC_VER)
+#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
+#else
+#if defined(__clang__)
+#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
+#else
+#define GSL_SUPPRESS(x)
+#endif // __clang__
+#endif // _MSC_VER
+
+//
+// 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(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
+#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
+#include <intrin.h>
+#define RANGE_CHECKS_FAILURE 0
+#endif
//
// There are three configuration options for this GSL implementation's behavior
@@ -54,12 +76,10 @@
//
#ifdef _MSC_VER
#define GSL_ASSUME(cond) __assume(cond)
-#elif defined(__clang__)
-#define GSL_ASSUME(cond) __builtin_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))
+#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0)
#endif
//
@@ -72,18 +92,68 @@ struct fail_fast : public std::logic_error
{
explicit fail_fast(char const* const message) : std::logic_error(message) {}
};
-}
+
+namespace details
+{
+#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
+
+ typedef void (__cdecl *terminate_handler)();
+
+ GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
+ [[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
+
+ [[noreturn]] inline void terminate() noexcept
+ {
+#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
+ (*gsl::details::get_terminate_handler())();
+#else
+ std::terminate();
+#endif
+ }
+
+#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
+
+ template <typename Exception>
+ [[noreturn]] void throw_exception(Exception&&) noexcept
+ {
+ gsl::details::terminate();
+ }
+
+#else
+
+ template <typename Exception>
+ [[noreturn]] void throw_exception(Exception&& exception)
+ {
+ throw std::forward<Exception>(exception);
+ }
+
+#endif
+
+} // namespace details
+} // namespace gsl
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) \
- : throw gsl::fail_fast("GSL: " type " failure at " __FILE__ \
- ": " GSL_STRINGIFY(__LINE__)))
+ : gsl::details::throw_exception(gsl::fail_fast( \
+ "GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__))))
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
-#define GSL_CONTRACT_CHECK(type, cond) (GSL_LIKELY(cond) ? static_cast<void>(0) : std::terminate())
+#define GSL_CONTRACT_CHECK(type, cond) \
+ (GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
diff --git a/include/gsl/gsl_byte b/include/gsl/gsl_byte
index 1e2e3be..bc18886 100644
--- a/include/gsl/gsl_byte
+++ b/include/gsl/gsl_byte
@@ -14,56 +14,81 @@
//
///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
#ifndef GSL_BYTE_H
#define GSL_BYTE_H
+//
+// make suppress attributes work for some compilers
+// Hopefully temporary until suppresion standardization occurs
+//
+#if defined(_MSC_VER)
+#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
+#else
+#if defined(__clang__)
+#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
+#else
+#define GSL_SUPPRESS(x)
+#endif // __clang__
+#endif // _MSC_VER
+
#include <type_traits>
#ifdef _MSC_VER
#pragma warning(push)
-// don't warn about function style casts in byte related operators
-#pragma warning(disable : 26493)
+// 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 _MSC_VER >= 1911 && (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE)
+#if defined(_HAS_STD_BYTE) && _HAS_STD_BYTE
#define GSL_USE_STD_BYTE 1
-#else // _MSC_VER >= 1911 && (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE)
+#else // defined(_HAS_STD_BYTE) && _HAS_STD_BYTE
#define GSL_USE_STD_BYTE 0
-#endif // _MSC_VER >= 1911 && (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE)
+#endif // defined(_HAS_STD_BYTE) && _HAS_STD_BYTE
#endif // GSL_USE_STD_BYTE
#else // _MSC_VER
#ifndef GSL_USE_STD_BYTE
// this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte
-#if defined(__cplusplus) && (__cplusplus >= 201703L)
+// also check if libc++ version is sufficient (> 5.0) or libstc++ 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
#include <cstddef>
-#else // defined(__cplusplus) && (__cplusplus >= 201703L)
+#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)
+#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
+#endif // _MSC_VER
+
+// Use __may_alias__ attribute on gcc and clang
+#if defined __clang__ || (__GNUC__ > 5)
+#define byte_may_alias __attribute__((__may_alias__))
+#else // defined __clang__ || defined __GNUC__
+#define byte_may_alias
+#endif // defined __clang__ || defined __GNUC__
namespace gsl
{
#if GSL_USE_STD_BYTE
-
using std::byte;
using std::to_integer;
@@ -71,68 +96,68 @@ using std::to_integer;
// This is a simple definition for now that allows
// use of byte within span<> to be standards-compliant
-enum class byte : unsigned char
+enum class byte_may_alias byte : unsigned char
{
};
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
-inline constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
+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>>
-inline constexpr byte operator<<(byte b, IntegerType shift) noexcept
+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>>
-inline constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
+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>>
-inline constexpr byte operator>>(byte b, IntegerType shift) noexcept
+constexpr byte operator>>(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) >> shift);
}
-inline constexpr byte& operator|=(byte& l, byte r) noexcept
+constexpr byte& operator|=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
-inline constexpr byte operator|(byte l, byte r) noexcept
+constexpr byte operator|(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
-inline constexpr byte& operator&=(byte& l, byte r) noexcept
+constexpr byte& operator&=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
-inline constexpr byte operator&(byte l, byte r) noexcept
+constexpr byte operator&(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
-inline constexpr byte& operator^=(byte& l, byte r) noexcept
+constexpr byte& operator^=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
-inline constexpr byte operator^(byte l, byte r) noexcept
+constexpr byte operator^(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
-inline constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
+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>>
-inline constexpr IntegerType to_integer(byte b) noexcept
+constexpr IntegerType to_integer(byte b) noexcept
{
return static_cast<IntegerType>(b);
}
@@ -140,7 +165,7 @@ inline constexpr IntegerType to_integer(byte b) noexcept
#endif // GSL_USE_STD_BYTE
template <bool E, typename T>
-inline constexpr byte to_byte_impl(T t) noexcept
+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. "
@@ -148,19 +173,21 @@ inline constexpr byte to_byte_impl(T t) noexcept
return static_cast<byte>(t);
}
template <>
-inline constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
+// 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>
-inline constexpr byte to_byte(T t) noexcept
+constexpr byte to_byte(T t) noexcept
{
return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
}
template <int I>
-inline constexpr byte to_byte() noexcept
+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");
diff --git a/include/gsl/gsl_util b/include/gsl/gsl_util
index 60ef498..542bbaa 100644
--- a/include/gsl/gsl_util
+++ b/include/gsl/gsl_util
@@ -14,17 +14,17 @@
//
///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
#ifndef GSL_UTIL_H
#define GSL_UTIL_H
-#include <gsl/gsl_assert> // Ensures/Expects
+#include <gsl/gsl_assert> // for Expects
#include <array>
-#include <exception>
-#include <type_traits>
-#include <utility>
+#include <cstddef> // for ptrdiff_t, size_t
+#include <exception> // for exception
+#include <initializer_list> // for initializer_list
+#include <type_traits> // for is_signed, integral_constant
+#include <utility> // for forward
#if defined(_MSC_VER)
@@ -34,20 +34,8 @@
#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
-#endif // _MSC_VER < 1910
-#endif // _MSC_VER
-
-// AFAIK there's no way to detect in GCC or MSVC. GCC has an __EXCEPTIONS macro,
-// but that is only defined if `-fexceptions` is *explicitly* passed on the
-// command line; defaulting to exceptions enabled will not set this macro.
-//
-// Non-Clang users will need to defined GSL_NO_EXCEPTIONS explicitly from the
-// command line if they are building with exceptions disabled.
-#if defined(__clang__) && !__has_feature(cxx_exceptions)
-// If building with -fno-exceptions, we'll fall back to gsl::Ensures in places
-// where we would have normally thrown an exception.
-#define GSL_NO_EXCEPTIONS
-#endif // defined(__has_feature) && !__has_feature(cxx_exceptions)
+#endif // _MSC_VER < 1910
+#endif // _MSC_VER
namespace gsl
{
@@ -55,47 +43,53 @@ namespace gsl
// GSL.util: utilities
//
-// final_act allows you to ensure something gets run at the end of a scope
+// 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_act
+class final_action
{
public:
- explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {}
+ explicit final_action(F f) noexcept : f_(std::move(f)) {}
- final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_)
+ final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_)
{
other.invoke_ = false;
}
- final_act(const final_act&) = delete;
- final_act& operator=(const final_act&) = delete;
+ final_action(const final_action&) = delete;
+ final_action& operator=(const final_action&) = delete;
+ final_action& operator=(final_action&&) = delete;
- ~final_act() noexcept
+ GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
+ ~final_action() noexcept
{
if (invoke_) f_();
}
private:
F f_;
- bool invoke_;
+ bool invoke_{true};
};
-// finally() - convenience function to generate a final_act
+// finally() - convenience function to generate a final_action
template <class F>
-inline final_act<F> finally(const F& f) noexcept
+final_action<F> finally(const F& f) noexcept
{
- return final_act<F>(f);
+ return final_action<F>(f);
}
template <class F>
-inline final_act<F> finally(F&& f) noexcept
+final_action<F> finally(F&& f) noexcept
{
- return final_act<F>(std::forward<F>(f));
+ return final_action<F>(std::forward<F>(f));
}
// narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U>
-inline constexpr T narrow_cast(U&& u) noexcept
+GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+constexpr T narrow_cast(U&& u) noexcept
{
return static_cast<T>(std::forward<U>(u));
}
@@ -111,21 +105,18 @@ namespace details
: public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
{
};
-}
+} // namespace details
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
-inline T narrow(U u)
+GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
+T narrow(U u) noexcept(false)
{
T t = narrow_cast<T>(u);
-#ifndef GSL_NO_EXCEPTIONS
- if (static_cast<U>(t) != u) throw narrowing_error();
+ if (static_cast<U>(t) != u) gsl::details::throw_exception(narrowing_error());
if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
- throw narrowing_error();
-#else
- Ensures(static_cast<U>(t) == u);
- Ensures(!(!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{}))));
-#endif
+ gsl::details::throw_exception(narrowing_error());
return t;
}
@@ -133,25 +124,30 @@ inline T narrow(U u)
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
//
template <class T, std::size_t N>
-inline constexpr T& at(T (&arr)[N], const std::ptrdiff_t index)
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
+constexpr T& at(T (&arr)[N], const index i)
{
- Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(N));
- return arr[static_cast<std::size_t>(index)];
+ Expects(i >= 0 && i < narrow_cast<index>(N));
+ return arr[narrow_cast<std::size_t>(i)];
}
template <class Cont>
-inline constexpr auto at(Cont& cont, const std::ptrdiff_t index) -> decltype(cont[cont.size()])
+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(index >= 0 && index < narrow_cast<std::ptrdiff_t>(cont.size()));
+ Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
using size_type = decltype(cont.size());
- return cont[static_cast<size_type>(index)];
+ return cont[narrow_cast<size_type>(i)];
}
template <class T>
-inline constexpr T at(const std::initializer_list<T> cont, const std::ptrdiff_t index)
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+constexpr T at(const std::initializer_list<T> cont, const index i)
{
- Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(cont.size()));
- return *(cont.begin() + index);
+ Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
+ return *(cont.begin() + i);
}
} // namespace gsl
diff --git a/include/gsl/multi_span b/include/gsl/multi_span
index 5e0eaac..c8f4aae 100644
--- a/include/gsl/multi_span
+++ b/include/gsl/multi_span
@@ -14,27 +14,27 @@
//
///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
#ifndef GSL_MULTI_SPAN_H
#define GSL_MULTI_SPAN_H
-#include <gsl/gsl_assert>
-#include <gsl/gsl_byte>
-#include <gsl/gsl_util>
+#include <gsl/gsl_assert> // for Expects
+#include <gsl/gsl_byte> // for byte
+#include <gsl/gsl_util> // for narrow_cast
-#include <algorithm>
-#include <array>
+#include <algorithm> // for transform, lexicographical_compare
+#include <array> // for array
#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <functional>
-#include <iterator>
-#include <limits>
+#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
+#include <cstdint> // for PTRDIFF_MAX
+#include <functional> // for divides, multiplies, minus, negate, plus
+#include <initializer_list> // for initializer_list
+#include <iterator> // for iterator, random_access_iterator_tag
+#include <limits> // for numeric_limits
#include <new>
#include <numeric>
#include <stdexcept>
-#include <type_traits>
+#include <string> // for basic_string
+#include <type_traits> // for enable_if_t, remove_cv_t, is_same, is_co...
#include <utility>
#ifdef _MSC_VER
@@ -44,6 +44,12 @@
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4702) // unreachable code
+// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
+#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
+#pragma warning(disable : 26473) // in some instantiations we cast to the same type
+#pragma warning(disable : 26490) // TODO: bug in parser - attributes and templates
+#pragma warning(disable : 26465) // TODO: bug - suppression does not work on template functions
+
#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
@@ -51,11 +57,15 @@
#endif // _MSC_VER < 1910
#endif // _MSC_VER
-#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
-#define GSL_NOEXCEPT /*noexcept*/
-#else
-#define GSL_NOEXCEPT noexcept
-#endif // GSL_THROW_ON_CONTRACT_VIOLATION
+// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t)
+// While there is a conversion from signed to unsigned, it happens at
+// compiletime, so the compiler wouldn't have to warn indiscriminently, but
+// could check if the source value actually doesn't fit into the target type
+// and only warn in those cases.
+#if __GNUC__ > 6
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
namespace gsl
{
@@ -82,15 +92,15 @@ namespace details
std::is_integral<T>::value && are_integral<Ts...>::value>
{
};
-}
+} // namespace details
template <std::size_t Rank>
-class index final
+class multi_span_index final
{
static_assert(Rank > 0, "Rank must be greater than 0!");
template <std::size_t OtherRank>
- friend class index;
+ friend class multi_span_index;
public:
static const std::size_t rank = Rank;
@@ -99,24 +109,27 @@ public:
using reference = std::add_lvalue_reference_t<value_type>;
using const_reference = std::add_lvalue_reference_t<std::add_const_t<value_type>>;
- constexpr index() GSL_NOEXCEPT {}
+ constexpr multi_span_index() noexcept {}
- constexpr index(const value_type (&values)[Rank]) GSL_NOEXCEPT
+ constexpr multi_span_index(const value_type (&values)[Rank]) noexcept
{
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
std::copy(values, values + Rank, elems);
}
template <typename... Ts, typename = std::enable_if_t<(sizeof...(Ts) == Rank) &&
details::are_integral<Ts...>::value>>
- constexpr index(Ts... ds) GSL_NOEXCEPT : elems{narrow_cast<value_type>(ds)...}
- {
- }
+ constexpr multi_span_index(Ts... ds) noexcept : elems{narrow_cast<value_type>(ds)...}
+ {}
- constexpr index(const index& other) GSL_NOEXCEPT = default;
+ constexpr multi_span_index(const multi_span_index& other) noexcept = default;
- constexpr index& operator=(const index& rhs) GSL_NOEXCEPT = default;
+ constexpr multi_span_index& operator=(const multi_span_index& rhs) noexcept = default;
// Preconditions: component_idx < rank
+ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
constexpr reference operator[](std::size_t component_idx)
{
Expects(component_idx < Rank); // Component index must be less than rank
@@ -124,82 +137,98 @@ public:
}
// Preconditions: component_idx < rank
- constexpr const_reference operator[](std::size_t component_idx) const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr const_reference operator[](std::size_t component_idx) const
{
Expects(component_idx < Rank); // Component index must be less than rank
return elems[component_idx];
}
- constexpr bool operator==(const index& rhs) const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
+ constexpr bool operator==(const multi_span_index& rhs) const
{
return std::equal(elems, elems + rank, rhs.elems);
}
- constexpr bool operator!=(const index& rhs) const GSL_NOEXCEPT { return !(this == rhs); }
+ constexpr bool operator!=(const multi_span_index& rhs) const
+ {
+ return !(*this == rhs);
+ }
- constexpr index operator+() const GSL_NOEXCEPT { return *this; }
+ constexpr multi_span_index operator+() const noexcept { return *this; }
- constexpr index operator-() const GSL_NOEXCEPT
+ constexpr multi_span_index operator-() const
{
- index ret = *this;
+ multi_span_index ret = *this;
std::transform(ret, ret + rank, ret, std::negate<value_type>{});
return ret;
}
- constexpr index operator+(const index& rhs) const GSL_NOEXCEPT
+ constexpr multi_span_index operator+(const multi_span_index& rhs) const
{
- index ret = *this;
+ multi_span_index ret = *this;
ret += rhs;
return ret;
}
- constexpr index operator-(const index& rhs) const GSL_NOEXCEPT
+ constexpr multi_span_index operator-(const multi_span_index& rhs) const
{
- index ret = *this;
+ multi_span_index ret = *this;
ret -= rhs;
return ret;
}
- constexpr index& operator+=(const index& rhs) GSL_NOEXCEPT
+ constexpr multi_span_index& operator+=(const multi_span_index& rhs)
{
- std::transform(elems, elems + rank, rhs.elems, elems, std::plus<value_type>{});
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
+ std::transform(elems, elems + rank, rhs.elems, elems,
+ std::plus<value_type>{});
return *this;
}
- constexpr index& operator-=(const index& rhs) GSL_NOEXCEPT
+ constexpr multi_span_index& operator-=(const multi_span_index& rhs)
{
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
std::transform(elems, elems + rank, rhs.elems, elems, std::minus<value_type>{});
return *this;
}
- constexpr index operator*(value_type v) const GSL_NOEXCEPT
+ constexpr multi_span_index operator*(value_type v) const
{
- index ret = *this;
+ multi_span_index ret = *this;
ret *= v;
return ret;
}
- constexpr index operator/(value_type v) const GSL_NOEXCEPT
+ constexpr multi_span_index operator/(value_type v) const
{
- index ret = *this;
+ multi_span_index ret = *this;
ret /= v;
return ret;
}
- friend constexpr index operator*(value_type v, const index& rhs) GSL_NOEXCEPT
+ friend constexpr multi_span_index operator*(value_type v, const multi_span_index& rhs)
{
return rhs * v;
}
- constexpr index& operator*=(value_type v) GSL_NOEXCEPT
+ constexpr multi_span_index& operator*=(value_type v)
{
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
std::transform(elems, elems + rank, elems,
[v](value_type x) { return std::multiplies<value_type>{}(x, v); });
return *this;
}
- constexpr index& operator/=(value_type v) GSL_NOEXCEPT
+ constexpr multi_span_index& operator/=(value_type v)
{
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
std::transform(elems, elems + rank, elems,
[v](value_type x) { return std::divides<value_type>{}(x, v); });
return *this;
@@ -213,43 +242,43 @@ private:
struct static_bounds_dynamic_range_t
{
- template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
- constexpr operator T() const GSL_NOEXCEPT
+ template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
+ constexpr operator T() const noexcept
{
return narrow_cast<T>(-1);
}
};
-constexpr bool operator==(static_bounds_dynamic_range_t, static_bounds_dynamic_range_t) GSL_NOEXCEPT
+constexpr bool operator==(static_bounds_dynamic_range_t, static_bounds_dynamic_range_t) noexcept
{
return true;
}
-constexpr bool operator!=(static_bounds_dynamic_range_t, static_bounds_dynamic_range_t) GSL_NOEXCEPT
+constexpr bool operator!=(static_bounds_dynamic_range_t, static_bounds_dynamic_range_t) noexcept
{
return false;
}
-template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
-constexpr bool operator==(static_bounds_dynamic_range_t, T other) GSL_NOEXCEPT
+template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
+constexpr bool operator==(static_bounds_dynamic_range_t, T other) noexcept
{
return narrow_cast<T>(-1) == other;
}
-template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
-constexpr bool operator==(T left, static_bounds_dynamic_range_t right) GSL_NOEXCEPT
+template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
+constexpr bool operator==(T left, static_bounds_dynamic_range_t right) noexcept
{
return right == left;
}
-template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
-constexpr bool operator!=(static_bounds_dynamic_range_t, T other) GSL_NOEXCEPT
+template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
+constexpr bool operator!=(static_bounds_dynamic_range_t, T other) noexcept
{
return narrow_cast<T>(-1) != other;
}
-template <typename T, typename Dummy = std::enable_if_t<std::is_integral<T>::value>>
-constexpr bool operator!=(T left, static_bounds_dynamic_range_t right) GSL_NOEXCEPT
+template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
+constexpr bool operator!=(T left, static_bounds_dynamic_range_t right) noexcept
{
return right != left;
}
@@ -287,16 +316,14 @@ namespace details
// TODO : following signature is for work around VS bug
template <typename OtherRange>
BoundsRanges(const OtherRange&, bool /* firstLevel */)
- {
- }
+ {}
BoundsRanges(const std::ptrdiff_t* const) {}
- BoundsRanges() = default;
+ BoundsRanges() noexcept = default;
template <typename T, std::size_t Dim>
void serialize(T&) const
- {
- }
+ {}
template <typename T, std::size_t Dim>
size_type linearize(const T&) const
@@ -310,11 +337,11 @@ namespace details
return -1;
}
- size_type elementNum(std::size_t) const GSL_NOEXCEPT { return 0; }
+ size_type elementNum(std::size_t) const noexcept { return 0; }
- size_type totalSize() const GSL_NOEXCEPT { return TotalSize; }
+ size_type totalSize() const noexcept { return TotalSize; }
- bool operator==(const BoundsRanges&) const GSL_NOEXCEPT { return true; }
+ bool operator==(const BoundsRanges&) const noexcept { return true; }
};
template <std::ptrdiff_t... RestRanges>
@@ -331,21 +358,22 @@ namespace details
size_type m_bound;
public:
+ GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
BoundsRanges(const std::ptrdiff_t* const arr)
: Base(arr + 1), m_bound(*arr * this->Base::totalSize())
{
Expects(0 <= *arr);
}
- BoundsRanges() : m_bound(0) {}
+ BoundsRanges() noexcept : m_bound(0) {}
template <std::ptrdiff_t OtherRange, std::ptrdiff_t... RestOtherRanges>
BoundsRanges(const BoundsRanges<OtherRange, RestOtherRanges...>& other,
bool /* firstLevel */ = true)
: Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
, m_bound(other.totalSize())
- {
- }
+ {}
template <typename T, std::size_t Dim = 0>
void serialize(T& arr) const
@@ -355,6 +383,7 @@ namespace details
}
template <typename T, std::size_t Dim = 0>
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
size_type linearize(const T& arr) const
{
const size_type index = this->Base::totalSize() * arr[Dim];
@@ -371,11 +400,19 @@ namespace details
return cur < m_bound ? cur + last : -1;
}
- size_type totalSize() const GSL_NOEXCEPT { return m_bound; }
+ GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
+ size_type totalSize() const noexcept
+ {
+ return m_bound;
+ }
- size_type elementNum() const GSL_NOEXCEPT { return totalSize() / this->Base::totalSize(); }
+ GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
+ size_type elementNum() const noexcept
+ {
+ return totalSize() / this->Base::totalSize();
+ }
- size_type elementNum(std::size_t dim) const GSL_NOEXCEPT
+ size_type elementNum(std::size_t dim) const noexcept
{
if (dim > 0)
return this->Base::elementNum(dim - 1);
@@ -383,7 +420,7 @@ namespace details
return elementNum();
}
- bool operator==(const BoundsRanges& rhs) const GSL_NOEXCEPT
+ bool operator==(const BoundsRanges& rhs) const noexcept
{
return m_bound == rhs.m_bound &&
static_cast<const Base&>(*this) == static_cast<const Base&>(rhs);
@@ -409,6 +446,7 @@ namespace details
bool firstLevel = true)
: Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
{
+ GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
(void) firstLevel;
}
@@ -422,7 +460,10 @@ namespace details
template <typename T, std::size_t Dim = 0>
size_type linearize(const T& arr) const
{
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
Expects(arr[Dim] >= 0 && arr[Dim] < CurrentRange); // Index is out of range
+
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
return this->Base::totalSize() * arr[Dim] +
this->Base::template linearize<T, Dim + 1>(arr);
}
@@ -436,11 +477,20 @@ namespace details
return this->Base::totalSize() * arr[Dim] + last;
}
- size_type totalSize() const GSL_NOEXCEPT { return CurrentRange * this->Base::totalSize(); }
+ GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
+ size_type totalSize() const noexcept
+ {
+ return CurrentRange * this->Base::totalSize();
+ }
- size_type elementNum() const GSL_NOEXCEPT { return CurrentRange; }
+ GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
+ size_type elementNum() const noexcept
+ {
+ return CurrentRange;
+ }
- size_type elementNum(std::size_t dim) const GSL_NOEXCEPT
+ GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
+ size_type elementNum(std::size_t dim) const noexcept
{
if (dim > 0)
return this->Base::elementNum(dim - 1);
@@ -448,7 +498,7 @@ namespace details
return elementNum();
}
- bool operator==(const BoundsRanges& rhs) const GSL_NOEXCEPT
+ bool operator==(const BoundsRanges& rhs) const noexcept
{
return static_cast<const Base&>(*this) == static_cast<const Base&>(rhs);
}
@@ -497,16 +547,18 @@ namespace details
}
template <std::size_t Rank, bool Enabled = (Rank > 1),
- typename Ret = std::enable_if_t<Enabled, index<Rank - 1>>>
- inline constexpr Ret shift_left(const index<Rank>& other) GSL_NOEXCEPT
+ typename Ret = std::enable_if_t<Enabled, multi_span_index<Rank - 1>>>
+ constexpr Ret shift_left(const multi_span_index<Rank>& other) noexcept
{
Ret ret{};
- for (std::size_t i = 0; i < Rank - 1; ++i) {
- ret[i] = other[i + 1];
+ for (std::size_t i = 0; i < Rank - 1; ++i)
+ {
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ ret[i] = other[i + 1];
}
return ret;
}
-}
+} // namespace details
template <typename IndexType>
class bounds_iterator;
@@ -524,7 +576,7 @@ class static_bounds<FirstRange, RestRanges...>
using MyRanges = details::BoundsRanges<FirstRange, RestRanges...>;
MyRanges m_ranges;
- constexpr static_bounds(const MyRanges& range) : m_ranges(range) {}
+ constexpr static_bounds(const MyRanges& range) noexcept : m_ranges(range) {}
template <std::ptrdiff_t... OtherRanges>
friend class static_bounds;
@@ -535,7 +587,7 @@ public:
static const std::ptrdiff_t static_size = MyRanges::TotalSize;
using size_type = std::ptrdiff_t;
- using index_type = index<rank>;
+ using index_type = multi_span_index<rank>;
using const_index_type = std::add_const_t<index_type>;
using iterator = bounds_iterator<const_index_type>;
using const_iterator = bounds_iterator<const_index_type>;
@@ -543,7 +595,8 @@ public:
using sliced_type = static_bounds<RestRanges...>;
using mapping_type = contiguous_mapping_tag;
- constexpr static_bounds(const static_bounds&) = default;
+ constexpr static_bounds(const static_bounds&) noexcept = default;
+ constexpr static_bounds() /*noexcept*/ = default;
template <typename SourceType, typename TargetType, std::size_t Rank>
struct BoundsRangeConvertible2;
@@ -601,8 +654,7 @@ public:
MyRanges::DynamicNum > 0 || other.m_ranges.totalSize() >= m_ranges.totalSize());
}
- constexpr static_bounds(std::initializer_list<size_type> il)
- : m_ranges(static_cast<const std::ptrdiff_t*>(il.begin()))
+ constexpr static_bounds(std::initializer_list<size_type> il) : m_ranges(il.begin())
{
// Size of the initializer list must match the rank of the array
Expects((MyRanges::DynamicNum == 0 && il.size() == 1 && *il.begin() == static_size) ||
@@ -611,33 +663,31 @@ public:
Expects(m_ranges.totalSize() <= PTRDIFF_MAX);
}
- constexpr static_bounds() = default;
-
- constexpr sliced_type slice() const GSL_NOEXCEPT
+ constexpr sliced_type slice() const noexcept
{
return sliced_type{static_cast<const details::BoundsRanges<RestRanges...>&>(m_ranges)};
}
- constexpr size_type stride() const GSL_NOEXCEPT { return rank > 1 ? slice().size() : 1; }
+ constexpr size_type stride() const noexcept { return rank > 1 ? slice().size() : 1; }
- constexpr size_type size() const GSL_NOEXCEPT { return m_ranges.totalSize(); }
+ constexpr size_type size() const noexcept { return m_ranges.totalSize(); }
- constexpr size_type total_size() const GSL_NOEXCEPT { return m_ranges.totalSize(); }
+ constexpr size_type total_size() const noexcept { return m_ranges.totalSize(); }
constexpr size_type linearize(const index_type& idx) const { return m_ranges.linearize(idx); }
- constexpr bool contains(const index_type& idx) const GSL_NOEXCEPT
+ constexpr bool contains(const index_type& idx) const noexcept
{
return m_ranges.contains(idx) != -1;
}
- constexpr size_type operator[](std::size_t index) const GSL_NOEXCEPT
+ constexpr size_type operator[](std::size_t idx) const noexcept
{
- return m_ranges.elementNum(index);
+ return m_ranges.elementNum(idx);
}
template <std::size_t Dim = 0>
- constexpr size_type extent() const GSL_NOEXCEPT
+ constexpr size_type extent() const noexcept
{
static_assert(Dim < rank,
"dimension should be less than rank (dimension count starts from 0)");
@@ -645,7 +695,7 @@ public:
}
template <typename IntType>
- constexpr size_type extent(IntType dim) const GSL_NOEXCEPT
+ constexpr size_type extent(IntType dim) const
{
static_assert(std::is_integral<IntType>::value,
"Dimension parameter must be supplied as an integral type.");
@@ -655,7 +705,7 @@ public:
return m_ranges.elementNum(real_dim);
}
- constexpr index_type index_bounds() const GSL_NOEXCEPT
+ constexpr index_type index_bounds() const noexcept
{
size_type extents[rank] = {};
m_ranges.serialize(extents);
@@ -663,31 +713,30 @@ public:
}
template <std::ptrdiff_t... Ranges>
- constexpr bool operator==(const static_bounds<Ranges...>& rhs) const GSL_NOEXCEPT
+ constexpr bool operator==(const static_bounds<Ranges...>& rhs) const noexcept
{
return this->size() == rhs.size();
}
template <std::ptrdiff_t... Ranges>
- constexpr bool operator!=(const static_bounds<Ranges...>& rhs) const GSL_NOEXCEPT
+ constexpr bool operator!=(const static_bounds<Ranges...>& rhs) const noexcept
{
return !(*this == rhs);
}
- constexpr const_iterator begin() const GSL_NOEXCEPT
+ constexpr const_iterator begin() const noexcept
{
return const_iterator(*this, index_type{});
}
- constexpr const_iterator end() const GSL_NOEXCEPT
+ constexpr const_iterator end() const noexcept
{
return const_iterator(*this, this->index_bounds());
}
};
template <std::size_t Rank>
-class strided_bounds
-{
+class strided_bounds {
template <std::size_t OtherRank>
friend class strided_bounds;
@@ -698,7 +747,7 @@ public:
using const_reference = std::add_const_t<reference>;
using size_type = value_type;
using difference_type = value_type;
- using index_type = index<rank>;
+ using index_type = multi_span_index<rank>;
using const_index_type = std::add_const_t<index_type>;
using iterator = bounds_iterator<const_index_type>;
using const_iterator = bounds_iterator<const_index_type>;
@@ -707,60 +756,60 @@ public:
using sliced_type = std::conditional_t<rank != 0, strided_bounds<rank - 1>, void>;
using mapping_type = generalized_mapping_tag;
- constexpr strided_bounds(const strided_bounds&) GSL_NOEXCEPT = default;
+ constexpr strided_bounds(const strided_bounds&) noexcept = default;
- constexpr strided_bounds& operator=(const strided_bounds&) GSL_NOEXCEPT = default;
+ constexpr strided_bounds& operator=(const strided_bounds&) noexcept = default;
constexpr strided_bounds(const value_type (&values)[rank], index_type strides)
: m_extents(values), m_strides(std::move(strides))
- {
- }
+ {}
- constexpr strided_bounds(const index_type& extents, const index_type& strides) GSL_NOEXCEPT
- : m_extents(extents),
- m_strides(strides)
+ constexpr strided_bounds(const index_type& extents, const index_type& strides) noexcept
+ : m_extents(extents), m_strides(strides)
{
}
- constexpr index_type strides() const GSL_NOEXCEPT { return m_strides; }
+ constexpr index_type strides() const noexcept { return m_strides; }
- constexpr size_type total_size() const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr size_type total_size() const noexcept
{
size_type ret = 0;
- for (std::size_t i = 0; i < rank; ++i) {
- ret += (m_extents[i] - 1) * m_strides[i];
- }
+ for (std::size_t i = 0; i < rank; ++i) { ret += (m_extents[i] - 1) * m_strides[i]; }
return ret + 1;
}
- constexpr size_type size() const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr size_type size() const noexcept
{
size_type ret = 1;
- for (std::size_t i = 0; i < rank; ++i) {
- ret *= m_extents[i];
- }
+ for (std::size_t i = 0; i < rank; ++i) { ret *= m_extents[i]; }
return ret;
}
- constexpr bool contains(const index_type& idx) const GSL_NOEXCEPT
+ constexpr bool contains(const index_type& idx) const noexcept
{
- for (std::size_t i = 0; i < rank; ++i) {
+ for (std::size_t i = 0; i < rank; ++i)
+ {
if (idx[i] < 0 || idx[i] >= m_extents[i]) return false;
}
return true;
}
- constexpr size_type linearize(const index_type& idx) const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr size_type linearize(const index_type& idx) const
{
size_type ret = 0;
- for (std::size_t i = 0; i < rank; i++) {
+ for (std::size_t i = 0; i < rank; i++)
+ {
Expects(idx[i] < m_extents[i]); // index is out of bounds of the array
ret += idx[i] * m_strides[i];
}
return ret;
}
- constexpr size_type stride() const GSL_NOEXCEPT { return m_strides[0]; }
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr size_type stride() const noexcept { return m_strides[0]; }
template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
constexpr sliced_type slice() const
@@ -769,23 +818,20 @@ public:
}
template <std::size_t Dim = 0>
- constexpr size_type extent() const GSL_NOEXCEPT
+
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr size_type extent() const noexcept
{
static_assert(Dim < Rank,
"dimension should be less than rank (dimension count starts from 0)");
return m_extents[Dim];
}
- constexpr index_type index_bounds() const GSL_NOEXCEPT { return m_extents; }
- constexpr const_iterator begin() const GSL_NOEXCEPT
- {
- return const_iterator{*this, index_type{}};
- }
+ constexpr index_type index_bounds() const noexcept { return m_extents; }
- constexpr const_iterator end() const GSL_NOEXCEPT
- {
- return const_iterator{*this, index_bounds()};
- }
+ constexpr const_iterator begin() const noexcept { return const_iterator{*this, index_type{}}; }
+
+ constexpr const_iterator end() const noexcept { return const_iterator{*this, index_bounds()}; }
private:
index_type m_extents;
@@ -806,35 +852,37 @@ struct is_bounds<strided_bounds<Rank>> : std::integral_constant<bool, true>
};
template <typename IndexType>
-class bounds_iterator : public std::iterator<std::random_access_iterator_tag, IndexType>
+class bounds_iterator
{
-private:
- using Base = std::iterator<std::random_access_iterator_tag, IndexType>;
-
public:
static const std::size_t rank = IndexType::rank;
- using typename Base::reference;
- using typename Base::pointer;
- using typename Base::difference_type;
- using typename Base::value_type;
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = IndexType;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type*;
+ using reference = value_type&;
using index_type = value_type;
using index_size_type = typename IndexType::value_type;
template <typename Bounds>
- explicit bounds_iterator(const Bounds& bnd, value_type curr) GSL_NOEXCEPT
- : boundary_(bnd.index_bounds()),
- curr_(std::move(curr))
+ explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept
+ : boundary_(bnd.index_bounds()), curr_(std::move(curr))
{
static_assert(is_bounds<Bounds>::value, "Bounds type must be provided");
}
- constexpr reference operator*() const GSL_NOEXCEPT { return curr_; }
+ constexpr reference operator*() const noexcept { return curr_; }
- constexpr pointer operator->() const GSL_NOEXCEPT { return &curr_; }
+ constexpr pointer operator->() const noexcept { return &curr_; }
+
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
+ constexpr bounds_iterator& operator++() noexcept
- constexpr bounds_iterator& operator++() GSL_NOEXCEPT
{
- for (std::size_t i = rank; i-- > 0;) {
- if (curr_[i] < boundary_[i] - 1) {
+ for (std::size_t i = rank; i-- > 0;)
+ {
+ if (curr_[i] < boundary_[i] - 1)
+ {
curr_[i]++;
return *this;
}
@@ -845,24 +893,26 @@ public:
return *this;
}
- constexpr bounds_iterator operator++(int) GSL_NOEXCEPT
+ constexpr bounds_iterator operator++(int) noexcept
{
auto ret = *this;
++(*this);
return ret;
}
- constexpr bounds_iterator& operator--() GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr bounds_iterator& operator--()
{
- if (!less(curr_, boundary_)) {
+ if (!less(curr_, boundary_))
+ {
// if at the past-the-end, set to last element
- for (std::size_t i = 0; i < rank; ++i) {
- curr_[i] = boundary_[i] - 1;
- }
+ for (std::size_t i = 0; i < rank; ++i) { curr_[i] = boundary_[i] - 1; }
return *this;
}
- for (std::size_t i = rank; i-- > 0;) {
- if (curr_[i] >= 1) {
+ for (std::size_t i = rank; i-- > 0;)
+ {
+ if (curr_[i] >= 1)
+ {
curr_[i]--;
return *this;
}
@@ -874,28 +924,28 @@ public:
return *this;
}
- constexpr bounds_iterator operator--(int) GSL_NOEXCEPT
+ constexpr bounds_iterator operator--(int) noexcept
{
auto ret = *this;
--(*this);
return ret;
}
- constexpr bounds_iterator operator+(difference_type n) const GSL_NOEXCEPT
+ constexpr bounds_iterator operator+(difference_type n) const noexcept
{
bounds_iterator ret{*this};
return ret += n;
}
- constexpr bounds_iterator& operator+=(difference_type n) GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr bounds_iterator& operator+=(difference_type n)
{
auto linear_idx = linearize(curr_) + n;
std::remove_const_t<value_type> stride = 0;
stride[rank - 1] = 1;
- for (std::size_t i = rank - 1; i-- > 0;) {
- stride[i] = stride[i + 1] * boundary_[i + 1];
- }
- for (std::size_t i = 0; i < rank; ++i) {
+ for (std::size_t i = rank - 1; i-- > 0;) { stride[i] = stride[i + 1] * boundary_[i + 1]; }
+ for (std::size_t i = 0; i < rank; ++i)
+ {
curr_[i] = linear_idx / stride[i];
linear_idx = linear_idx % stride[i];
}
@@ -904,79 +954,78 @@ public:
return *this;
}
- constexpr bounds_iterator operator-(difference_type n) const GSL_NOEXCEPT
+ constexpr bounds_iterator operator-(difference_type n) const noexcept
{
bounds_iterator ret{*this};
return ret -= n;
}
- constexpr bounds_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; }
+ constexpr bounds_iterator& operator-=(difference_type n) noexcept { return *this += -n; }
- constexpr difference_type operator-(const bounds_iterator& rhs) const GSL_NOEXCEPT
+ constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept
{
return linearize(curr_) - linearize(rhs.curr_);
}
- constexpr value_type operator[](difference_type n) const GSL_NOEXCEPT { return *(*this + n); }
+ constexpr value_type operator[](difference_type n) const noexcept { return *(*this + n); }
- constexpr bool operator==(const bounds_iterator& rhs) const GSL_NOEXCEPT
+ constexpr bool operator==(const bounds_iterator& rhs) const noexcept
{
return curr_ == rhs.curr_;
}
- constexpr bool operator!=(const bounds_iterator& rhs) const GSL_NOEXCEPT
- {
- return !(*this == rhs);
- }
- constexpr bool operator<(const bounds_iterator& rhs) const GSL_NOEXCEPT
+ constexpr bool operator!=(const bounds_iterator& rhs) const noexcept { return !(*this == rhs); }
+
+ constexpr bool operator<(const bounds_iterator& rhs) const noexcept
{
return less(curr_, rhs.curr_);
}
- constexpr bool operator<=(const bounds_iterator& rhs) const GSL_NOEXCEPT
- {
- return !(rhs < *this);
- }
+ constexpr bool operator<=(const bounds_iterator& rhs) const noexcept { return !(rhs < *this); }
- constexpr bool operator>(const bounds_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; }
+ constexpr bool operator>(const bounds_iterator& rhs) const noexcept { return rhs < *this; }
- constexpr bool operator>=(const bounds_iterator& rhs) const GSL_NOEXCEPT
- {
- return !(rhs > *this);
- }
+ constexpr bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); }
- void swap(bounds_iterator& rhs) GSL_NOEXCEPT
+ void swap(bounds_iterator& rhs) noexcept
{
std::swap(boundary_, rhs.boundary_);
std::swap(curr_, rhs.curr_);
}
private:
- constexpr bool less(index_type& one, index_type& other) const GSL_NOEXCEPT
+
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr bool less(index_type& one, index_type& other) const noexcept
{
- for (std::size_t i = 0; i < rank; ++i) {
+ for (std::size_t i = 0; i < rank; ++i)
+ {
if (one[i] < other[i]) return true;
}
return false;
}
- constexpr index_size_type linearize(const value_type& idx) const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ constexpr index_size_type linearize(const value_type& idx) const noexcept
{
// TODO: Smarter impl.
// Check if past-the-end
index_size_type multiplier = 1;
index_size_type res = 0;
- if (!less(idx, boundary_)) {
+ if (!less(idx, boundary_))
+ {
res = 1;
- for (std::size_t i = rank; i-- > 0;) {
+ for (std::size_t i = rank; i-- > 0;)
+ {
res += (idx[i] - 1) * multiplier;
multiplier *= boundary_[i];
}
}
else
{
- for (std::size_t i = rank; i-- > 0;) {
+ for (std::size_t i = rank; i-- > 0;)
+ {
res += idx[i] * multiplier;
multiplier *= boundary_[i];
}
@@ -990,7 +1039,7 @@ private:
template <typename IndexType>
bounds_iterator<IndexType> operator+(typename bounds_iterator<IndexType>::difference_type n,
- const bounds_iterator<IndexType>& rhs) GSL_NOEXCEPT
+ const bounds_iterator<IndexType>& rhs) noexcept
{
return rhs + n;
}
@@ -998,26 +1047,29 @@ bounds_iterator<IndexType> operator+(typename bounds_iterator<IndexType>::differ
namespace details
{
template <typename Bounds>
- inline constexpr std::enable_if_t<
+ constexpr std::enable_if_t<
std::is_same<typename Bounds::mapping_type, generalized_mapping_tag>::value,
typename Bounds::index_type>
- make_stride(const Bounds& bnd) GSL_NOEXCEPT
+ make_stride(const Bounds& bnd) noexcept
{
return bnd.strides();
}
// Make a stride vector from bounds, assuming contiguous memory.
template <typename Bounds>
- inline constexpr std::enable_if_t<
+ constexpr std::enable_if_t<
std::is_same<typename Bounds::mapping_type, contiguous_mapping_tag>::value,
typename Bounds::index_type>
- make_stride(const Bounds& bnd) GSL_NOEXCEPT
+ make_stride(const Bounds& bnd) noexcept
{
auto extents = bnd.index_bounds();
typename Bounds::size_type stride[Bounds::rank] = {};
stride[Bounds::rank - 1] = 1;
- for (std::size_t i = 1; i < Bounds::rank; ++i) {
+ for (std::size_t i = 1; i < Bounds::rank; ++i)
+ {
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
stride[Bounds::rank - i - 1] = stride[Bounds::rank - i] * extents[Bounds::rank - i];
}
return {stride};
@@ -1054,17 +1106,17 @@ struct dim_t<dynamic_range>
{
static const std::ptrdiff_t value = dynamic_range;
const std::ptrdiff_t dvalue;
- dim_t(std::ptrdiff_t size) : dvalue(size) {}
+ constexpr dim_t(std::ptrdiff_t size) noexcept : dvalue(size) {}
};
template <std::ptrdiff_t N, class = std::enable_if_t<(N >= 0)>>
-inline constexpr dim_t<N> dim() GSL_NOEXCEPT
+constexpr dim_t<N> dim() noexcept
{
return dim_t<N>();
}
template <std::ptrdiff_t N = dynamic_range, class = std::enable_if_t<N == dynamic_range>>
-inline constexpr dim_t<N> dim(std::ptrdiff_t n) GSL_NOEXCEPT
+constexpr dim_t<N> dim(std::ptrdiff_t n) noexcept
{
return dim_t<>(n);
}
@@ -1072,7 +1124,6 @@ inline constexpr dim_t<N> dim(std::ptrdiff_t n) GSL_NOEXCEPT
template <typename ValueType, std::ptrdiff_t FirstDimension = dynamic_range,
std::ptrdiff_t... RestDimensions>
class multi_span;
-
template <typename ValueType, std::size_t Rank>
class strided_span;
@@ -1174,7 +1225,7 @@ namespace details
struct is_multi_span : is_multi_span_oracle<std::remove_cv_t<T>>
{
};
-}
+} // namespace details
template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
class multi_span
@@ -1210,7 +1261,9 @@ private:
public:
// default constructor - same as constructing from nullptr_t
- constexpr multi_span() GSL_NOEXCEPT : multi_span(nullptr, bounds_type{})
+ GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
+ constexpr multi_span() noexcept
+ : multi_span(nullptr, bounds_type{})
{
static_assert(bounds_type::dynamic_rank != 0 ||
(bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0),
@@ -1219,7 +1272,9 @@ public:
}
// construct from nullptr - get an empty multi_span
- constexpr multi_span(std::nullptr_t) GSL_NOEXCEPT : multi_span(nullptr, bounds_type{})
+ GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
+ constexpr multi_span(std::nullptr_t) noexcept
+ : multi_span(nullptr, bounds_type{})
{
static_assert(bounds_type::dynamic_rank != 0 ||
(bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0),
@@ -1229,8 +1284,9 @@ public:
// construct from nullptr with size of 0 (helps with template function calls)
template <class IntType, typename = std::enable_if_t<std::is_integral<IntType>::value>>
- constexpr multi_span(std::nullptr_t, IntType size) GSL_NOEXCEPT
- : multi_span(nullptr, bounds_type{})
+
+ // GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive // TODO: parser bug
+ constexpr multi_span(std::nullptr_t, IntType size) : multi_span(nullptr, bounds_type{})
{
static_assert(bounds_type::dynamic_rank != 0 ||
(bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0),
@@ -1240,7 +1296,10 @@ public:
}
// construct from a single element
- constexpr multi_span(reference data) GSL_NOEXCEPT : multi_span(&data, bounds_type{1})
+
+ GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
+ constexpr multi_span(reference data) noexcept
+ : multi_span(&data, bounds_type{1})
{
static_assert(bounds_type::dynamic_rank > 0 || bounds_type::static_size == 0 ||
bounds_type::static_size == 1,
@@ -1252,14 +1311,14 @@ public:
constexpr multi_span(value_type&&) = delete;
// construct from pointer + length
- constexpr multi_span(pointer ptr, size_type size) GSL_NOEXCEPT
+ GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
+ constexpr multi_span(pointer ptr, size_type size)
: multi_span(ptr, bounds_type{size})
- {
- }
+ {}
// construct from pointer + length - multidimensional
- constexpr multi_span(pointer data, bounds_type bounds) GSL_NOEXCEPT : data_(data),
- bounds_(std::move(bounds))
+ constexpr multi_span(pointer data, bounds_type bounds)
+ : data_(data), bounds_(std::move(bounds))
{
Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0);
}
@@ -1313,8 +1372,9 @@ public:
constexpr multi_span(const std::array<T, N>& arr)
: multi_span(arr.data(), bounds_type{static_bounds<N>{}})
{
- static_assert(std::is_convertible<T(*)[], typename std::remove_const_t<value_type>(*)[]>::value,
- "Cannot convert from source type to target multi_span type.");
+ static_assert(
+ std::is_convertible<T(*)[], typename std::remove_const_t<value_type>(*)[]>::value,
+ "Cannot convert from source type to target multi_span type.");
static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value,
"You cannot construct a multi_span from a std::array of smaller size.");
}
@@ -1336,8 +1396,7 @@ public:
constexpr multi_span(Cont& cont)
: multi_span(static_cast<pointer>(cont.data()),
details::newBoundsHelper<bounds_type>(narrow_cast<size_type>(cont.size())))
- {
- }
+ {}
// prevent constructing from temporary containers
template <typename Cont, typename DataType = typename Cont::value_type,
@@ -1354,11 +1413,9 @@ public:
typename OtherBounds = static_bounds<OtherDimensions...>,
typename = std::enable_if_t<std::is_convertible<OtherValueType, ValueType>::value &&
std::is_convertible<OtherBounds, bounds_type>::value>>
- constexpr multi_span(multi_span<OtherValueType, OtherDimensions...> other) GSL_NOEXCEPT
- : data_(other.data_),
- bounds_(other.bounds_)
- {
- }
+ constexpr multi_span(multi_span<OtherValueType, OtherDimensions...> other)
+ : data_(other.data_), bounds_(other.bounds_)
+ {}
// trivial copy and move
constexpr multi_span(const multi_span&) = default;
@@ -1370,7 +1427,8 @@ public:
// first() - extract the first Count elements into a new multi_span
template <std::ptrdiff_t Count>
- constexpr multi_span<ValueType, Count> first() const GSL_NOEXCEPT
+
+ constexpr multi_span<ValueType, Count> first() const
{
static_assert(Count >= 0, "Count must be >= 0.");
static_assert(bounds_type::static_size == dynamic_range ||
@@ -1382,7 +1440,7 @@ public:
}
// first() - extract the first count elements into a new multi_span
- constexpr multi_span<ValueType, dynamic_range> first(size_type count) const GSL_NOEXCEPT
+ constexpr multi_span<ValueType, dynamic_range> first(size_type count) const
{
Expects(count >= 0 && count <= this->size());
return {this->data(), count};
@@ -1390,7 +1448,7 @@ public:
// last() - extract the last Count elements into a new multi_span
template <std::ptrdiff_t Count>
- constexpr multi_span<ValueType, Count> last() const GSL_NOEXCEPT
+ constexpr multi_span<ValueType, Count> last() const
{
static_assert(Count >= 0, "Count must be >= 0.");
static_assert(bounds_type::static_size == dynamic_range ||
@@ -1402,7 +1460,7 @@ public:
}
// last() - extract the last count elements into a new multi_span
- constexpr multi_span<ValueType, dynamic_range> last(size_type count) const GSL_NOEXCEPT
+ constexpr multi_span<ValueType, dynamic_range> last(size_type count) const
{
Expects(count >= 0 && count <= this->size());
return {this->data() + this->size() - count, count};
@@ -1410,7 +1468,7 @@ public:
// subspan() - create a subview of Count elements starting at Offset
template <std::ptrdiff_t Offset, std::ptrdiff_t Count>
- constexpr multi_span<ValueType, Count> subspan() const GSL_NOEXCEPT
+ constexpr multi_span<ValueType, Count> subspan() const
{
static_assert(Count >= 0, "Count must be >= 0.");
static_assert(Offset >= 0, "Offset must be >= 0.");
@@ -1426,8 +1484,8 @@ public:
// subspan() - create a subview of count elements starting at offset
// supplying dynamic_range for count will consume all available elements from offset
- constexpr multi_span<ValueType, dynamic_range>
- subspan(size_type offset, size_type count = dynamic_range) const GSL_NOEXCEPT
+ constexpr multi_span<ValueType, dynamic_range> subspan(size_type offset,
+ size_type count = dynamic_range) const
{
Expects((offset >= 0 && offset <= this->size()) &&
(count == dynamic_range || (count <= this->size() - offset)));
@@ -1436,34 +1494,34 @@ public:
// section - creates a non-contiguous, strided multi_span from a contiguous one
constexpr strided_span<ValueType, Rank> section(index_type origin,
- index_type extents) const GSL_NOEXCEPT
+ index_type extents) const
{
- size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
+ const size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
return {&this->operator[](origin), size,
strided_bounds<Rank>{extents, details::make_stride(bounds())}};
}
// length of the multi_span in elements
- constexpr size_type size() const GSL_NOEXCEPT { return bounds_.size(); }
+ constexpr size_type size() const noexcept { return bounds_.size(); }
// length of the multi_span in elements
- constexpr size_type length() const GSL_NOEXCEPT { return this->size(); }
+ constexpr size_type length() const noexcept { return this->size(); }
// length of the multi_span in bytes
- constexpr size_type size_bytes() const GSL_NOEXCEPT
+ constexpr size_type size_bytes() const noexcept
{
return narrow_cast<size_type>(sizeof(value_type)) * this->size();
}
// length of the multi_span in bytes
- constexpr size_type length_bytes() const GSL_NOEXCEPT { return this->size_bytes(); }
+ constexpr size_type length_bytes() const noexcept { return this->size_bytes(); }
- constexpr bool empty() const GSL_NOEXCEPT { return this->size() == 0; }
+ constexpr bool empty() const noexcept { return this->size() == 0; }
static constexpr std::size_t rank() { return Rank; }
template <std::size_t Dim = 0>
- constexpr size_type extent() const GSL_NOEXCEPT
+ constexpr size_type extent() const noexcept
{
static_assert(Dim < Rank,
"Dimension should be less than rank (dimension count starts from 0).");
@@ -1471,36 +1529,39 @@ public:
}
template <typename IntType>
- constexpr size_type extent(IntType dim) const GSL_NOEXCEPT
+ constexpr size_type extent(IntType dim) const
{
return bounds_.extent(dim);
}
- constexpr bounds_type bounds() const GSL_NOEXCEPT { return bounds_; }
+ constexpr bounds_type bounds() const noexcept { return bounds_; }
- constexpr pointer data() const GSL_NOEXCEPT { return data_; }
+ constexpr pointer data() const noexcept { return data_; }
template <typename FirstIndex>
- constexpr reference operator()(FirstIndex index)
+ constexpr reference operator()(FirstIndex idx)
{
- return this->operator[](narrow_cast<std::ptrdiff_t>(index));
+ return this->operator[](narrow_cast<std::ptrdiff_t>(idx));
}
template <typename FirstIndex, typename... OtherIndices>
- constexpr reference operator()(FirstIndex index, OtherIndices... indices)
+ constexpr reference operator()(FirstIndex firstIndex, OtherIndices... indices)
{
- index_type idx = {narrow_cast<std::ptrdiff_t>(index),
- narrow_cast<std::ptrdiff_t>(indices)...};
+ const index_type idx = {narrow_cast<std::ptrdiff_t>(firstIndex),
+ narrow_cast<std::ptrdiff_t>(indices)...};
return this->operator[](idx);
}
- constexpr reference operator[](const index_type& idx) const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ constexpr reference operator[](const index_type& idx) const
{
return data_[bounds_.linearize(idx)];
}
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
- constexpr Ret operator[](size_type idx) const GSL_NOEXCEPT
+
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ constexpr Ret operator[](size_type idx) const
{
Expects(idx >= 0 && idx < bounds_.size()); // index is out of bounds of the array
const size_type ridx = idx * bounds_.stride();
@@ -1510,85 +1571,81 @@ public:
return Ret{data_ + ridx, bounds_.slice()};
}
- constexpr iterator begin() const GSL_NOEXCEPT { return iterator{this, true}; }
+ constexpr iterator begin() const noexcept { return iterator{this, true}; }
- constexpr iterator end() const GSL_NOEXCEPT { return iterator{this, false}; }
+ constexpr iterator end() const noexcept { return iterator{this, false}; }
- constexpr const_iterator cbegin() const GSL_NOEXCEPT
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ constexpr const_iterator cbegin() const noexcept
{
return const_iterator{reinterpret_cast<const const_span*>(this), true};
}
- constexpr const_iterator cend() const GSL_NOEXCEPT
+ constexpr const_iterator cend() const noexcept
{
return const_iterator{reinterpret_cast<const const_span*>(this), false};
}
- constexpr reverse_iterator rbegin() const GSL_NOEXCEPT { return reverse_iterator{end()}; }
+ constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
- constexpr reverse_iterator rend() const GSL_NOEXCEPT { return reverse_iterator{begin()}; }
+ constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
- constexpr const_reverse_iterator crbegin() const GSL_NOEXCEPT
+ constexpr const_reverse_iterator crbegin() const noexcept
{
return const_reverse_iterator{cend()};
}
- constexpr const_reverse_iterator crend() const GSL_NOEXCEPT
+ constexpr const_reverse_iterator crend() const noexcept
{
return const_reverse_iterator{cbegin()};
}
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const
{
return bounds_.size() == other.bounds_.size() &&
(data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin()));
}
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const
{
return !(*this == other);
}
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const
{
return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end());
}
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const
{
return !(other < *this);
}
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const
+ noexcept
{
return (other < *this);
}
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const
{
return !(*this < other);
}
@@ -1602,21 +1659,21 @@ public:
// DimCount and Enabled here are workarounds for a bug in MSVC 2015
template <typename SpanType, typename... Dimensions2, std::size_t DimCount = sizeof...(Dimensions2),
bool Enabled = (DimCount > 0), typename = std::enable_if_t<Enabled>>
-inline constexpr auto as_multi_span(SpanType s, Dimensions2... dims)
+constexpr auto as_multi_span(SpanType s, Dimensions2... dims)
-> multi_span<typename SpanType::value_type, Dimensions2::value...>
{
static_assert(details::is_multi_span<SpanType>::value,
"Variadic as_multi_span() is for reshaping existing spans.");
using BoundsType =
typename multi_span<typename SpanType::value_type, (Dimensions2::value)...>::bounds_type;
- auto tobounds = details::static_as_multi_span_helper<BoundsType>(dims..., details::Sep{});
+ const auto tobounds = details::static_as_multi_span_helper<BoundsType>(dims..., details::Sep{});
details::verifyBoundsReshape(s.bounds(), tobounds);
return {s.data(), tobounds};
}
// convert a multi_span<T> to a multi_span<const byte>
template <typename U, std::ptrdiff_t... Dimensions>
-multi_span<const byte, dynamic_range> as_bytes(multi_span<U, Dimensions...> s) GSL_NOEXCEPT
+multi_span<const byte, dynamic_range> as_bytes(multi_span<U, Dimensions...> s) noexcept
{
static_assert(std::is_trivial<std::decay_t<U>>::value,
"The value_type of multi_span must be a trivial type.");
@@ -1628,7 +1685,7 @@ multi_span<const byte, dynamic_range> as_bytes(multi_span<U, Dimensions...> s) G
// on all implementations. It should be considered an experimental extension
// to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions>
-multi_span<byte> as_writeable_bytes(multi_span<U, Dimensions...> s) GSL_NOEXCEPT
+multi_span<byte> as_writeable_bytes(multi_span<U, Dimensions...> s) noexcept
{
static_assert(std::is_trivial<std::decay_t<U>>::value,
"The value_type of multi_span must be a trivial type.");
@@ -1640,8 +1697,7 @@ multi_span<byte> as_writeable_bytes(multi_span<U, Dimensions...> s) GSL_NOEXCEPT
// on all implementations. It should be considered an experimental extension
// to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions>
-inline constexpr auto
-as_multi_span(multi_span<const byte, Dimensions...> s) GSL_NOEXCEPT -> multi_span<
+constexpr auto as_multi_span(multi_span<const byte, Dimensions...> s) -> multi_span<
const U, static_cast<std::ptrdiff_t>(
multi_span<const byte, Dimensions...>::bounds_type::static_size != dynamic_range
? (static_cast<std::size_t>(
@@ -1667,7 +1723,7 @@ as_multi_span(multi_span<const byte, Dimensions...> s) GSL_NOEXCEPT -> multi_spa
// on all implementations. It should be considered an experimental extension
// to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions>
-inline constexpr auto as_multi_span(multi_span<byte, Dimensions...> s) GSL_NOEXCEPT
+constexpr auto as_multi_span(multi_span<byte, Dimensions...> s)
-> multi_span<U, narrow_cast<std::ptrdiff_t>(
multi_span<byte, Dimensions...>::bounds_type::static_size != dynamic_range
? static_cast<std::size_t>(
@@ -1676,11 +1732,10 @@ inline constexpr auto as_multi_span(multi_span<byte, Dimensions...> s) GSL_NOEXC
: dynamic_range)>
{
using ByteSpan = multi_span<byte, Dimensions...>;
- static_assert(
- std::is_trivial<std::decay_t<U>>::value &&
- (ByteSpan::bounds_type::static_size == dynamic_range ||
- ByteSpan::bounds_type::static_size % static_cast<std::size_t>(sizeof(U)) == 0),
- "Target type must be a trivial type and its size must match the byte array size");
+ static_assert(std::is_trivial<std::decay_t<U>>::value &&
+ (ByteSpan::bounds_type::static_size == dynamic_range ||
+ ByteSpan::bounds_type::static_size % sizeof(U) == 0),
+ "Target type must be a trivial type and its size must match the byte array size");
Expects((s.size_bytes() % sizeof(U)) == 0);
return {reinterpret_cast<U*>(s.data()),
@@ -1688,7 +1743,7 @@ inline constexpr auto as_multi_span(multi_span<byte, Dimensions...> s) GSL_NOEXC
}
template <typename T, std::ptrdiff_t... Dimensions>
-inline constexpr auto as_multi_span(T* const& ptr, dim_t<Dimensions>... args)
+constexpr auto as_multi_span(T* const& ptr, dim_t<Dimensions>... args)
-> multi_span<std::remove_all_extents_t<T>, Dimensions...>
{
return {reinterpret_cast<std::remove_all_extents_t<T>*>(ptr),
@@ -1697,41 +1752,41 @@ inline constexpr auto as_multi_span(T* const& ptr, dim_t<Dimensions>... args)
}
template <typename T>
-inline constexpr auto as_multi_span(T* arr, std::ptrdiff_t len) ->
+constexpr auto as_multi_span(T* arr, std::ptrdiff_t len) ->
typename details::SpanArrayTraits<T, dynamic_range>::type
{
return {reinterpret_cast<std::remove_all_extents_t<T>*>(arr), len};
}
template <typename T, std::size_t N>
-inline constexpr auto as_multi_span(T (&arr)[N]) -> typename details::SpanArrayTraits<T, N>::type
+constexpr auto as_multi_span(T (&arr)[N]) -> typename details::SpanArrayTraits<T, N>::type
{
return {arr};
}
template <typename T, std::size_t N>
-inline constexpr multi_span<const T, N> as_multi_span(const std::array<T, N>& arr)
+constexpr multi_span<const T, N> as_multi_span(const std::array<T, N>& arr)
{
return {arr};
}
template <typename T, std::size_t N>
-inline constexpr multi_span<const T, N> as_multi_span(const std::array<T, N>&&) = delete;
+constexpr multi_span<const T, N> as_multi_span(const std::array<T, N>&&) = delete;
template <typename T, std::size_t N>
-inline constexpr multi_span<T, N> as_multi_span(std::array<T, N>& arr)
+constexpr multi_span<T, N> as_multi_span(std::array<T, N>& arr)
{
return {arr};
}
template <typename T>
-inline constexpr multi_span<T, dynamic_range> as_multi_span(T* begin, T* end)
+constexpr multi_span<T, dynamic_range> as_multi_span(T* begin, T* end)
{
return {begin, end};
}
template <typename Cont>
-inline constexpr auto as_multi_span(Cont& arr) -> std::enable_if_t<
+constexpr auto as_multi_span(Cont& arr) -> std::enable_if_t<
!details::is_multi_span<std::decay_t<Cont>>::value,
multi_span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>>
{
@@ -1740,13 +1795,14 @@ inline constexpr auto as_multi_span(Cont& arr) -> std::enable_if_t<
}
template <typename Cont>
-inline constexpr auto as_multi_span(Cont&& arr) -> std::enable_if_t<
+constexpr auto as_multi_span(Cont&& arr) -> std::enable_if_t<
!details::is_multi_span<std::decay_t<Cont>>::value,
multi_span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>> = delete;
// from basic_string which doesn't have nonconst .data() member like other contiguous containers
template <typename CharT, typename Traits, typename Allocator>
-inline constexpr auto as_multi_span(std::basic_string<CharT, Traits, Allocator>& str)
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+constexpr auto as_multi_span(std::basic_string<CharT, Traits, Allocator>& str)
-> multi_span<CharT, dynamic_range>
{
Expects(str.size() < PTRDIFF_MAX);
@@ -1791,6 +1847,7 @@ public:
Expects((bounds_.size() > 0 && ptr != nullptr) || bounds_.size() == 0);
// Bounds cross data boundaries
Expects(this->bounds().total_size() <= size);
+ GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
(void) size;
}
@@ -1798,26 +1855,23 @@ public:
template <size_type N>
constexpr strided_span(value_type (&values)[N], bounds_type bounds)
: strided_span(values, N, std::move(bounds))
- {
- }
+ {}
// from array view
template <typename OtherValueType, std::ptrdiff_t... Dimensions,
bool Enabled1 = (sizeof...(Dimensions) == Rank),
bool Enabled2 = std::is_convertible<OtherValueType*, ValueType*>::value,
- typename Dummy = std::enable_if_t<Enabled1 && Enabled2>>
+ typename = std::enable_if_t<Enabled1 && Enabled2>>
constexpr strided_span(multi_span<OtherValueType, Dimensions...> av, bounds_type bounds)
: strided_span(av.data(), av.bounds().total_size(), std::move(bounds))
- {
- }
+ {}
// convertible
- template <typename OtherValueType, typename Dummy = std::enable_if_t<std::is_convertible<
+ template <typename OtherValueType, typename = std::enable_if_t<std::is_convertible<
OtherValueType (*)[], value_type (*)[]>::value>>
constexpr strided_span(const strided_span<OtherValueType, Rank>& other)
: data_(other.data_), bounds_(other.bounds_)
- {
- }
+ {}
// convert from bytes
template <typename OtherValueType>
@@ -1831,7 +1885,7 @@ public:
"OtherValueType should have a size to contain a multiple of ValueTypes");
auto d = narrow_cast<size_type>(sizeof(OtherValueType) / sizeof(value_type));
- size_type size = this->bounds().total_size() / d;
+ const size_type size = this->bounds().total_size() / d;
return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())),
size,
bounds_type{resize_extent(this->bounds().index_bounds(), d),
@@ -1840,17 +1894,19 @@ public:
constexpr strided_span section(index_type origin, index_type extents) const
{
- size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
+ const size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
return {&this->operator[](origin), size,
bounds_type{extents, details::make_stride(bounds())}};
}
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr reference operator[](const index_type& idx) const
{
return data_[bounds_.linearize(idx)];
}
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr Ret operator[](size_type idx) const
{
Expects(idx < bounds_.size()); // index is out of bounds of the array
@@ -1861,21 +1917,23 @@ public:
return {data_ + ridx, bounds_.slice().total_size(), bounds_.slice()};
}
- constexpr bounds_type bounds() const GSL_NOEXCEPT { return bounds_; }
+ constexpr bounds_type bounds() const noexcept { return bounds_; }
template <std::size_t Dim = 0>
- constexpr size_type extent() const GSL_NOEXCEPT
+ constexpr size_type extent() const noexcept
{
static_assert(Dim < Rank,
"dimension should be less than Rank (dimension count starts from 0)");
return bounds_.template extent<Dim>();
}
- constexpr size_type size() const GSL_NOEXCEPT { return bounds_.size(); }
+ constexpr size_type size() const noexcept { return bounds_.size(); }
+
+ constexpr pointer data() const noexcept { return data_; }
- constexpr pointer data() const GSL_NOEXCEPT { return data_; }
+ constexpr bool empty() const noexcept { return this->size() == 0; }
- constexpr explicit operator bool() const GSL_NOEXCEPT { return data_ != nullptr; }
+ constexpr explicit operator bool() const noexcept { return data_ != nullptr; }
constexpr iterator begin() const { return iterator{this, true}; }
@@ -1900,56 +1958,50 @@ public:
constexpr const_reverse_iterator crend() const { return const_reverse_iterator{cbegin()}; }
template <typename OtherValueType, std::ptrdiff_t OtherRank,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator==(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator==(const strided_span<OtherValueType, OtherRank>& other) const
{
return bounds_.size() == other.bounds_.size() &&
(data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin()));
}
template <typename OtherValueType, std::ptrdiff_t OtherRank,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator!=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator!=(const strided_span<OtherValueType, OtherRank>& other) const
{
return !(*this == other);
}
template <typename OtherValueType, std::ptrdiff_t OtherRank,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator<(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator<(const strided_span<OtherValueType, OtherRank>& other) const
{
return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end());
}
template <typename OtherValueType, std::ptrdiff_t OtherRank,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator<=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator<=(const strided_span<OtherValueType, OtherRank>& other) const
{
return !(other < *this);
}
template <typename OtherValueType, std::ptrdiff_t OtherRank,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator>(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator>(const strided_span<OtherValueType, OtherRank>& other) const
{
return (other < *this);
}
template <typename OtherValueType, std::ptrdiff_t OtherRank,
- typename Dummy = std::enable_if_t<std::is_same<
- std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
- constexpr bool
- operator>=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
+ typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
+ std::remove_cv_t<OtherValueType>>::value>>
+ constexpr bool operator>=(const strided_span<OtherValueType, OtherRank>& other) const
{
return !(*this < other);
}
@@ -1958,6 +2010,7 @@ private:
static index_type resize_extent(const index_type& extent, std::ptrdiff_t d)
{
// The last dimension of the array needs to contain a multiple of new type elements
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
Expects(extent[Rank - 1] >= d && (extent[Rank - 1] % d == 0));
index_type ret = extent;
@@ -1966,16 +2019,18 @@ private:
return ret;
}
- template <bool Enabled = (Rank == 1), typename Dummy = std::enable_if_t<Enabled>>
+ template <bool Enabled = (Rank == 1), typename = std::enable_if_t<Enabled>>
static index_type resize_stride(const index_type& strides, std::ptrdiff_t, void* = nullptr)
{
// Only strided arrays with regular strides can be resized
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
Expects(strides[Rank - 1] == 1);
return strides;
}
- template <bool Enabled = (Rank > 1), typename Dummy = std::enable_if_t<Enabled>>
+ template <bool Enabled = (Rank > 1), typename = std::enable_if_t<Enabled>>
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
static index_type resize_stride(const index_type& strides, std::ptrdiff_t d)
{
// Only strided arrays with regular strides can be resized
@@ -1984,7 +2039,8 @@ private:
// memory that can contain a multiple of new type elements
Expects(strides[Rank - 2] >= d && (strides[Rank - 2] % d == 0));
- for (std::size_t i = Rank - 1; i > 0; --i) {
+ for (std::size_t i = Rank - 1; i > 0; --i)
+ {
// Only strided arrays with regular strides can be resized
Expects((strides[i - 1] >= strides[i]) && (strides[i - 1] % strides[i] == 0));
}
@@ -1998,14 +2054,13 @@ private:
template <class Span>
class contiguous_span_iterator
- : public std::iterator<std::random_access_iterator_tag, typename Span::value_type>
{
- using Base = std::iterator<std::random_access_iterator_tag, typename Span::value_type>;
-
public:
- using typename Base::reference;
- using typename Base::pointer;
- using typename Base::difference_type;
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = typename Span::value_type;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type*;
+ using reference = value_type&;
private:
template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
@@ -2013,96 +2068,98 @@ private:
pointer data_;
const Span* m_validator;
- void validateThis() const
- {
+
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ void validateThis() const {
// iterator is out of range of the array
Expects(data_ >= m_validator->data_ && data_ < m_validator->data_ + m_validator->size());
}
+
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
contiguous_span_iterator(const Span* container, bool isbegin)
: data_(isbegin ? container->data_ : container->data_ + container->size())
, m_validator(container)
- {
- }
+ {}
public:
- reference operator*() const GSL_NOEXCEPT
+ reference operator*() const
{
validateThis();
return *data_;
}
- pointer operator->() const GSL_NOEXCEPT
+ pointer operator->() const
{
validateThis();
return data_;
}
- contiguous_span_iterator& operator++() GSL_NOEXCEPT
+
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ contiguous_span_iterator& operator++() noexcept
{
++data_;
return *this;
}
- contiguous_span_iterator operator++(int) GSL_NOEXCEPT
+ contiguous_span_iterator operator++(int) noexcept
{
auto ret = *this;
++(*this);
return ret;
}
- contiguous_span_iterator& operator--() GSL_NOEXCEPT
+
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ contiguous_span_iterator& operator--() noexcept
{
--data_;
return *this;
}
- contiguous_span_iterator operator--(int) GSL_NOEXCEPT
+ contiguous_span_iterator operator--(int) noexcept
{
auto ret = *this;
--(*this);
return ret;
}
- contiguous_span_iterator operator+(difference_type n) const GSL_NOEXCEPT
+ contiguous_span_iterator operator+(difference_type n) const noexcept
{
contiguous_span_iterator ret{*this};
return ret += n;
}
- contiguous_span_iterator& operator+=(difference_type n) GSL_NOEXCEPT
+ contiguous_span_iterator& operator+=(difference_type n) noexcept
{
data_ += n;
return *this;
}
- contiguous_span_iterator operator-(difference_type n) const GSL_NOEXCEPT
+ contiguous_span_iterator operator-(difference_type n) const noexcept
{
contiguous_span_iterator ret{*this};
return ret -= n;
}
- contiguous_span_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; }
- difference_type operator-(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
+
+ contiguous_span_iterator& operator-=(difference_type n) { return *this += -n; }
+ difference_type operator-(const contiguous_span_iterator& rhs) const
{
Expects(m_validator == rhs.m_validator);
return data_ - rhs.data_;
}
- reference operator[](difference_type n) const GSL_NOEXCEPT { return *(*this + n); }
- bool operator==(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
+ reference operator[](difference_type n) const { return *(*this + n); }
+ bool operator==(const contiguous_span_iterator& rhs) const
{
Expects(m_validator == rhs.m_validator);
return data_ == rhs.data_;
}
- bool operator!=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
- {
- return !(*this == rhs);
- }
- bool operator<(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
+
+ bool operator!=(const contiguous_span_iterator& rhs) const { return !(*this == rhs); }
+
+ bool operator<(const contiguous_span_iterator& rhs) const
{
Expects(m_validator == rhs.m_validator);
return data_ < rhs.data_;
}
- bool operator<=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
- {
- return !(rhs < *this);
- }
- bool operator>(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; }
- bool operator>=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
- {
- return !(rhs > *this);
- }
- void swap(contiguous_span_iterator& rhs) GSL_NOEXCEPT
+
+ bool operator<=(const contiguous_span_iterator& rhs) const { return !(rhs < *this); }
+ bool operator>(const contiguous_span_iterator& rhs) const { return rhs < *this; }
+ bool operator>=(const contiguous_span_iterator& rhs) const { return !(rhs > *this); }
+
+ void swap(contiguous_span_iterator& rhs) noexcept
{
std::swap(data_, rhs.data_);
std::swap(m_validator, rhs.m_validator);
@@ -2111,22 +2168,19 @@ public:
template <typename Span>
contiguous_span_iterator<Span> operator+(typename contiguous_span_iterator<Span>::difference_type n,
- const contiguous_span_iterator<Span>& rhs) GSL_NOEXCEPT
+ const contiguous_span_iterator<Span>& rhs) noexcept
{
return rhs + n;
}
template <typename Span>
-class general_span_iterator
- : public std::iterator<std::random_access_iterator_tag, typename Span::value_type>
-{
- using Base = std::iterator<std::random_access_iterator_tag, typename Span::value_type>;
-
+class general_span_iterator {
public:
- using typename Base::reference;
- using typename Base::pointer;
- using typename Base::difference_type;
- using typename Base::value_type;
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = typename Span::value_type;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type*;
+ using reference = value_type&;
private:
template <typename ValueType, std::size_t Rank>
@@ -2137,72 +2191,73 @@ private:
general_span_iterator(const Span* container, bool isbegin)
: m_container(container)
, m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end())
- {
- }
+ {}
public:
- reference operator*() GSL_NOEXCEPT { return (*m_container)[*m_itr]; }
- pointer operator->() GSL_NOEXCEPT { return &(*m_container)[*m_itr]; }
- general_span_iterator& operator++() GSL_NOEXCEPT
+ reference operator*() noexcept { return (*m_container)[*m_itr]; }
+ pointer operator->() noexcept { return &(*m_container)[*m_itr]; }
+ general_span_iterator& operator++() noexcept
{
++m_itr;
return *this;
}
- general_span_iterator operator++(int) GSL_NOEXCEPT
+ general_span_iterator operator++(int) noexcept
{
auto ret = *this;
++(*this);
return ret;
}
- general_span_iterator& operator--() GSL_NOEXCEPT
+ general_span_iterator& operator--() noexcept
{
--m_itr;
return *this;
}
- general_span_iterator operator--(int) GSL_NOEXCEPT
+ general_span_iterator operator--(int) noexcept
{
auto ret = *this;
--(*this);
return ret;
}
- general_span_iterator operator+(difference_type n) const GSL_NOEXCEPT
+ general_span_iterator operator+(difference_type n) const noexcept
{
general_span_iterator ret{*this};
return ret += n;
}
- general_span_iterator& operator+=(difference_type n) GSL_NOEXCEPT
+ general_span_iterator& operator+=(difference_type n) noexcept
{
m_itr += n;
return *this;
}
- general_span_iterator operator-(difference_type n) const GSL_NOEXCEPT
+ general_span_iterator operator-(difference_type n) const noexcept
{
general_span_iterator ret{*this};
return ret -= n;
}
- general_span_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; }
- difference_type operator-(const general_span_iterator& rhs) const GSL_NOEXCEPT
+ general_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; }
+ difference_type operator-(const general_span_iterator& rhs) const
{
Expects(m_container == rhs.m_container);
return m_itr - rhs.m_itr;
}
- value_type operator[](difference_type n) const GSL_NOEXCEPT { return (*m_container)[m_itr[n]]; }
- bool operator==(const general_span_iterator& rhs) const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+ value_type operator[](difference_type n) const { return (*m_container)[m_itr[n]]; }
+
+ bool operator==(const general_span_iterator& rhs) const
{
Expects(m_container == rhs.m_container);
return m_itr == rhs.m_itr;
}
- bool operator!=(const general_span_iterator& rhs) const GSL_NOEXCEPT { return !(*this == rhs); }
- bool operator<(const general_span_iterator& rhs) const GSL_NOEXCEPT
+ bool operator!=(const general_span_iterator& rhs) const { return !(*this == rhs); }
+ bool operator<(const general_span_iterator& rhs) const
{
Expects(m_container == rhs.m_container);
return m_itr < rhs.m_itr;
}
- bool operator<=(const general_span_iterator& rhs) const GSL_NOEXCEPT { return !(rhs < *this); }
- bool operator>(const general_span_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; }
- bool operator>=(const general_span_iterator& rhs) const GSL_NOEXCEPT { return !(rhs > *this); }
- void swap(general_span_iterator& rhs) GSL_NOEXCEPT
+ bool operator<=(const general_span_iterator& rhs) const { return !(rhs < *this); }
+ bool operator>(const general_span_iterator& rhs) const { return rhs < *this; }
+ bool operator>=(const general_span_iterator& rhs) const { return !(rhs > *this); }
+ void swap(general_span_iterator& rhs) noexcept
{
std::swap(m_itr, rhs.m_itr);
std::swap(m_container, rhs.m_container);
@@ -2211,15 +2266,13 @@ public:
template <typename Span>
general_span_iterator<Span> operator+(typename general_span_iterator<Span>::difference_type n,
- const general_span_iterator<Span>& rhs) GSL_NOEXCEPT
+ const general_span_iterator<Span>& rhs) noexcept
{
return rhs + n;
}
} // namespace gsl
-#undef GSL_NOEXCEPT
-
#ifdef _MSC_VER
#if _MSC_VER < 1910
@@ -2231,4 +2284,8 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
#endif // _MSC_VER
+#if __GNUC__ > 6
+#pragma GCC diagnostic pop
+#endif // __GNUC__ > 6
+
#endif // GSL_MULTI_SPAN_H
diff --git a/include/gsl/pointers b/include/gsl/pointers
new file mode 100644
index 0000000..a338856
--- /dev/null
+++ b/include/gsl/pointers
@@ -0,0 +1,198 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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_POINTERS_H
+#define GSL_POINTERS_H
+
+#include <gsl/gsl_assert> // for Ensures, Expects
+
+#include <algorithm> // for forward
+#include <iosfwd> // for ptrdiff_t, nullptr_t, ostream, 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(_MSC_VER) && _MSC_VER < 1910
+#pragma push_macro("constexpr")
+#define constexpr /*constexpr*/
+
+#endif // defined(_MSC_VER) && _MSC_VER < 1910
+
+namespace gsl
+{
+
+//
+// GSL.owner: ownership pointers
+//
+using std::unique_ptr;
+using std::shared_ptr;
+
+//
+// owner
+//
+// 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
+//
+template <class T, class = std::enable_if_t<std::is_pointer<T>::value>>
+using owner = T;
+
+//
+// not_null
+//
+// Restricts a pointer or smart pointer to only hold non-null values.
+//
+// Has zero size overhead over T.
+//
+// If T is a pointer (i.e. T == U*) then
+// - allow construction from U*
+// - disallow construction from nullptr_t
+// - disallow default construction
+// - ensure construction from null U* fails
+// - allow implicit conversion to U*
+//
+template <class T>
+class not_null
+{
+public:
+ static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
+
+ template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
+ constexpr explicit not_null(U&& u) : ptr_(std::forward<U>(u))
+ {
+ Expects(ptr_ != nullptr);
+ }
+
+ template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
+ constexpr explicit not_null(T u) : ptr_(u)
+ {
+ Expects(ptr_ != nullptr);
+ }
+
+ 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(not_null&& other) = default;
+ not_null(const not_null& other) = default;
+ not_null& operator=(const not_null& other) = default;
+
+ constexpr T get() const
+ {
+ Ensures(ptr_ != nullptr);
+ return ptr_;
+ }
+
+ constexpr operator T() const { return get(); }
+ constexpr T operator->() const { return get(); }
+ constexpr decltype(auto) operator*() const { return *get(); }
+
+ // prevents compilation when someone attempts to assign a null pointer constant
+ not_null(std::nullptr_t) = delete;
+ not_null& operator=(std::nullptr_t) = delete;
+
+ // unwanted operators...pointers only point to single objects!
+ not_null& operator++() = delete;
+ not_null& operator--() = delete;
+ not_null operator++(int) = delete;
+ not_null operator--(int) = delete;
+ not_null& operator+=(std::ptrdiff_t) = delete;
+ not_null& operator-=(std::ptrdiff_t) = delete;
+ void operator[](std::ptrdiff_t) const = delete;
+
+private:
+ T ptr_;
+};
+
+template <class T>
+auto make_not_null(T&& t) {
+ return gsl::not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
+}
+
+template <class T>
+std::ostream& operator<<(std::ostream& os, const not_null<T>& val)
+{
+ os << val.get();
+ return os;
+}
+
+template <class T, class U>
+auto operator==(const not_null<T>& lhs, const not_null<U>& rhs) -> 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) -> 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) -> 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) -> 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) -> 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) -> decltype(lhs.get() >= rhs.get())
+{
+ return lhs.get() >= rhs.get();
+}
+
+// more unwanted operators
+template <class T, class U>
+std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete;
+template <class T>
+not_null<T> operator-(const not_null<T>&, std::ptrdiff_t) = delete;
+template <class T>
+not_null<T> operator+(const not_null<T>&, std::ptrdiff_t) = delete;
+template <class T>
+not_null<T> operator+(std::ptrdiff_t, const not_null<T>&) = delete;
+
+} // namespace gsl
+
+namespace std
+{
+template <class T>
+struct hash<gsl::not_null<T>>
+{
+ std::size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
+};
+
+} // namespace std
+
+#if defined(_MSC_VER) && _MSC_VER < 1910
+#undef constexpr
+#pragma pop_macro("constexpr")
+
+#endif // defined(_MSC_VER) && _MSC_VER < 1910
+
+#endif // GSL_POINTERS_H
diff --git a/include/gsl/span b/include/gsl/span
index 3f54b48..8cb3dbe 100644
--- a/include/gsl/span
+++ b/include/gsl/span
@@ -14,22 +14,22 @@
//
///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
#ifndef GSL_SPAN_H
#define GSL_SPAN_H
-#include <gsl/gsl_assert>
-#include <gsl/gsl_byte>
-#include <gsl/gsl_util>
+#include <gsl/gsl_assert> // for Expects
+#include <gsl/gsl_byte> // for byte
+#include <gsl/gsl_util> // for narrow_cast, narrow
-#include <array>
-#include <iterator>
+#include <algorithm> // for lexicographical_compare
+#include <array> // for array
+#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
+#include <iterator> // for reverse_iterator, distance, random_access_...
#include <limits>
-#include <memory>
#include <stdexcept>
-#include <type_traits>
+#include <type_traits> // for enable_if_t, declval, is_convertible, inte...
#include <utility>
+#include <memory> // for std::addressof
#ifdef _MSC_VER
#pragma warning(push)
@@ -38,23 +38,33 @@
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4702) // unreachable code
-// blanket turn off warnings from CppCoreCheck for now
-// so people aren't annoyed by them when running the tool.
-// more targeted suppressions will be added in a future update to the GSL
-#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
+// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
+#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
+#pragma warning(disable : 26446) // parser bug does not allow attributes on some templates
#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
+#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
-#endif // _MSC_VER < 1910
-#endif // _MSC_VER
+#endif // _MSC_VER < 1910
+#endif // _MSC_VER
-#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
-#define GSL_NOEXCEPT /*noexcept*/
-#else
-#define GSL_NOEXCEPT noexcept
-#endif // GSL_THROW_ON_CONTRACT_VIOLATION
+// See if we have enough C++17 power to use a static constexpr data member
+// without needing an out-of-line definition
+#if !(defined(__cplusplus) && (__cplusplus >= 201703L))
+#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
+#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L))
+
+// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t)
+// While there is a conversion from signed to unsigned, it happens at
+// compiletime, so the compiler wouldn't have to warn indiscriminently, but
+// could check if the source value actually doesn't fit into the target type
+// and only warn in those cases.
+#if __GNUC__ > 6
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
namespace gsl
{
@@ -117,6 +127,11 @@ namespace details
using element_type_ = typename Span::element_type;
public:
+#ifdef _MSC_VER
+ // Tell Microsoft standard library that span_iterators are checked.
+ using _Unchecked_type = typename Span::pointer;
+#endif
+
using iterator_category = std::random_access_iterator_tag;
using value_type = std::remove_cv_t<element_type_>;
using difference_type = typename Span::index_type;
@@ -126,149 +141,165 @@ namespace details
span_iterator() = default;
- constexpr span_iterator(const Span* span, typename Span::index_type index) GSL_NOEXCEPT
- : span_(span), index_(index)
- {
- Expects(span == nullptr || (index_ >= 0 && index <= span_->length()));
- }
+ constexpr span_iterator(const Span* span, typename Span::index_type idx) noexcept
+ : span_(span), index_(idx)
+ {}
friend span_iterator<Span, true>;
- template<bool B, std::enable_if_t<!B && IsConst>* = nullptr>
- constexpr span_iterator(const span_iterator<Span, B>& other) GSL_NOEXCEPT
+ template <bool B, std::enable_if_t<!B && IsConst>* = nullptr>
+ constexpr span_iterator(const span_iterator<Span, B>& other) noexcept
: span_iterator(other.span_, other.index_)
- {
- }
+ {}
- constexpr reference operator*() const GSL_NOEXCEPT
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ constexpr reference operator*() const
{
- Expects(span_);
- return (*span_)[index_];
+ Expects(index_ != span_->size());
+ return *(span_->data() + index_);
}
- constexpr pointer operator->() const GSL_NOEXCEPT
+ constexpr pointer operator->() const
{
- Expects(span_ && index_ >= 0 && index_ < span_->length());
+ Expects(index_ != span_->size());
return span_->data() + index_;
}
- constexpr span_iterator& operator++() GSL_NOEXCEPT
+ constexpr span_iterator& operator++()
{
- Expects(span_ && index_ >= 0 && index_ < span_->length());
+ Expects(0 <= index_ && index_ != span_->size());
++index_;
return *this;
}
- constexpr span_iterator operator++(int) GSL_NOEXCEPT
+ constexpr span_iterator operator++(int)
{
auto ret = *this;
++(*this);
return ret;
}
- constexpr span_iterator& operator--() GSL_NOEXCEPT
+ constexpr span_iterator& operator--()
{
- Expects(span_ && index_ > 0 && index_ <= span_->length());
+ Expects(index_ != 0 && index_ <= span_->size());
--index_;
return *this;
}
- constexpr span_iterator operator--(int) GSL_NOEXCEPT
+ constexpr span_iterator operator--(int)
{
auto ret = *this;
--(*this);
return ret;
}
- constexpr span_iterator operator+(difference_type n) const GSL_NOEXCEPT
+ constexpr span_iterator operator+(difference_type n) const
{
auto ret = *this;
return ret += n;
}
- constexpr span_iterator& operator+=(difference_type n) GSL_NOEXCEPT
+ friend constexpr span_iterator operator+(difference_type n, span_iterator const& rhs)
{
- Expects(span_ && (index_ + n) >= 0 && (index_ + n) <= span_->length());
+ return rhs + n;
+ }
+
+ constexpr span_iterator& operator+=(difference_type n)
+ {
+ Expects((index_ + n) >= 0 && (index_ + n) <= span_->size());
index_ += n;
return *this;
}
- constexpr span_iterator operator-(difference_type n) const GSL_NOEXCEPT
+ constexpr span_iterator operator-(difference_type n) const
{
auto ret = *this;
return ret -= n;
}
- constexpr span_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; }
+ constexpr span_iterator& operator-=(difference_type n) { return *this += -n; }
- constexpr difference_type operator-(const span_iterator& rhs) const GSL_NOEXCEPT
+ constexpr difference_type operator-(span_iterator rhs) const
{
Expects(span_ == rhs.span_);
return index_ - rhs.index_;
}
- constexpr reference operator[](difference_type n) const GSL_NOEXCEPT
- {
- return *(*this + n);
- }
+ constexpr reference operator[](difference_type n) const { return *(*this + n); }
- constexpr friend bool operator==(const span_iterator& lhs,
- const span_iterator& rhs) GSL_NOEXCEPT
+ constexpr friend bool operator==(span_iterator lhs, span_iterator rhs) noexcept
{
return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_;
}
- constexpr friend bool operator!=(const span_iterator& lhs,
- const span_iterator& rhs) GSL_NOEXCEPT
+ constexpr friend bool operator!=(span_iterator lhs, span_iterator rhs) noexcept
{
return !(lhs == rhs);
}
- constexpr friend bool operator<(const span_iterator& lhs,
- const span_iterator& rhs) GSL_NOEXCEPT
+ constexpr friend bool operator<(span_iterator lhs, span_iterator rhs) noexcept
{
- Expects(lhs.span_ == rhs.span_);
return lhs.index_ < rhs.index_;
}
- constexpr friend bool operator<=(const span_iterator& lhs,
- const span_iterator& rhs) GSL_NOEXCEPT
+ constexpr friend bool operator<=(span_iterator lhs, span_iterator rhs) noexcept
{
return !(rhs < lhs);
}
- constexpr friend bool operator>(const span_iterator& lhs,
- const span_iterator& rhs) GSL_NOEXCEPT
+ constexpr friend bool operator>(span_iterator lhs, span_iterator rhs) noexcept
{
return rhs < lhs;
}
- constexpr friend bool operator>=(const span_iterator& lhs,
- const span_iterator& rhs) GSL_NOEXCEPT
+ constexpr friend bool operator>=(span_iterator lhs, span_iterator rhs) noexcept
{
return !(rhs > lhs);
}
+#ifdef _MSC_VER
+ // MSVC++ iterator debugging support; allows STL algorithms in 15.8+
+ // to unwrap span_iterator to a pointer type after a range check in STL
+ // algorithm calls
+ friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept
+ { // test that [lhs, rhs) forms a valid range inside an STL algorithm
+ Expects(lhs.span_ == rhs.span_ // range spans have to match
+ && lhs.index_ <= rhs.index_); // range must not be transposed
+ }
+
+ constexpr void _Verify_offset(const difference_type n) const noexcept
+ { // test that the iterator *this + n is a valid range in an STL
+ // algorithm call
+ Expects((index_ + n) >= 0 && (index_ + n) <= span_->size());
+ }
+
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ constexpr pointer _Unwrapped() const noexcept
+ { // after seeking *this to a high water mark, or using one of the
+ // _Verify_xxx functions above, unwrap this span_iterator to a raw
+ // pointer
+ return span_->data() + index_;
+ }
+
+ // Tell the STL that span_iterator should not be unwrapped if it can't
+ // validate in advance, even in release / optimized builds:
+#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
+ static constexpr const bool _Unwrap_when_unverified = false;
+#else
+ static constexpr bool _Unwrap_when_unverified = false;
+#endif
+ GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive
+ constexpr void _Seek_to(const pointer p) noexcept
+ { // adjust the position of *this to previously verified location p
+ // after _Unwrapped
+ index_ = p - span_->data();
+ }
+#endif
+
protected:
const Span* span_ = nullptr;
std::ptrdiff_t index_ = 0;
};
- template <class Span, bool IsConst>
- inline constexpr span_iterator<Span, IsConst>
- operator+(typename span_iterator<Span, IsConst>::difference_type n,
- const span_iterator<Span, IsConst>& rhs) GSL_NOEXCEPT
- {
- return rhs + n;
- }
-
- template <class Span, bool IsConst>
- inline constexpr span_iterator<Span, IsConst>
- operator-(typename span_iterator<Span, IsConst>::difference_type n,
- const span_iterator<Span, IsConst>& rhs) GSL_NOEXCEPT
- {
- return rhs - n;
- }
-
template <std::ptrdiff_t Ext>
class extent_type
{
@@ -277,7 +308,7 @@ namespace details
static_assert(Ext >= 0, "A fixed-size span must be >= 0 in size.");
- constexpr extent_type() GSL_NOEXCEPT {}
+ constexpr extent_type() noexcept {}
template <index_type Other>
constexpr extent_type(extent_type<Other> ext)
@@ -289,7 +320,7 @@ namespace details
constexpr extent_type(index_type size) { Expects(size == Ext); }
- constexpr index_type size() const GSL_NOEXCEPT { return Ext; }
+ constexpr index_type size() const noexcept { return Ext; }
};
template <>
@@ -300,16 +331,23 @@ namespace details
template <index_type Other>
explicit constexpr extent_type(extent_type<Other> ext) : size_(ext.size())
- {
- }
+ {}
explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); }
- constexpr index_type size() const GSL_NOEXCEPT { return size_; }
+ constexpr index_type size() const noexcept { return size_; }
private:
index_type size_;
};
+
+ template <class ElementType, std::ptrdiff_t Extent, std::ptrdiff_t Offset, std::ptrdiff_t Count>
+ struct calculate_subspan_type
+ {
+ using type = span<ElementType, Count != dynamic_extent
+ ? Count
+ : (Extent != dynamic_extent ? Extent - Offset : Extent)>;
+ };
} // namespace details
// [span], class template span
@@ -331,56 +369,42 @@ public:
using size_type = index_type;
- constexpr static const index_type extent = Extent;
+#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
+ static constexpr const index_type extent{Extent};
+#else
+ static constexpr index_type extent{Extent};
+#endif
// [span.cons], span constructors, copy, assignment, and destructor
template <bool Dependent = false,
// "Dependent" is needed to make "std::enable_if_t<Dependent || Extent <= 0>" SFINAE,
// since "std::enable_if_t<Extent <= 0>" is ill-formed when Extent is greater than 0.
class = std::enable_if_t<(Dependent || Extent <= 0)>>
- constexpr span() GSL_NOEXCEPT : storage_(nullptr, details::extent_type<0>())
- {
- }
-
- constexpr span(std::nullptr_t) GSL_NOEXCEPT : span() {}
+ constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
+ {}
constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {}
constexpr span(pointer firstElem, pointer lastElem)
: storage_(firstElem, std::distance(firstElem, lastElem))
- {
- }
+ {}
template <std::size_t N>
- constexpr span(element_type (&arr)[N]) GSL_NOEXCEPT
- : storage_(&arr[0], details::extent_type<N>())
- {
- }
+ constexpr span(element_type (&arr)[N]) noexcept
+ : storage_(KnownNotNull{std::addressof(arr[0])}, details::extent_type<N>())
+ {}
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
- constexpr span(std::array<ArrayElementType, N>& arr) GSL_NOEXCEPT
- : storage_(&arr[0], details::extent_type<N>())
- {
- }
+ // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug
+ constexpr span(std::array<ArrayElementType, N>& arr) noexcept
+ : storage_(arr.data(), details::extent_type<N>())
+ {}
template <std::size_t N>
- constexpr span(const std::array<std::remove_const_t<element_type>, N>& arr) GSL_NOEXCEPT
- : storage_(&arr[0], details::extent_type<N>())
- {
- }
-
- template <class ArrayElementType = std::add_pointer<element_type>>
- constexpr span(const std::unique_ptr<ArrayElementType>& ptr, index_type count)
- : storage_(ptr.get(), count)
- {
- }
-
- constexpr span(const std::unique_ptr<ElementType>& ptr) : storage_(ptr.get(), ptr.get() ? 1 : 0)
- {
- }
- constexpr span(const std::shared_ptr<ElementType>& ptr) : storage_(ptr.get(), ptr.get() ? 1 : 0)
- {
- }
+ // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug
+ constexpr span(const std::array<std::remove_const_t<element_type>, N>& arr) noexcept
+ : storage_(arr.data(), details::extent_type<N>())
+ {}
// NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement
// on Container to be a contiguous sequence container.
@@ -391,8 +415,7 @@ public:
std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>>
constexpr span(Container& cont) : span(cont.data(), narrow<index_type>(cont.size()))
- {
- }
+ {}
template <class Container,
class = std::enable_if_t<
@@ -401,11 +424,9 @@ public:
std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>>
constexpr span(const Container& cont) : span(cont.data(), narrow<index_type>(cont.size()))
- {
- }
+ {}
- constexpr span(const span& other) GSL_NOEXCEPT = default;
- constexpr span(span&& other) GSL_NOEXCEPT = default;
+ constexpr span(const span& other) noexcept = default;
template <
class OtherElementType, std::ptrdiff_t OtherExtent,
@@ -414,23 +435,10 @@ public:
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
constexpr span(const span<OtherElementType, OtherExtent>& other)
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
- {
- }
-
- template <
- class OtherElementType, std::ptrdiff_t OtherExtent,
- class = std::enable_if_t<
- details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
- details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
- constexpr span(span<OtherElementType, OtherExtent>&& other)
- : storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
- {
- }
+ {}
- ~span() GSL_NOEXCEPT = default;
- constexpr span& operator=(const span& other) GSL_NOEXCEPT = default;
-
- constexpr span& operator=(span&& other) GSL_NOEXCEPT = default;
+ ~span() noexcept = default;
+ constexpr span& operator=(const span& other) noexcept = default;
// [span.sub], span subviews
template <std::ptrdiff_t Count>
@@ -441,17 +449,21 @@ public:
}
template <std::ptrdiff_t Count>
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr span<element_type, Count> last() const
{
- Expects(Count >= 0 && Count <= size());
+ Expects(Count >= 0 && size() - Count >= 0);
return {data() + (size() - Count), Count};
}
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
- constexpr span<element_type, Count> subspan() const
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ constexpr auto subspan() const ->
+ typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
{
- Expects((Offset == 0 || (Offset > 0 && Offset <= size())) &&
+ Expects((Offset >= 0 && size() - Offset >= 0) &&
(Count == dynamic_extent || (Count >= 0 && Offset + Count <= size())));
+
return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
}
@@ -463,53 +475,93 @@ public:
constexpr span<element_type, dynamic_extent> last(index_type count) const
{
- Expects(count >= 0 && count <= size());
- return {data() + (size() - count), count};
+ return make_subspan(size() - count, dynamic_extent, subspan_selector<Extent>{});
}
constexpr span<element_type, dynamic_extent> subspan(index_type offset,
index_type count = dynamic_extent) const
{
- Expects((offset == 0 || (offset > 0 && offset <= size())) &&
- (count == dynamic_extent || (count >= 0 && offset + count <= size())));
- return {data() + offset, count == dynamic_extent ? size() - offset : count};
+ return make_subspan(offset, count, subspan_selector<Extent>{});
}
// [span.obs], span observers
- constexpr index_type length() const GSL_NOEXCEPT { return size(); }
- constexpr index_type size() const GSL_NOEXCEPT { return storage_.size(); }
- constexpr index_type length_bytes() const GSL_NOEXCEPT { return size_bytes(); }
- constexpr index_type size_bytes() const GSL_NOEXCEPT
+ constexpr index_type size() const noexcept { return storage_.size(); }
+ constexpr index_type size_bytes() const noexcept
{
return size() * narrow_cast<index_type>(sizeof(element_type));
}
- constexpr bool empty() const GSL_NOEXCEPT { return size() == 0; }
+ constexpr bool empty() const noexcept { return size() == 0; }
// [span.elem], span element access
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr reference operator[](index_type idx) const
{
- Expects(idx >= 0 && idx < storage_.size());
+ Expects(CheckRange(idx, storage_.size()));
return data()[idx];
}
constexpr reference at(index_type idx) const { return this->operator[](idx); }
constexpr reference operator()(index_type idx) const { return this->operator[](idx); }
- constexpr pointer data() const GSL_NOEXCEPT { return storage_.data(); }
+ constexpr pointer data() const noexcept { return storage_.data(); }
// [span.iter], span iterator support
- iterator begin() const GSL_NOEXCEPT { return {this, 0}; }
- iterator end() const GSL_NOEXCEPT { return {this, length()}; }
+ constexpr iterator begin() const noexcept { return {this, 0}; }
+ constexpr iterator end() const noexcept { return {this, size()}; }
- const_iterator cbegin() const GSL_NOEXCEPT { return {this, 0}; }
- const_iterator cend() const GSL_NOEXCEPT { return {this, length()}; }
+ constexpr const_iterator cbegin() const noexcept { return {this, 0}; }
+ constexpr const_iterator cend() const noexcept { return {this, size()}; }
- reverse_iterator rbegin() const GSL_NOEXCEPT { return reverse_iterator{end()}; }
- reverse_iterator rend() const GSL_NOEXCEPT { return reverse_iterator{begin()}; }
+ constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
+ constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
- const_reverse_iterator crbegin() const GSL_NOEXCEPT { return const_reverse_iterator{cend()}; }
- const_reverse_iterator crend() const GSL_NOEXCEPT { return const_reverse_iterator{cbegin()}; }
+ constexpr const_reverse_iterator crbegin() const noexcept
+ {
+ return const_reverse_iterator{cend()};
+ }
+ constexpr const_reverse_iterator crend() const noexcept
+ {
+ return const_reverse_iterator{cbegin()};
+ }
+
+#ifdef _MSC_VER
+ // Tell MSVC how to unwrap spans in range-based-for
+ constexpr pointer _Unchecked_begin() const noexcept { return data(); }
+ constexpr pointer _Unchecked_end() const noexcept
+ {
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ return data() + size();
+ }
+#endif // _MSC_VER
private:
+ static bool CheckRange(index_type idx, index_type size)
+ {
+ // Optimization:
+ //
+ // idx >= 0 && idx < size
+ // =>
+ // static_cast<size_t>(idx) < static_cast<size_t>(size)
+ //
+ // because size >=0 by span construction, and negative idx will
+ // wrap around to a value always greater than size when casted.
+
+ // check if we have enough space to wrap around
+ if (sizeof(index_type) <= sizeof(size_t))
+ {
+ return narrow_cast<size_t>(idx) < narrow_cast<size_t>(size);
+ }
+ else
+ {
+ return idx >= 0 && idx < size;
+ }
+ }
+
+ // Needed to remove unnecessary null check in subspans
+ struct KnownNotNull
+ {
+ pointer p;
+ };
+
// this implementation detail class lets us take advantage of the
// empty base class optimization to pay for only storage of a single
// pointer in the case of fixed-size spans
@@ -517,60 +569,98 @@ private:
class storage_type : public ExtentType
{
public:
+ // KnownNotNull parameter is needed to remove unnecessary null check
+ // in subspans and constructors from arrays
+ template <class OtherExtentType>
+ constexpr storage_type(KnownNotNull data, OtherExtentType ext)
+ : ExtentType(ext), data_(data.p)
+ {
+ Expects(ExtentType::size() >= 0);
+ }
+
template <class OtherExtentType>
constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
{
- Expects((!data && ExtentType::size() == 0) || (data && ExtentType::size() >= 0));
+ Expects(ExtentType::size() >= 0);
+ Expects(data || ExtentType::size() == 0);
}
- constexpr pointer data() const GSL_NOEXCEPT { return data_; }
+ constexpr pointer data() const noexcept { return data_; }
private:
pointer data_;
};
storage_type<details::extent_type<Extent>> storage_;
+
+ // The rest is needed to remove unnecessary null check
+ // in subspans and constructors from arrays
+ constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {}
+
+ template <std::ptrdiff_t CallerExtent>
+ class subspan_selector
+ {
+ };
+
+ template <std::ptrdiff_t CallerExtent>
+ span<element_type, dynamic_extent> make_subspan(index_type offset, index_type count,
+ subspan_selector<CallerExtent>) const
+ {
+ const span<element_type, dynamic_extent> tmp(*this);
+ return tmp.subspan(offset, count);
+ }
+
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ span<element_type, dynamic_extent> make_subspan(index_type offset, index_type count,
+ subspan_selector<dynamic_extent>) const
+ {
+ Expects(offset >= 0 && size() - offset >= 0);
+
+ if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; }
+
+ Expects(count >= 0 && size() - offset >= count);
+ return {KnownNotNull{data() + offset}, count};
+ }
};
+#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
+template <class ElementType, std::ptrdiff_t Extent>
+constexpr const typename span<ElementType, Extent>::index_type span<ElementType, Extent>::extent;
+#endif
+
// [span.comparison], span comparison operators
template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent>
-inline constexpr bool operator==(const span<ElementType, FirstExtent>& l,
- const span<ElementType, SecondExtent>& r)
+constexpr bool operator==(span<ElementType, FirstExtent> l, span<ElementType, SecondExtent> r)
{
return std::equal(l.begin(), l.end(), r.begin(), r.end());
}
template <class ElementType, std::ptrdiff_t Extent>
-inline constexpr bool operator!=(const span<ElementType, Extent>& l,
- const span<ElementType, Extent>& r)
+constexpr bool operator!=(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
return !(l == r);
}
template <class ElementType, std::ptrdiff_t Extent>
-inline constexpr bool operator<(const span<ElementType, Extent>& l,
- const span<ElementType, Extent>& r)
+constexpr bool operator<(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
}
template <class ElementType, std::ptrdiff_t Extent>
-inline constexpr bool operator<=(const span<ElementType, Extent>& l,
- const span<ElementType, Extent>& r)
+constexpr bool operator<=(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
return !(l > r);
}
template <class ElementType, std::ptrdiff_t Extent>
-inline constexpr bool operator>(const span<ElementType, Extent>& l,
- const span<ElementType, Extent>& r)
+constexpr bool operator>(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
return r < l;
}
template <class ElementType, std::ptrdiff_t Extent>
-inline constexpr bool operator>=(const span<ElementType, Extent>& l,
- const span<ElementType, Extent>& r)
+constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
return !(l < r);
}
@@ -596,21 +686,23 @@ namespace details
: std::integral_constant<std::ptrdiff_t, dynamic_extent>
{
};
-}
+} // namespace details
// [span.objectrep], views of object representation
template <class ElementType, std::ptrdiff_t Extent>
span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
-as_bytes(span<ElementType, Extent> s) GSL_NOEXCEPT
+as_bytes(span<ElementType, Extent> s) noexcept
{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
}
template <class ElementType, std::ptrdiff_t Extent,
class = std::enable_if_t<!std::is_const<ElementType>::value>>
span<byte, details::calculate_byte_size<ElementType, Extent>::value>
-as_writeable_bytes(span<ElementType, Extent> s) GSL_NOEXCEPT
+as_writeable_bytes(span<ElementType, Extent> s) noexcept
{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}
@@ -618,59 +710,58 @@ as_writeable_bytes(span<ElementType, Extent> s) GSL_NOEXCEPT
// make_span() - Utility functions for creating spans
//
template <class ElementType>
-span<ElementType> make_span(ElementType* ptr, typename span<ElementType>::index_type count)
+constexpr span<ElementType> make_span(ElementType* ptr,
+ typename span<ElementType>::index_type count)
{
return span<ElementType>(ptr, count);
}
template <class ElementType>
-span<ElementType> make_span(ElementType* firstElem, ElementType* lastElem)
+constexpr span<ElementType> make_span(ElementType* firstElem, ElementType* lastElem)
{
return span<ElementType>(firstElem, lastElem);
}
template <class ElementType, std::size_t N>
-span<ElementType, N> make_span(ElementType (&arr)[N])
+constexpr span<ElementType, N> make_span(ElementType (&arr)[N]) noexcept
{
return span<ElementType, N>(arr);
}
template <class Container>
-span<typename Container::value_type> make_span(Container& cont)
+constexpr span<typename Container::value_type> make_span(Container& cont)
{
return span<typename Container::value_type>(cont);
}
template <class Container>
-span<const typename Container::value_type> make_span(const Container& cont)
+constexpr span<const typename Container::value_type> make_span(const Container& cont)
{
return span<const typename Container::value_type>(cont);
}
template <class Ptr>
-span<typename Ptr::element_type> make_span(Ptr& cont, std::ptrdiff_t count)
+constexpr span<typename Ptr::element_type> make_span(Ptr& cont, std::ptrdiff_t count)
{
return span<typename Ptr::element_type>(cont, count);
}
template <class Ptr>
-span<typename Ptr::element_type> make_span(Ptr& cont)
+constexpr span<typename Ptr::element_type> make_span(Ptr& cont)
{
return span<typename Ptr::element_type>(cont);
}
// Specialization of gsl::at for span
template <class ElementType, std::ptrdiff_t Extent>
-inline constexpr ElementType& at(const span<ElementType, Extent>& s, std::ptrdiff_t index)
+constexpr ElementType& at(span<ElementType, Extent> s, index i)
{
// No bounds checking here because it is done in span::operator[] called below
- return s[index];
+ return s[i];
}
} // namespace gsl
-#undef GSL_NOEXCEPT
-
#ifdef _MSC_VER
#if _MSC_VER < 1910
#undef constexpr
@@ -681,4 +772,8 @@ inline constexpr ElementType& at(const span<ElementType, Extent>& s, std::ptrdif
#pragma warning(pop)
#endif // _MSC_VER
+#if __GNUC__ > 6
+#pragma GCC diagnostic pop
+#endif // __GNUC__ > 6
+
#endif // GSL_SPAN_H
diff --git a/include/gsl/string_span b/include/gsl/string_span
index 26ae3e8..d298039 100644
--- a/include/gsl/string_span
+++ b/include/gsl/string_span
@@ -14,40 +14,35 @@
//
///////////////////////////////////////////////////////////////////////////////
-#pragma once
-
#ifndef GSL_STRING_SPAN_H
#define GSL_STRING_SPAN_H
-#include <gsl/gsl_assert>
-#include <gsl/gsl_util>
-#include <gsl/span>
+#include <gsl/gsl_assert> // for Ensures, Expects
+#include <gsl/gsl_util> // for narrow_cast
+#include <gsl/span> // for operator!=, operator==, dynamic_extent
+#include <gsl/pointers> // for not_null
-#include <cstdint>
+#include <algorithm> // for equal, lexicographical_compare
+#include <array> // for array
+#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
+#include <cstdint> // for PTRDIFF_MAX
#include <cstring>
-#include <string>
+#include <string> // for basic_string, allocator, char_traits
+#include <type_traits> // for declval, is_convertible, enable_if_t, add_...
#ifdef _MSC_VER
#pragma warning(push)
-// blanket turn off warnings from CppCoreCheck for now
-// so people aren't annoyed by them when running the tool.
-// more targeted suppressions will be added in a future update to the GSL
-#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
+// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
+#pragma warning(disable : 26446) // TODO: bug in parser - attributes and templates
+#pragma warning(disable : 26481) // TODO: suppress does not work inside templates sometimes
#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
-#endif // _MSC_VER < 1910
-#endif // _MSC_VER
-
-// In order to test the library, we need it to throw exceptions that we can catch
-#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
-#define GSL_NOEXCEPT /*noexcept*/
-#else
-#define GSL_NOEXCEPT noexcept
-#endif // GSL_THROW_ON_CONTRACT_VIOLATION
+#endif // _MSC_VER < 1910
+#endif // _MSC_VER
namespace gsl
{
@@ -72,37 +67,38 @@ template <std::ptrdiff_t Extent = dynamic_extent>
using cwzstring = basic_zstring<const wchar_t, Extent>;
template <std::ptrdiff_t Extent = dynamic_extent>
-using zstring = basic_zstring<char, Extent>;
+using cu16zstring = basic_zstring<const char16_t, Extent>;
template <std::ptrdiff_t Extent = dynamic_extent>
-using wzstring = basic_zstring<wchar_t, Extent>;
+using cu32zstring = basic_zstring<const char32_t, Extent>;
-namespace details
-{
- inline std::ptrdiff_t string_length(const char* str, std::ptrdiff_t n)
- {
- if (str == nullptr || n <= 0) return 0;
+template <std::ptrdiff_t Extent = dynamic_extent>
+using zstring = basic_zstring<char, Extent>;
- span<const char> str_span{str, n};
+template <std::ptrdiff_t Extent = dynamic_extent>
+using wzstring = basic_zstring<wchar_t, Extent>;
- std::ptrdiff_t len = 0;
- while (len < n && str_span[len]) len++;
+template <std::ptrdiff_t Extent = dynamic_extent>
+using u16zstring = basic_zstring<char16_t, Extent>;
- return len;
- }
+template <std::ptrdiff_t Extent = dynamic_extent>
+using u32zstring = basic_zstring<char32_t, Extent>;
- inline std::ptrdiff_t wstring_length(const wchar_t* str, std::ptrdiff_t n)
+namespace details
+{
+ template <class CharT>
+ std::ptrdiff_t string_length(const CharT* str, std::ptrdiff_t n)
{
if (str == nullptr || n <= 0) return 0;
- span<const wchar_t> str_span{str, n};
+ const span<const CharT> str_span{str, n};
std::ptrdiff_t len = 0;
while (len < n && str_span[len]) len++;
return len;
}
-}
+} // namespace details
//
// ensure_sentinel()
@@ -115,71 +111,46 @@ namespace details
template <typename T, const T Sentinel>
span<T, dynamic_extent> ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX)
{
+ Ensures(seq != nullptr);
+
+ GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // TODO: false positive // TODO: suppress does not work
auto cur = seq;
+ Ensures(cur != nullptr); // workaround for removing the warning
+
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // TODO: suppress does not work
while ((cur - seq) < max && *cur != Sentinel) ++cur;
Ensures(*cur == Sentinel);
return {seq, cur - seq};
}
//
-// ensure_z - creates a span for a czstring or cwzstring.
+// ensure_z - creates a span for a zero terminated strings.
// Will fail fast if a null-terminator cannot be found before
// the limit of size_type.
//
-template <typename T>
-inline span<T, dynamic_extent> ensure_z(T* const& sz, std::ptrdiff_t max = PTRDIFF_MAX)
+template <typename CharT>
+span<CharT, dynamic_extent> ensure_z(CharT* const& sz, std::ptrdiff_t max = PTRDIFF_MAX)
{
- return ensure_sentinel<T, 0>(sz, max);
+ return ensure_sentinel<CharT, CharT(0)>(sz, max);
}
-// TODO (neilmac) there is probably a better template-magic way to get the const and non-const
-// overloads to share an implementation
-inline span<char, dynamic_extent> ensure_z(char* const& sz, std::ptrdiff_t max)
+template <typename CharT, std::size_t N>
+span<CharT, dynamic_extent> ensure_z(CharT (&sz)[N])
{
- auto len = details::string_length(sz, max);
- Ensures(sz[len] == 0);
- return {sz, len};
-}
-
-inline span<const char, dynamic_extent> ensure_z(const char* const& sz, std::ptrdiff_t max)
-{
- auto len = details::string_length(sz, max);
- Ensures(sz[len] == 0);
- return {sz, len};
-}
-
-inline span<wchar_t, dynamic_extent> ensure_z(wchar_t* const& sz, std::ptrdiff_t max)
-{
- auto len = details::wstring_length(sz, max);
- Ensures(sz[len] == 0);
- return {sz, len};
-}
-
-inline span<const wchar_t, dynamic_extent> ensure_z(const wchar_t* const& sz, std::ptrdiff_t max)
-{
- auto len = details::wstring_length(sz, max);
- Ensures(sz[len] == 0);
- return {sz, len};
-}
-
-template <typename T, std::size_t N>
-span<T, dynamic_extent> ensure_z(T (&sz)[N])
-{
- return ensure_z(&sz[0], static_cast<std::ptrdiff_t>(N));
+ return ensure_z(&sz[0], narrow_cast<std::ptrdiff_t>(N));
}
template <class Cont>
span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent>
ensure_z(Cont& cont)
{
- return ensure_z(cont.data(), static_cast<std::ptrdiff_t>(cont.length()));
+ return ensure_z(cont.data(), narrow_cast<std::ptrdiff_t>(cont.size()));
}
template <typename CharT, std::ptrdiff_t>
class basic_string_span;
-namespace details
-{
+namespace details {
template <typename T>
struct is_basic_string_span_oracle : std::false_type
{
@@ -194,48 +165,7 @@ namespace details
struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>>
{
};
-
- template <typename T>
- struct length_func
- {
- };
-
- template <>
- struct length_func<char>
- {
- std::ptrdiff_t operator()(const char* const ptr, std::ptrdiff_t length) GSL_NOEXCEPT
- {
- return details::string_length(ptr, length);
- }
- };
-
- template <>
- struct length_func<wchar_t>
- {
- std::ptrdiff_t operator()(const wchar_t* const ptr, std::ptrdiff_t length) GSL_NOEXCEPT
- {
- return details::wstring_length(ptr, length);
- }
- };
-
- template <>
- struct length_func<const char>
- {
- std::ptrdiff_t operator()(const char* const ptr, std::ptrdiff_t length) GSL_NOEXCEPT
- {
- return details::string_length(ptr, length);
- }
- };
-
- template <>
- struct length_func<const wchar_t>
- {
- std::ptrdiff_t operator()(const wchar_t* const ptr, std::ptrdiff_t length) GSL_NOEXCEPT
- {
- return details::wstring_length(ptr, length);
- }
- };
-}
+} // namespace details
//
// string_span and relatives
@@ -257,22 +187,13 @@ public:
using const_reverse_iterator = typename impl_type::const_reverse_iterator;
// default (empty)
- constexpr basic_string_span() GSL_NOEXCEPT = default;
+ constexpr basic_string_span() noexcept = default;
// copy
- constexpr basic_string_span(const basic_string_span& other) GSL_NOEXCEPT = default;
-
-// move
- constexpr basic_string_span(basic_string_span&& other) GSL_NOEXCEPT = default;
+ constexpr basic_string_span(const basic_string_span& other) noexcept = default;
// assign
- constexpr basic_string_span& operator=(const basic_string_span& other) GSL_NOEXCEPT = default;
-
-// move assign
- constexpr basic_string_span& operator=(basic_string_span&& other) GSL_NOEXCEPT = default;
-
- // from nullptr
- constexpr basic_string_span(std::nullptr_t ptr) GSL_NOEXCEPT : span_(ptr) {}
+ constexpr basic_string_span& operator=(const basic_string_span& other) noexcept = default;
constexpr basic_string_span(pointer ptr, index_type length) : span_(ptr, length) {}
constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {}
@@ -281,32 +202,27 @@ public:
// All other containers allow 0s within the length, so we do not remove them
template <std::size_t N>
constexpr basic_string_span(element_type (&arr)[N]) : span_(remove_z(arr))
- {
- }
+ {}
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
- constexpr basic_string_span(std::array<ArrayElementType, N>& arr) GSL_NOEXCEPT : span_(arr)
- {
- }
+ constexpr basic_string_span(std::array<ArrayElementType, N>& arr) noexcept : span_(arr)
+ {}
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
- constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) GSL_NOEXCEPT
- : span_(arr)
- {
- }
+ constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) noexcept : span_(arr)
+ {}
// Container signature should work for basic_string after C++17 version exists
template <class Traits, class Allocator>
+ // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug
constexpr basic_string_span(std::basic_string<element_type, Traits, Allocator>& str)
: span_(&str[0], narrow_cast<std::ptrdiff_t>(str.length()))
- {
- }
+ {}
template <class Traits, class Allocator>
constexpr basic_string_span(const std::basic_string<element_type, Traits, Allocator>& str)
: span_(&str[0], str.length())
- {
- }
+ {}
// from containers. Containers must have a pointer type and data() function signatures
template <class Container,
@@ -316,8 +232,7 @@ public:
std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>>
constexpr basic_string_span(Container& cont) : span_(cont)
- {
- }
+ {}
template <class Container,
class = std::enable_if_t<
@@ -326,8 +241,7 @@ public:
std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>>
constexpr basic_string_span(const Container& cont) : span_(cont)
- {
- }
+ {}
// from string_span
template <
@@ -336,8 +250,7 @@ public:
typename basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>>
constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other)
: span_(other.data(), other.length())
- {
- }
+ {}
template <index_type Count>
constexpr basic_string_span<element_type, Count> first() const
@@ -378,28 +291,28 @@ public:
constexpr pointer data() const { return span_.data(); }
- constexpr index_type length() const GSL_NOEXCEPT { return span_.size(); }
- constexpr index_type size() const GSL_NOEXCEPT { return span_.size(); }
- constexpr index_type size_bytes() const GSL_NOEXCEPT { return span_.size_bytes(); }
- constexpr index_type length_bytes() const GSL_NOEXCEPT { return span_.length_bytes(); }
- constexpr bool empty() const GSL_NOEXCEPT { return size() == 0; }
+ constexpr index_type length() const noexcept { return span_.size(); }
+ constexpr index_type size() const noexcept { return span_.size(); }
+ constexpr index_type size_bytes() const noexcept { return span_.size_bytes(); }
+ constexpr index_type length_bytes() const noexcept { return span_.length_bytes(); }
+ constexpr bool empty() const noexcept { return size() == 0; }
- constexpr iterator begin() const GSL_NOEXCEPT { return span_.begin(); }
- constexpr iterator end() const GSL_NOEXCEPT { return span_.end(); }
+ constexpr iterator begin() const noexcept { return span_.begin(); }
+ constexpr iterator end() const noexcept { return span_.end(); }
- constexpr const_iterator cbegin() const GSL_NOEXCEPT { return span_.cbegin(); }
- constexpr const_iterator cend() const GSL_NOEXCEPT { return span_.cend(); }
+ constexpr const_iterator cbegin() const noexcept { return span_.cbegin(); }
+ constexpr const_iterator cend() const noexcept { return span_.cend(); }
- constexpr reverse_iterator rbegin() const GSL_NOEXCEPT { return span_.rbegin(); }
- constexpr reverse_iterator rend() const GSL_NOEXCEPT { return span_.rend(); }
+ constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); }
+ constexpr reverse_iterator rend() const noexcept { return span_.rend(); }
- constexpr const_reverse_iterator crbegin() const GSL_NOEXCEPT { return span_.crbegin(); }
- constexpr const_reverse_iterator crend() const GSL_NOEXCEPT { return span_.crend(); }
+ constexpr const_reverse_iterator crbegin() const noexcept { return span_.crbegin(); }
+ constexpr const_reverse_iterator crend() const noexcept { return span_.crend(); }
private:
static impl_type remove_z(pointer const& sz, std::ptrdiff_t max)
{
- return {sz, details::length_func<element_type>()(sz, max)};
+ return {sz, details::string_length(sz, max)};
}
template <std::size_t N>
@@ -423,6 +336,18 @@ using wstring_span = basic_string_span<wchar_t, Extent>;
template <std::ptrdiff_t Extent = dynamic_extent>
using cwstring_span = basic_string_span<const wchar_t, Extent>;
+template <std::ptrdiff_t Extent = dynamic_extent>
+using u16string_span = basic_string_span<char16_t, Extent>;
+
+template <std::ptrdiff_t Extent = dynamic_extent>
+using cu16string_span = basic_string_span<const char16_t, Extent>;
+
+template <std::ptrdiff_t Extent = dynamic_extent>
+using u32string_span = basic_string_span<char32_t, Extent>;
+
+template <std::ptrdiff_t Extent = dynamic_extent>
+using cu32string_span = basic_string_span<const char32_t, Extent>;
+
//
// to_string() allow (explicit) conversions from string_span to string
//
@@ -431,21 +356,37 @@ template <typename CharT, std::ptrdiff_t Extent>
std::basic_string<typename std::remove_const<CharT>::type>
to_string(basic_string_span<CharT, Extent> view)
{
- return {view.data(), static_cast<std::size_t>(view.length())};
+ return {view.data(), narrow_cast<std::size_t>(view.length())};
}
template <typename CharT, typename Traits = typename std::char_traits<CharT>,
typename Allocator = std::allocator<CharT>, typename gCharT, std::ptrdiff_t Extent>
std::basic_string<CharT, Traits, Allocator> to_basic_string(basic_string_span<gCharT, Extent> view)
{
- return {view.data(), static_cast<std::size_t>(view.length())};
+ return {view.data(), narrow_cast<std::size_t>(view.length())};
+}
+
+template <class ElementType, std::ptrdiff_t Extent>
+basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
+as_bytes(basic_string_span<ElementType, Extent> s) noexcept
+{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
+}
+
+template <class ElementType, std::ptrdiff_t Extent,
+ class = std::enable_if_t<!std::is_const<ElementType>::value>>
+basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value>
+as_writeable_bytes(basic_string_span<ElementType, Extent> s) noexcept
+{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}
// zero-terminated string span, used to convert
// zero-terminated spans to legacy strings
template <typename CharT, std::ptrdiff_t Extent = dynamic_extent>
-class basic_zstring_span
-{
+class basic_zstring_span {
public:
using value_type = CharT;
using const_value_type = std::add_const_t<CharT>;
@@ -459,7 +400,7 @@ public:
using impl_type = span<value_type, Extent>;
using string_span_type = basic_string_span<value_type, Extent>;
- constexpr basic_zstring_span(impl_type s) GSL_NOEXCEPT : span_(s)
+ constexpr basic_zstring_span(impl_type s) : span_(s)
{
// expects a zero-terminated span
Expects(s[s.size() - 1] == '\0');
@@ -468,26 +409,25 @@ public:
// copy
constexpr basic_zstring_span(const basic_zstring_span& other) = default;
-// move
+ // move
constexpr basic_zstring_span(basic_zstring_span&& other) = default;
// assign
constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default;
-// move assign
+ // move assign
constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default;
- constexpr bool empty() const GSL_NOEXCEPT { return span_.size() == 0; }
+ constexpr bool empty() const noexcept { return span_.size() == 0; }
- constexpr string_span_type as_string_span() const GSL_NOEXCEPT
+ constexpr string_span_type as_string_span() const noexcept
{
- auto sz = span_.size();
- return span_.first(sz <= 0 ? 0 : sz - 1);
+ const auto sz = span_.size();
+ return {span_.data(), sz > 1 ? sz - 1 : 0};
}
+ constexpr string_span_type ensure_z() const { return gsl::ensure_z(span_); }
- constexpr string_span_type ensure_z() const GSL_NOEXCEPT { return gsl::ensure_z(span_); }
-
- constexpr const_zstring_type assume_z() const GSL_NOEXCEPT { return span_.data(); }
+ constexpr const_zstring_type assume_z() const noexcept { return span_.data(); }
private:
impl_type span_;
@@ -500,17 +440,29 @@ template <std::ptrdiff_t Max = dynamic_extent>
using wzstring_span = basic_zstring_span<wchar_t, Max>;
template <std::ptrdiff_t Max = dynamic_extent>
+using u16zstring_span = basic_zstring_span<char16_t, Max>;
+
+template <std::ptrdiff_t Max = dynamic_extent>
+using u32zstring_span = basic_zstring_span<char32_t, Max>;
+
+template <std::ptrdiff_t Max = dynamic_extent>
using czstring_span = basic_zstring_span<const char, Max>;
template <std::ptrdiff_t Max = dynamic_extent>
using cwzstring_span = basic_zstring_span<const wchar_t, Max>;
+template <std::ptrdiff_t Max = dynamic_extent>
+using cu16zstring_span = basic_zstring_span<const char16_t, Max>;
+
+template <std::ptrdiff_t Max = dynamic_extent>
+using cu32zstring_span = basic_zstring_span<const char32_t, Max>;
+
// operator ==
template <class CharT, std::ptrdiff_t Extent, class T,
class = std::enable_if_t<
details::is_basic_string_span<T>::value ||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>>
-bool operator==(const gsl::basic_string_span<CharT, Extent>& one, const T& other) GSL_NOEXCEPT
+bool operator==(const gsl::basic_string_span<CharT, Extent>& one, const T& other)
{
const gsl::basic_string_span<std::add_const_t<CharT>> tmp(other);
return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end());
@@ -520,9 +472,9 @@ template <class CharT, std::ptrdiff_t Extent, class T,
class = std::enable_if_t<
!details::is_basic_string_span<T>::value &&
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>>
-bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other) GSL_NOEXCEPT
+bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other)
{
- gsl::basic_string_span<std::add_const_t<CharT>> tmp(one);
+ const gsl::basic_string_span<std::add_const_t<CharT>> tmp(one);
return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end());
}
@@ -530,17 +482,17 @@ bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
-bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
return !(one == other);
}
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
-bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
return !(one == other);
}
@@ -549,7 +501,7 @@ bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_N
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
-bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
const gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
@@ -557,10 +509,10 @@ bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NO
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
-bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end());
@@ -574,12 +526,12 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NO
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>>
-bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
@@ -588,12 +540,12 @@ bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NO
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>>
-bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end());
@@ -604,17 +556,17 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NO
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
-bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
return !(other < one);
}
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
-bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
return !(other < one);
}
@@ -627,12 +579,12 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_N
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>>
-bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
return !(other < one);
}
@@ -640,12 +592,12 @@ bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_N
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>>
-bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
return !(other < one);
}
@@ -655,17 +607,17 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_N
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
-bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
return other < one;
}
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
-bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
return other < one;
}
@@ -678,12 +630,12 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NO
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>>
-bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
return other < one;
}
@@ -691,12 +643,12 @@ bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NO
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>>
-bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
return other < one;
}
@@ -706,17 +658,17 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NO
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
-bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
return !(one < other);
}
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
-bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
return !(one < other);
}
@@ -729,12 +681,12 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_N
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>>
-bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT
+bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
return !(one < other);
}
@@ -742,19 +694,17 @@ bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_N
template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type,
- typename Dummy = std::enable_if_t<
+ typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>>
-bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT
+bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
return !(one < other);
}
#endif
-} // namespace GSL
-
-#undef GSL_NOEXCEPT
+} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
diff --git a/samples/gsl_transition b/samples/gsl_transition
new file mode 100644
index 0000000..3f5bf6c
--- /dev/null
+++ b/samples/gsl_transition
@@ -0,0 +1,130 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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_TRANSITION_H
+#define GSL_TRANSITION_H
+
+#include <gsl/gsl_assert> // for Ensures, Expects
+#include <gsl/pointers> // for gsl::not_null
+
+#if defined(_MSC_VER) && _MSC_VER < 1910
+#pragma push_macro("constexpr")
+#define constexpr /*constexpr*/
+
+#endif // defined(_MSC_VER) && _MSC_VER < 1910
+
+namespace gsl_helpers
+{
+//
+// sloppy_not_null
+//
+// Restricts a pointer or smart pointer to only hold non-null values,
+//
+// - provides a sloppy (i.e. no explicit contructor from T) wrapper of gsl::not_null
+// - is temporary, only to be used to incrementally transition of code
+// using older version of gsl::not_null to the new one that made the constructor explicit
+//
+// To make the transition:
+//
+// - replace all occurences of gsl::not_null in your code by sloppy_not_null
+// variant: rename gsl::not_null by NotNull by including the following in your code,
+// foe example, in a common include file:
+//
+// template<typename T>
+// using NotNull = gsl::not_null<T>;
+//
+// compile using old version of GSL
+// change GSL version and replace gsl::not_null by gsl_helpers::sloppy_not_null
+// in the added code lines above
+//
+// - compile - compilation should be successful
+// - replace some sloppy_not_nulls by gsl::not_null, fix compilation erros,
+// redesign as needed, compile and test
+// - repeat until no sloppy_not_nulls remain
+//
+template <class T>
+class sloppy_not_null: public gsl::not_null<T>
+{
+public:
+
+ template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
+ constexpr sloppy_not_null(U&& u) :
+ gsl::not_null<T>(std::forward<U>(u))
+ {}
+
+ template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
+ constexpr sloppy_not_null(T u) :
+ gsl::not_null<T>(u)
+ {}
+
+ template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
+ constexpr sloppy_not_null(const gsl::not_null<U>& other) :
+ gsl::not_null<T>(other)
+ {}
+
+ sloppy_not_null(sloppy_not_null&& other) = default;
+ sloppy_not_null(const sloppy_not_null& other) = default;
+ sloppy_not_null& operator=(const sloppy_not_null& other) = default;
+ sloppy_not_null& operator=(const gsl::not_null<T>& other)
+ {
+ gsl::not_null<T>::operator=(other);
+ return *this;
+ }
+
+ // prevents compilation when someone attempts to assign a null pointer constant
+ sloppy_not_null(std::nullptr_t) = delete;
+ sloppy_not_null& operator=(std::nullptr_t) = delete;
+
+ // unwanted operators...pointers only point to single objects!
+ sloppy_not_null& operator++() = delete;
+ sloppy_not_null& operator--() = delete;
+ sloppy_not_null operator++(int) = delete;
+ sloppy_not_null operator--(int) = delete;
+ sloppy_not_null& operator+=(std::ptrdiff_t) = delete;
+ sloppy_not_null& operator-=(std::ptrdiff_t) = delete;
+ void operator[](std::ptrdiff_t) const = delete;
+};
+
+// more unwanted operators
+template <class T, class U>
+std::ptrdiff_t operator-(const sloppy_not_null<T>&, const sloppy_not_null<U>&) = delete;
+template <class T>
+sloppy_not_null<T> operator-(const sloppy_not_null<T>&, std::ptrdiff_t) = delete;
+template <class T>
+sloppy_not_null<T> operator+(const sloppy_not_null<T>&, std::ptrdiff_t) = delete;
+template <class T>
+sloppy_not_null<T> operator+(std::ptrdiff_t, const sloppy_not_null<T>&) = delete;
+
+} // namespace gsl
+
+namespace std
+{
+template <class T>
+struct hash<gsl_helpers::sloppy_not_null<T>>
+{
+ std::size_t operator()(const gsl_helpers::sloppy_not_null<T>& value) const { return hash<T>{}(value); }
+};
+
+} // namespace std
+
+#if defined(_MSC_VER) && _MSC_VER < 1910
+#undef constexpr
+#pragma pop_macro("constexpr")
+
+#endif // defined(_MSC_VER) && _MSC_VER < 1910
+
+#endif // GSL_TRANSITION_H
+
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5306e85..2d37a51 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -6,20 +6,29 @@ project(GSLTests CXX)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
list(APPEND CATCH_CMAKE_ARGS
- "-DCMAKE_INSTALL_PREFIX=${CMAKE_SOURCE_DIR}"
+ "-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/external"
"-DNO_SELFTEST=true"
)
-# add catch
-ExternalProject_Add(
- catch
- PREFIX ${CMAKE_BINARY_DIR}/catch
- GIT_REPOSITORY https://github.com/philsquared/Catch.git
- GIT_TAG v1.9.6
- CMAKE_ARGS ${CATCH_CMAKE_ARGS}
- LOG_DOWNLOAD 1
- UPDATE_DISCONNECTED 1
-)
+if(GIT_FOUND)
+ # add catch
+ ExternalProject_Add(
+ catch
+ PREFIX ${CMAKE_BINARY_DIR}/catch
+ GIT_REPOSITORY https://github.com/catchorg/Catch2.git
+ GIT_TAG v2.0.1
+ CMAKE_ARGS ${CATCH_CMAKE_ARGS}
+ LOG_DOWNLOAD 1
+ UPDATE_DISCONNECTED 1
+ )
+else()
+ # assume catch is installed in a system directory
+ add_custom_target(catch)
+endif()
+
+if (MSVC AND (GSL_CXX_STANDARD EQUAL 17))
+ set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-)
+endif()
# this interface adds compile options to how the tests are run
# please try to keep entries ordered =)
@@ -30,6 +39,7 @@ target_compile_options(gsl_tests_config INTERFACE
/W4
/WX
>
+ ${GSL_CPLUSPLUS_OPT}
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
-fno-strict-aliasing
-Wall
@@ -39,6 +49,7 @@ target_compile_options(gsl_tests_config INTERFACE
-Werror
-Wextra
-Wno-missing-braces
+ -Wno-unknown-attributes
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
@@ -48,6 +59,11 @@ target_compile_options(gsl_tests_config INTERFACE
>
)
+# for tests to find the catch header
+target_include_directories(gsl_tests_config INTERFACE
+ ${CMAKE_BINARY_DIR}/external/include
+)
+
# set definitions for tests
target_compile_definitions(gsl_tests_config INTERFACE
GSL_THROW_ON_CONTRACT_VIOLATION
@@ -91,3 +107,67 @@ add_gsl_test(utils_tests)
add_gsl_test(owner_tests)
add_gsl_test(byte_tests)
add_gsl_test(algorithm_tests)
+add_gsl_test(sloppy_notnull_tests)
+
+
+# No exception tests
+
+foreach(flag_var
+ CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ STRING (REGEX REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}")
+endforeach(flag_var)
+
+# this interface adds compile options to how the tests are run
+# please try to keep entries ordered =)
+add_library(gsl_tests_config_noexcept INTERFACE)
+target_compile_options(gsl_tests_config_noexcept INTERFACE
+ $<$<CXX_COMPILER_ID:MSVC>:
+ /D_HAS_EXCEPTIONS=0
+ /wd4702
+ /wd4577
+ /W4
+ /WX
+ >
+ ${GSL_CPLUSPLUS_OPT}
+ $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
+ -fno-strict-aliasing
+ -fno-exceptions
+ -Wall
+ -Wcast-align
+ -Wconversion
+ -Wctor-dtor-privacy
+ -Werror
+ -Wextra
+ -Wno-missing-braces
+ -Wno-unknown-attributes
+ -Wnon-virtual-dtor
+ -Wold-style-cast
+ -Woverloaded-virtual
+ -Wpedantic
+ -Wshadow
+ -Wsign-conversion
+ >
+)
+
+# set definitions for tests
+target_compile_definitions(gsl_tests_config_noexcept INTERFACE
+ GSL_TERMINATE_ON_CONTRACT_VIOLATION
+)
+
+function(add_gsl_test_noexcept name)
+ add_executable(${name} ${name}.cpp)
+ target_link_libraries(${name}
+ GSL
+ gsl_tests_config_noexcept
+ )
+ add_test(
+ ${name}
+ ${name}
+ )
+ # group all tests under GSL_tests_noexcept
+ set_property(TARGET ${name} PROPERTY FOLDER "GSL_tests_noexcept")
+endfunction()
+
+add_gsl_test_noexcept(no_exception_throw_tests)
+add_gsl_test_noexcept(no_exception_ensure_tests)
diff --git a/tests/algorithm_tests.cpp b/tests/algorithm_tests.cpp
index 045fd3e..368b53d 100644
--- a/tests/algorithm_tests.cpp
+++ b/tests/algorithm_tests.cpp
@@ -14,15 +14,29 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHE...
+
+#include <gsl/gsl_algorithm> // for copy
+#include <gsl/span> // for span
-#include <gsl/gsl_algorithm>
+#include <array> // for array
+#include <cstddef> // for size_t
-#include <array>
+namespace gsl {
+struct fail_fast;
+} // namespace gsl
using namespace std;
using namespace gsl;
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("same_type")
{
// dynamic source and destination span
@@ -30,8 +44,8 @@ TEST_CASE("same_type")
std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- span<int> src_span(src);
- span<int> dst_span(dst);
+ const span<int> src_span(src);
+ const span<int> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -47,8 +61,8 @@ TEST_CASE("same_type")
std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- span<int, 5> src_span(src);
- span<int> dst_span(dst);
+ const span<int, 5> src_span(src);
+ const span<int> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -64,8 +78,8 @@ TEST_CASE("same_type")
std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- span<int> src_span(src);
- span<int, 10> dst_span(dst);
+ const span<int> src_span(src);
+ const span<int, 10> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -81,8 +95,8 @@ TEST_CASE("same_type")
std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- span<int, 5> src_span(src);
- span<int, 10> dst_span(dst);
+ const span<int, 5> src_span(src);
+ const span<int, 10> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -94,6 +108,9 @@ TEST_CASE("same_type")
}
}
+
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("compatible_type")
{
// dynamic source and destination span
@@ -101,8 +118,8 @@ TEST_CASE("compatible_type")
std::array<short, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- span<short> src_span(src);
- span<int> dst_span(dst);
+ const span<short> src_span(src);
+ const span<int> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -118,8 +135,8 @@ TEST_CASE("compatible_type")
std::array<short, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- span<short, 5> src_span(src);
- span<int> dst_span(dst);
+ const span<short, 5> src_span(src);
+ const span<int> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -135,8 +152,8 @@ TEST_CASE("compatible_type")
std::array<short, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- span<short> src_span(src);
- span<int, 10> dst_span(dst);
+ const span<short> src_span(src);
+ const span<int, 10> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -152,8 +169,8 @@ TEST_CASE("compatible_type")
std::array<short, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- span<short, 5> src_span(src);
- span<int, 10> dst_span(dst);
+ const span<short, 5> src_span(src);
+ const span<int, 10> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -189,10 +206,10 @@ TEST_CASE("small_destination_span")
std::array<int, 12> src{1, 2, 3, 4};
std::array<int, 4> dst{};
- span<int> src_span_dyn(src);
- span<int, 12> src_span_static(src);
- span<int> dst_span_dyn(dst);
- span<int, 4> dst_span_static(dst);
+ const span<int> src_span_dyn(src);
+ const span<int, 12> src_span_static(src);
+ const span<int> dst_span_dyn(dst);
+ const span<int, 4> dst_span_static(dst);
CHECK_THROWS_AS(copy(src_span_dyn, dst_span_dyn), fail_fast);
CHECK_THROWS_AS(copy(src_span_dyn, dst_span_static), fail_fast);
diff --git a/tests/assertion_tests.cpp b/tests/assertion_tests.cpp
index 42966d1..0c509ad 100644
--- a/tests/assertion_tests.cpp
+++ b/tests/assertion_tests.cpp
@@ -14,9 +14,15 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
+#endif
-#include <gsl/gsl>
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
+
+#include <gsl/gsl_assert> // for fail_fast (ptr only), Ensures, Expects
using namespace gsl;
diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp
index 78e8e3d..7f07be0 100644
--- a/tests/at_tests.cpp
+++ b/tests/at_tests.cpp
@@ -14,15 +14,30 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK_THROW...
+
+#include <gsl/gsl_util> // for at
-#include <gsl/gsl>
+#include <array> // for array
+#include <cstddef> // for size_t
+#include <initializer_list> // for initializer_list
+#include <vector> // for vector
-#include <initializer_list>
-#include <vector>
+
+namespace gsl {
+struct fail_fast;
+} // namespace gsl
using gsl::fail_fast;
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("static_array")
{
int a[4] = {1, 2, 3, 4};
@@ -39,6 +54,8 @@ TEST_CASE("static_array")
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
}
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("std_array")
{
std::array<int, 4> a = {1, 2, 3, 4};
@@ -55,6 +72,8 @@ TEST_CASE("std_array")
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
}
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("StdVector")
{
std::vector<int> a = {1, 2, 3, 4};
@@ -71,9 +90,11 @@ TEST_CASE("StdVector")
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
}
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("InitializerList")
{
- std::initializer_list<int> a = {1, 2, 3, 4};
+ const std::initializer_list<int> a = {1, 2, 3, 4};
for (int i = 0; i < 4; ++i) {
CHECK(gsl::at(a, i) == i + 1);
@@ -87,6 +108,9 @@ TEST_CASE("InitializerList")
}
#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
static constexpr bool test_constexpr()
{
int a1[4] = {1, 2, 3, 4};
@@ -108,3 +132,4 @@ static constexpr bool test_constexpr()
static_assert(test_constexpr(), "FAIL");
#endif
+
diff --git a/tests/bounds_tests.cpp b/tests/bounds_tests.cpp
index 51b5393..e586d44 100644
--- a/tests/bounds_tests.cpp
+++ b/tests/bounds_tests.cpp
@@ -14,11 +14,21 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, TEST_CASE
+
+#include <gsl/multi_span> // for static_bounds, static_bounds_dynamic_range_t
-#include <gsl/multi_span>
+#include <cstddef> // for ptrdiff_t, size_t
-#include <vector>
+namespace gsl {
+struct fail_fast;
+} // namespace gsl
using namespace std;
using namespace gsl;
@@ -28,6 +38,7 @@ namespace
void use(std::ptrdiff_t&) {}
}
+GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
TEST_CASE("basic_bounds")
{
for (auto point : static_bounds<dynamic_range, 3, 4>{2}) {
@@ -40,6 +51,8 @@ TEST_CASE("basic_bounds")
}
}
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("bounds_basic")
{
static_bounds<3, 4, 5> b;
@@ -49,6 +62,8 @@ TEST_CASE("bounds_basic")
x.slice().slice();
}
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("arrayview_iterator")
{
static_bounds<4, dynamic_range, 2> bounds{3};
@@ -67,6 +82,7 @@ TEST_CASE("arrayview_iterator")
#endif
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("bounds_convertible")
{
static_bounds<7, 4, 2> b1;
@@ -93,3 +109,7 @@ TEST_CASE("bounds_convertible")
CHECK(b5 == b6);
CHECK(b5.size() == b6.size());
}
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+copy(src_span_static, dst_span_static);
+#endif
diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp
index 2c6259d..d6634bb 100644
--- a/tests/byte_tests.cpp
+++ b/tests/byte_tests.cpp
@@ -14,23 +14,21 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
+#endif
-#include <gsl/gsl_byte>
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
-#include <iostream>
-#include <list>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
+#include <gsl/gsl_byte> // for to_byte, to_integer, byte, operator&, ope...
using namespace std;
using namespace gsl;
namespace
{
-
TEST_CASE("construction")
{
{
@@ -38,6 +36,7 @@ TEST_CASE("construction")
CHECK(static_cast<unsigned char>(b) == 4);
}
+ GSL_SUPPRESS(es.49)
{
const byte b = byte(12);
CHECK(static_cast<unsigned char>(b) == 12);
@@ -53,11 +52,12 @@ TEST_CASE("construction")
CHECK(static_cast<unsigned char>(b) == 12);
}
- // waiting for C++17 enum class direct initializer support
- //{
- // byte b { 14 };
- // CHECK(static_cast<unsigned char>(b) == 14);
- //}
+#if defined(__cplusplus) && (__cplusplus >= 201703L)
+ {
+ const byte b { 14 };
+ CHECK(static_cast<unsigned char>(b) == 14);
+ }
+#endif
}
TEST_CASE("bitwise_operations")
@@ -121,6 +121,7 @@ int modify_both(gsl::byte & b, int& i)
return i;
}
+GSL_SUPPRESS(type.1)
TEST_CASE("aliasing")
{
int i{0};
@@ -129,3 +130,7 @@ TEST_CASE("aliasing")
}
}
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+copy(src_span_static, dst_span_static);
+#endif
diff --git a/tests/multi_span_tests.cpp b/tests/multi_span_tests.cpp
index af58d76..9c05cb4 100644
--- a/tests/multi_span_tests.cpp
+++ b/tests/multi_span_tests.cpp
@@ -14,16 +14,32 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
-#include <gsl/multi_span>
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
+
+#include <gsl/gsl_byte> // for byte
+#include <gsl/gsl_util> // for narrow_cast
+#include <gsl/multi_span> // for multi_span, contiguous_span_iterator, dim
-#include <iostream>
-#include <list>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
+#include <algorithm> // for fill, for_each
+#include <array> // for array
+#include <iostream> // for ptrdiff_t, size_t
+#include <iterator> // for reverse_iterator, begin, end, operator!=
+#include <numeric> // for iota
+#include <stddef.h> // for ptrdiff_t
+#include <string> // for string
+#include <vector> // for vector
+
+namespace gsl
+{
+struct fail_fast;
+} // namespace gsl
using namespace std;
using namespace gsl;
@@ -36,8 +52,9 @@ struct BaseClass
struct DerivedClass : BaseClass
{
};
-}
+} // namespace
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("default_constructor")
{
{
@@ -72,6 +89,7 @@ TEST_CASE("default_constructor")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_nullptr_constructor")
{
{
@@ -114,8 +132,8 @@ TEST_CASE("from_nullptr_constructor")
}
}
-TEST_CASE("from_nullptr_length_constructor")
-{
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+TEST_CASE("from_nullptr_length_constructor") {
{
multi_span<int> s{nullptr, 0};
CHECK((s.length() == 0 && s.data() == nullptr));
@@ -133,25 +151,18 @@ TEST_CASE("from_nullptr_length_constructor")
}
{
-#ifdef CONFIRM_COMPILATION_ERRORS
- multi_span<int, 1> s{nullptr, 0};
- CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
-#endif
- }
-
- {
- auto workaround_macro = []() { multi_span<int> s{nullptr, 1}; };
+ auto workaround_macro = []() { const multi_span<int> s{nullptr, 1}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
- auto const_workaround_macro = []() { multi_span<const int> cs{nullptr, 1}; };
+ auto const_workaround_macro = []() { const multi_span<const int> cs{nullptr, 1}; };
CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
}
{
- auto workaround_macro = []() { multi_span<int, 0> s{nullptr, 1}; };
+ auto workaround_macro = []() { const multi_span<int, 0> s{nullptr, 1}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
- auto const_workaround_macro = []() { multi_span<const int, 0> s{nullptr, 1}; };
+ auto const_workaround_macro = []() { const multi_span<const int, 0> s{nullptr, 1}; };
CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
}
@@ -162,8 +173,16 @@ TEST_CASE("from_nullptr_length_constructor")
multi_span<const int*> cs{nullptr, 0};
CHECK((cs.length() == 0 && cs.data() == nullptr));
}
+
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ multi_span<int, 1> s{nullptr, 0};
+ CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
+#endif
+ }
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_element_constructor")
{
int i = 5;
@@ -214,6 +233,7 @@ TEST_CASE("from_element_constructor")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_pointer_length_constructor")
{
int arr[4] = {1, 2, 3, 4};
@@ -238,11 +258,12 @@ TEST_CASE("from_pointer_length_constructor")
{
int* p = nullptr;
- auto workaround_macro = [=]() { multi_span<int> s{p, 2}; };
+ auto workaround_macro = [=]() { const multi_span<int> s{p, 2}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_pointer_pointer_constructor")
{
int arr[4] = {1, 2, 3, 4};
@@ -270,29 +291,31 @@ TEST_CASE("from_pointer_pointer_constructor")
}
{
- auto workaround_macro = [&]() { multi_span<int> s{&arr[1], &arr[0]}; };
+ auto workaround_macro = [&]() { const multi_span<int> s{&arr[1], &arr[0]}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
int* p = nullptr;
- auto workaround_macro = [&]() { multi_span<int> s{&arr[0], p}; };
+ auto workaround_macro = [&]() { const multi_span<int> s{&arr[0], p}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
int* p = nullptr;
- auto workaround_macro = [&]() { multi_span<int> s{p, p}; };
+ auto workaround_macro = [&]() { const multi_span<int> s{p, p}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
int* p = nullptr;
- auto workaround_macro = [&]() { multi_span<int> s{&arr[0], p}; };
+ auto workaround_macro = [&]() { const multi_span<int> s{&arr[0], p}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("from_array_constructor")
{
int arr[5] = {1, 2, 3, 4, 5};
@@ -417,6 +440,11 @@ TEST_CASE("from_array_constructor")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("from_dynamic_array_constructor")
{
double(*arr)[3][4] = new double[100][3][4];
@@ -445,6 +473,7 @@ TEST_CASE("from_dynamic_array_constructor")
delete[] arr;
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: Attribute
TEST_CASE("from_std_array_constructor")
{
std::array<int, 4> arr = {1, 2, 3, 4};
@@ -504,6 +533,7 @@ TEST_CASE("from_std_array_constructor")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_const_std_array_constructor")
{
const std::array<int, 4> arr = {1, 2, 3, 4};
@@ -551,6 +581,7 @@ TEST_CASE("from_const_std_array_constructor")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_container_constructor")
{
std::vector<int> v = {1, 2, 3};
@@ -581,8 +612,7 @@ TEST_CASE("from_container_constructor")
multi_span<char> s{cstr};
#endif
multi_span<const char> cs{cstr};
- CHECK((cs.size() == narrow_cast<std::ptrdiff_t>(cstr.size()) &&
- cs.data() == cstr.data()));
+ CHECK((cs.size() == narrow_cast<std::ptrdiff_t>(cstr.size()) && cs.data() == cstr.data()));
}
{
@@ -625,6 +655,8 @@ TEST_CASE("from_container_constructor")
}
}
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_convertible_span_constructor")
{
#ifdef CONFIRM_COMPILATION_ERRORS
@@ -652,6 +684,7 @@ TEST_CASE("from_convertible_span_constructor")
(void) avcd;
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("copy_move_and_assignment")
{
multi_span<int> s1;
@@ -680,6 +713,8 @@ void fn(const Bounds&)
{
static_assert(Bounds::static_size == 60, "static bounds is wrong size");
}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_multi_span_reshape")
{
int a[3][4][5];
@@ -698,11 +733,10 @@ TEST_CASE("as_multi_span_reshape")
auto av8 = as_multi_span<int>(av7);
CHECK(av8.size() == av6.size());
- for (auto i = 0; i < av8.size(); i++) {
- CHECK(av8[i] == 1);
- }
+ for (auto i = 0; i < av8.size(); i++) { CHECK(av8[i] == 1); }
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("first")
{
int arr[5] = {1, 2, 3, 4, 5};
@@ -746,6 +780,7 @@ TEST_CASE("first")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("last")
{
int arr[5] = {1, 2, 3, 4, 5};
@@ -788,6 +823,7 @@ TEST_CASE("last")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("subspan")
{
int arr[5] = {1, 2, 3, 4, 5};
@@ -861,6 +897,7 @@ TEST_CASE("subspan")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("rank")
{
int arr[2] = {1, 2};
@@ -882,6 +919,7 @@ TEST_CASE("rank")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("extent")
{
{
@@ -954,6 +992,7 @@ TEST_CASE("operator_function_call")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("comparison_operators")
{
{
@@ -1066,17 +1105,20 @@ TEST_CASE("comparison_operators")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("basics")
{
auto ptr = as_multi_span(new int[10], 10);
fill(ptr.begin(), ptr.end(), 99);
- for (int num : ptr) {
- CHECK(num == 99);
- }
+ for (int num : ptr) { CHECK(num == 99); }
delete[] ptr.data();
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
TEST_CASE("bounds_checks")
{
int arr[10][2];
@@ -1103,25 +1145,24 @@ TEST_CASE("bounds_checks")
void overloaded_func(multi_span<const int, dynamic_range, 3, 5> exp, int expected_value)
{
- for (auto val : exp) {
- CHECK(val == expected_value);
- }
+ for (auto val : exp) { CHECK(val == expected_value); }
}
void overloaded_func(multi_span<const char, dynamic_range, 3, 5> exp, char expected_value)
{
- for (auto val : exp) {
- CHECK(val == expected_value);
- }
+ for (auto val : exp) { CHECK(val == expected_value); }
}
void fixed_func(multi_span<int, 3, 3, 5> exp, int expected_value)
{
- for (auto val : exp) {
- CHECK(val == expected_value);
- }
+ for (auto val : exp) { CHECK(val == expected_value); }
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
TEST_CASE("span_parameter_test")
{
auto data = new int[4][3][5];
@@ -1143,12 +1184,16 @@ TEST_CASE("span_parameter_test")
delete[] data;
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // false positive, checker does not recognize multi_span yet
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
TEST_CASE("md_access")
{
auto width = 5, height = 20;
auto imgSize = width * height;
- auto image_ptr = new int[static_cast<std::size_t>(imgSize)][3];
+ auto image_ptr = new int[narrow_cast<std::size_t>(imgSize)][3];
// size check will be done
auto image_view =
@@ -1157,8 +1202,10 @@ TEST_CASE("md_access")
iota(image_view.begin(), image_view.end(), 1);
int expected = 0;
- for (auto i = 0; i < height; i++) {
- for (auto j = 0; j < width; j++) {
+ for (auto i = 0; i < height; i++)
+ {
+ for (auto j = 0; j < width; j++)
+ {
CHECK(expected + 1 == image_view[i][j][0]);
CHECK(expected + 2 == image_view[i][j][1]);
CHECK(expected + 3 == image_view[i][j][2]);
@@ -1175,6 +1222,11 @@ TEST_CASE("md_access")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
+GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
TEST_CASE("as_multi_span")
{
{
@@ -1193,6 +1245,7 @@ TEST_CASE("as_multi_span")
string str = "ttttttttttttttt"; // size = 15
auto t = str.data();
+ GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
(void) t;
auto av3 = as_multi_span(str);
overloaded_func(as_multi_span(av3, dim(1), dim<3>(), dim<5>()), 't');
@@ -1224,22 +1277,24 @@ TEST_CASE("as_multi_span")
auto dv = as_multi_span(vec);
(void) dv;
-#ifdef CONFIRM_COMPILATION_ERRORS
+ #ifdef CONFIRM_COMPILATION_ERRORS
auto dv2 = as_multi_span(std::move(vec));
-#endif
+ #endif
}
}
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
TEST_CASE("empty_spans")
{
{
multi_span<int, 0> empty_av(nullptr);
- CHECK(empty_av.bounds().index_bounds() == index<1>{0});
+ CHECK(empty_av.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_av[0], fail_fast);
CHECK_THROWS_AS(empty_av.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast);
- for (auto& v : empty_av) {
+ for (auto& v : empty_av)
+ {
(void) v;
CHECK(false);
}
@@ -1247,21 +1302,29 @@ TEST_CASE("empty_spans")
{
multi_span<int> empty_av = {};
- CHECK(empty_av.bounds().index_bounds() == index<1>{0});
+ CHECK(empty_av.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_av[0], fail_fast);
CHECK_THROWS_AS(empty_av.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast);
- for (auto& v : empty_av) {
+ for (auto& v : empty_av)
+ {
(void) v;
CHECK(false);
}
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("index_constructor")
{
auto arr = new int[8];
- for (int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; ++i)
+ {
arr[2 * i] = 4 + i;
arr[2 * i + 1] = i;
}
@@ -1269,13 +1332,13 @@ TEST_CASE("index_constructor")
multi_span<int, dynamic_range> av(arr, 8);
ptrdiff_t a[1] = {0};
- index<1> i = a;
+ multi_span_index<1> i = a;
CHECK(av[i] == 4);
auto av2 = as_multi_span(av, dim<4>(), dim(2));
ptrdiff_t a2[2] = {0, 1};
- index<2> i2 = a2;
+ multi_span_index<2> i2 = a2;
CHECK(av2[i2] == 0);
CHECK(av2[0][i] == 4);
@@ -1283,91 +1346,93 @@ TEST_CASE("index_constructor")
delete[] arr;
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("index_constructors")
{
{
// components of the same type
- index<3> i1(0, 1, 2);
+ multi_span_index<3> i1(0, 1, 2);
CHECK(i1[0] == 0);
// components of different types
std::size_t c0 = 0;
std::size_t c1 = 1;
- index<3> i2(c0, c1, 2);
+ multi_span_index<3> i2(c0, c1, 2);
CHECK(i2[0] == 0);
// from array
- index<3> i3 = {0, 1, 2};
+ multi_span_index<3> i3 = {0, 1, 2};
CHECK(i3[0] == 0);
// from other index of the same size type
- index<3> i4 = i3;
+ multi_span_index<3> i4 = i3;
CHECK(i4[0] == 0);
// default
- index<3> i7;
+ multi_span_index<3> i7;
CHECK(i7[0] == 0);
// default
- index<3> i9 = {};
+ multi_span_index<3> i9 = {};
CHECK(i9[0] == 0);
}
{
// components of the same type
- index<1> i1(0);
+ multi_span_index<1> i1(0);
CHECK(i1[0] == 0);
// components of different types
std::size_t c0 = 0;
- index<1> i2(c0);
+ multi_span_index<1> i2(c0);
CHECK(i2[0] == 0);
// from array
- index<1> i3 = {0};
+ multi_span_index<1> i3 = {0};
CHECK(i3[0] == 0);
// from int
- index<1> i4 = 0;
+ multi_span_index<1> i4 = 0;
CHECK(i4[0] == 0);
// from other index of the same size type
- index<1> i5 = i3;
+ multi_span_index<1> i5 = i3;
CHECK(i5[0] == 0);
// default
- index<1> i8;
+ multi_span_index<1> i8;
CHECK(i8[0] == 0);
// default
- index<1> i9 = {};
+ multi_span_index<1> i9 = {};
CHECK(i9[0] == 0);
}
- #ifdef CONFIRM_COMPILATION_ERRORS
+#ifdef CONFIRM_COMPILATION_ERRORS
{
- index<3> i1(0, 1);
- index<3> i2(0, 1, 2, 3);
- index<3> i3 = {0};
- index<3> i4 = {0, 1, 2, 3};
- index<1> i5 = {0, 1};
+ multi_span_index<3> i1(0, 1);
+ multi_span_index<3> i2(0, 1, 2, 3);
+ multi_span_index<3> i3 = {0};
+ multi_span_index<3> i4 = {0, 1, 2, 3};
+ multi_span_index<1> i5 = {0, 1};
}
- #endif
+#endif
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("index_operations")
{
ptrdiff_t a[3] = {0, 1, 2};
ptrdiff_t b[3] = {3, 4, 5};
- index<3> i = a;
- index<3> j = b;
+ multi_span_index<3> i = a;
+ multi_span_index<3> j = b;
CHECK(i[0] == 0);
CHECK(i[1] == 1);
CHECK(i[2] == 2);
{
- index<3> k = i + j;
+ multi_span_index<3> k = i + j;
CHECK(i[0] == 0);
CHECK(i[1] == 1);
@@ -1378,7 +1443,7 @@ TEST_CASE("index_operations")
}
{
- index<3> k = i * 3;
+ multi_span_index<3> k = i * 3;
CHECK(i[0] == 0);
CHECK(i[1] == 1);
@@ -1389,7 +1454,7 @@ TEST_CASE("index_operations")
}
{
- index<3> k = 3 * i;
+ multi_span_index<3> k = 3 * i;
CHECK(i[0] == 0);
CHECK(i[1] == 1);
@@ -1400,7 +1465,7 @@ TEST_CASE("index_operations")
}
{
- index<2> k = details::shift_left(i);
+ multi_span_index<2> k = details::shift_left(i);
CHECK(i[0] == 0);
CHECK(i[1] == 1);
@@ -1410,6 +1475,8 @@ TEST_CASE("index_operations")
}
}
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
{
auto length = av.size() / 2;
@@ -1418,33 +1485,33 @@ void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
auto section = av.section({0, 1}, {length, 1});
CHECK(section.size() == length);
- for (auto i = 0; i < section.size(); ++i) {
- CHECK(section[i][0] == av[i][1]);
- }
+ for (auto i = 0; i < section.size(); ++i) { CHECK(section[i][0] == av[i][1]); }
- for (auto i = 0; i < section.size(); ++i) {
- auto idx = index<2>{i, 0}; // avoid braces inside the CHECK macro
+ for (auto i = 0; i < section.size(); ++i)
+ {
+ auto idx = multi_span_index<2>{i, 0}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]);
}
CHECK(section.bounds().index_bounds()[0] == length);
CHECK(section.bounds().index_bounds()[1] == 1);
- for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) {
- for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) {
- auto idx = index<2>{i, j}; // avoid braces inside the CHECK macro
+ for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i)
+ {
+ for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j)
+ {
+ auto idx = multi_span_index<2>{i, j}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]);
}
}
auto check_sum = 0;
- for (auto i = 0; i < length; ++i) {
- check_sum += av[i][1];
- }
+ for (auto i = 0; i < length; ++i) { check_sum += av[i][1]; }
{
auto idx = 0;
auto sum = 0;
- for (auto num : section) {
+ for (auto num : section)
+ {
CHECK(num == av[idx][1]);
sum += num;
idx++;
@@ -1455,7 +1522,8 @@ void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
{
auto idx = length - 1;
auto sum = 0;
- for (auto iter = section.rbegin(); iter != section.rend(); ++iter) {
+ for (auto iter = section.rbegin(); iter != section.rend(); ++iter)
+ {
CHECK(*iter == av[idx][1]);
sum += *iter;
idx--;
@@ -1465,6 +1533,7 @@ void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("span_section_iteration")
{
int arr[4][2] = {{4, 0}, {5, 1}, {6, 2}, {7, 3}};
@@ -1491,15 +1560,18 @@ TEST_CASE("span_section_iteration")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("dynamic_span_section_iteration")
{
auto height = 4, width = 2;
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 arr = new int[narrow_cast<std::size_t>(size)];
+ for (auto i = 0; i < size; ++i) { arr[i] = i; }
auto av = as_multi_span(arr, size);
@@ -1523,6 +1595,10 @@ TEST_CASE("dynamic_span_section_iteration")
delete[] arr;
}
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
TEST_CASE("span_structure_size")
{
double(*arr)[3][4] = new double[100][3][4];
@@ -1542,6 +1618,7 @@ TEST_CASE("span_structure_size")
(void) av2;
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("fixed_size_conversions")
{
int arr[] = {1, 2, 3, 4};
@@ -1623,7 +1700,7 @@ TEST_CASE("fixed_size_conversions")
#endif
{
auto f = [&]() {
- multi_span<int, 4> av9 = {arr2, 2};
+ const multi_span<int, 4> av9 = {arr2, 2};
(void) av9;
};
CHECK_THROWS_AS(f(), fail_fast);
@@ -1632,12 +1709,13 @@ TEST_CASE("fixed_size_conversions")
// this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one
multi_span<int, dynamic_range> av = arr2;
auto f = [&]() {
- multi_span<int, 4> av2 = av;
+ const multi_span<int, 4> av2 = av;
(void) av2;
};
CHECK_THROWS_AS(f(), fail_fast);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_writeable_bytes")
{
int a[] = {1, 2, 3, 4};
@@ -1666,6 +1744,10 @@ TEST_CASE("as_writeable_bytes")
}
}
+
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("iterator")
{
int a[] = {1, 2, 3, 4};
@@ -1674,8 +1756,14 @@ TEST_CASE("iterator")
multi_span<int, dynamic_range> av = a;
auto wav = as_writeable_bytes(av);
for (auto& b : wav) {
+#if defined(__cplusplus) && (__cplusplus >= 201703L)
+ b = byte{0};
+#else
+ GSL_SUPPRESS(es.49)
b = byte(0);
+#endif
}
+
for (std::size_t i = 0; i < 4; ++i) {
CHECK(a[i] == 0);
}
@@ -1691,3 +1779,7 @@ TEST_CASE("iterator")
}
}
}
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+copy(src_span_static, dst_span_static);
+#endif \ No newline at end of file
diff --git a/tests/no_exception_ensure_tests.cpp b/tests/no_exception_ensure_tests.cpp
new file mode 100644
index 0000000..3a7f007
--- /dev/null
+++ b/tests/no_exception_ensure_tests.cpp
@@ -0,0 +1,53 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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 <cstdlib> // for std::exit
+#include <gsl/span> // for span
+
+int operator_subscript_no_throw() noexcept
+{
+ int arr[10];
+ const gsl::span<int> sp { arr };
+ return sp[11];
+}
+
+
+void test_terminate()
+{
+ std::exit(0);
+}
+
+void setup_termination_handler() noexcept
+{
+#if defined(_MSC_VER)
+
+ auto& handler = gsl::details::get_terminate_handler();
+ handler = &test_terminate;
+
+#else
+
+ std::set_terminate(test_terminate);
+
+#endif
+}
+
+
+int main() noexcept
+{
+ setup_termination_handler();
+ operator_subscript_no_throw();
+ return -1;
+}
diff --git a/tests/no_exception_throw_tests.cpp b/tests/no_exception_throw_tests.cpp
new file mode 100644
index 0000000..e9f4dac
--- /dev/null
+++ b/tests/no_exception_throw_tests.cpp
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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 <cstdlib> // for std::exit
+#include <gsl/gsl_util> // for narrow
+#include <gsl/gsl_assert> // for get_terminate
+
+int narrow_no_throw()
+{
+ const long long bigNumber = 0x0fffffffffffffff;
+ return gsl::narrow<int>(bigNumber);
+}
+
+void test_terminate()
+{
+ std::exit(0);
+}
+
+void setup_termination_handler() noexcept
+{
+#if defined(_MSC_VER)
+
+ auto& handler = gsl::details::get_terminate_handler();
+ handler = &test_terminate;
+
+#else
+
+ std::set_terminate(test_terminate);
+
+#endif
+}
+
+
+int main()
+{
+ setup_termination_handler();
+ narrow_no_throw();
+ return -1;
+}
diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp
index 62f1e57..668c0a2 100644
--- a/tests/notnull_tests.cpp
+++ b/tests/notnull_tests.cpp
@@ -14,13 +14,30 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
-#include <gsl/gsl>
+// Fix VS2015 build breaks in Release
+#pragma warning(disable : 4702) // unreachable code
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
+
+#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
-#include <memory>
-#include <string>
-#include <vector>
+#include <algorithm> // for addressof
+#include <memory> // for shared_ptr, make_shared, operator<, opera...
+#include <sstream> // for operator<<, ostringstream, basic_ostream:...
+#include <stdint.h> // for uint16_t
+#include <string> // for basic_string, operator==, string, operator<<
+#include <typeinfo> // for type_info
+
+namespace gsl
+{
+struct fail_fast;
+} // namespace gsl
using namespace gsl;
@@ -56,6 +73,7 @@ struct CustomPtr
template <typename T, typename U>
std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -63,6 +81,7 @@ std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -70,6 +89,7 @@ std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -77,6 +97,7 @@ std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -84,6 +105,7 @@ std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -91,6 +113,7 @@ std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator>=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
+ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -104,8 +127,19 @@ struct NonCopyableNonMovable
NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete;
};
-bool helper(not_null<int*> p) { return *p == 12; }
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+bool helper(not_null<int*> p)
+{
+ return *p == 12;
+}
+
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+bool helper_const(not_null<const int*> p)
+{
+ return *p == 12;
+}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullConstructors")
{
#ifdef CONFIRM_COMPILATION_ERRORS
@@ -127,17 +161,56 @@ TEST_CASE("TestNotNullConstructors")
not_null<std::shared_ptr<int>> x(
std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
+
+#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
+ int* pi = nullptr;
+ CHECK_THROWS_AS(not_null<decltype(pi)>(pi), fail_fast);
+#endif
+}
+
+template<typename T>
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+void ostream_helper(T v)
+{
+ not_null<T*> p(&v);
+ {
+ std::ostringstream os;
+ std::ostringstream ref;
+ os << p;
+ ref << &v;
+ CHECK(os.str() == ref.str());
+ }
+ {
+ std::ostringstream os;
+ std::ostringstream ref;
+ os << *p;
+ ref << v;
+ CHECK(os.str() == ref.str());
+ }
+}
+
+TEST_CASE("TestNotNullostream")
+{
+ ostream_helper<int>(17);
+ ostream_helper<float>(21.5f);
+ ostream_helper<double>(3.4566e-7f);
+ ostream_helper<char>('c');
+ ostream_helper<uint16_t>(0x0123u);
+ ostream_helper<const char*>("cstring");
+ ostream_helper<std::string>("string");
}
+GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullCasting")
{
MyBase base;
MyDerived derived;
Unrelated unrelated;
- not_null<Unrelated*> u = &unrelated;
+ not_null<Unrelated*> u{&unrelated};
(void) u;
- not_null<MyDerived*> p = &derived;
- not_null<MyBase*> q = &base;
+ not_null<MyDerived*> p{&derived};
+ not_null<MyBase*> q(&base);
q = p; // allowed with heterogeneous copy ctor
CHECK(q == p);
@@ -148,18 +221,18 @@ TEST_CASE("TestNotNullCasting")
not_null<Unrelated*> r = p;
not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
#endif
- not_null<Unrelated*> t = reinterpret_cast<Unrelated*>(p.get());
+ not_null<Unrelated*> t(reinterpret_cast<Unrelated*>(p.get()));
CHECK(reinterpret_cast<void*>(p.get()) == reinterpret_cast<void*>(t.get()));
}
TEST_CASE("TestNotNullAssignment")
{
int i = 12;
- not_null<int*> p = &i;
+ not_null<int*> p(&i);
CHECK(helper(p));
int* q = nullptr;
- CHECK_THROWS_AS(p = q, fail_fast);
+ CHECK_THROWS_AS(p = not_null<int*>(q), fail_fast);
}
TEST_CASE("TestNotNullRawPointerComparison")
@@ -188,21 +261,21 @@ TEST_CASE("TestNotNullRawPointerComparison")
CHECK((NotNull1(p1) <= NotNull1(p1)) == true);
CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
-
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullDereferenceOperator")
{
{
auto sp1 = std::make_shared<NonCopyableNonMovable>();
using NotNullSp1 = not_null<decltype(sp1)>;
- CHECK(typeid(*sp1) == typeid(*NotNullSp1(sp1)));
+ CHECK(typeid(*sp1) == typeid(*NotNullSp1(sp1)));
CHECK(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1));
}
{
- int ints[1] = { 42 };
+ int ints[1] = {42};
CustomPtr<int> p1(&ints[0]);
using NotNull1 = not_null<decltype(p1)>;
@@ -252,6 +325,7 @@ TEST_CASE("TestNotNullSharedPtrComparison")
CHECK((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1));
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullCustomPtrComparison")
{
int ints[2] = {42, 43};
@@ -283,3 +357,122 @@ TEST_CASE("TestNotNullCustomPtrComparison")
CHECK((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2));
CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1));
}
+
+#if defined(__cplusplus) && (__cplusplus >= 201703L)
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+TEST_CASE("TestNotNullConstructorTypeDeduction")
+{
+ {
+ int i = 42;
+
+ not_null x{&i};
+ helper(not_null{&i});
+ helper_const(not_null{&i});
+
+ CHECK(*x == 42);
+ }
+
+ {
+ int i = 42;
+ int* p = &i;
+
+ not_null x{p};
+ helper(not_null{p});
+ helper_const(not_null{p});
+
+ CHECK(*x == 42);
+ }
+
+ {
+ auto workaround_macro = []() {
+ int* p1 = nullptr;
+ const not_null x{p1};
+ };
+ CHECK_THROWS_AS(workaround_macro(), fail_fast);
+ }
+
+ {
+ auto workaround_macro = []() {
+ const int* p1 = nullptr;
+ const not_null x{p1};
+ };
+ CHECK_THROWS_AS(workaround_macro(), fail_fast);
+ }
+
+ {
+ int* p = nullptr;
+
+ CHECK_THROWS_AS(helper(not_null{p}), fail_fast);
+ CHECK_THROWS_AS(helper_const(not_null{p}), fail_fast);
+ }
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ not_null x{nullptr};
+ helper(not_null{nullptr});
+ helper_const(not_null{nullptr});
+ }
+#endif
+}
+#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)
+
+TEST_CASE("TestMakeNotNull")
+{
+ {
+ int i = 42;
+
+ const auto x = make_not_null(&i);
+ helper(make_not_null(&i));
+ helper_const(make_not_null(&i));
+
+ CHECK(*x == 42);
+ }
+
+ {
+ int i = 42;
+ int* p = &i;
+
+ const auto x = make_not_null(p);
+ helper(make_not_null(p));
+ helper_const(make_not_null(p));
+
+ CHECK(*x == 42);
+ }
+
+ {
+ const auto workaround_macro = []() {
+ int* p1 = nullptr;
+ const auto x = make_not_null(p1);
+ CHECK(*x == 42);
+ };
+ CHECK_THROWS_AS(workaround_macro(), fail_fast);
+ }
+
+ {
+ const auto workaround_macro = []() {
+ const int* p1 = nullptr;
+ const auto x = make_not_null(p1);
+ CHECK(*x == 42);
+ };
+ CHECK_THROWS_AS(workaround_macro(), fail_fast);
+ }
+
+ {
+ int* p = nullptr;
+
+ CHECK_THROWS_AS(helper(make_not_null(p)), fail_fast);
+ CHECK_THROWS_AS(helper_const(make_not_null(p)), fail_fast);
+ }
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ CHECK_THROWS_AS(make_not_null(nullptr), fail_fast);
+ CHECK_THROWS_AS(helper(make_not_null(nullptr)), fail_fast);
+ CHECK_THROWS_AS(helper_const(make_not_null(nullptr)), fail_fast);
+ }
+#endif
+}
+
+static_assert(std::is_nothrow_move_constructible<not_null<void *>>::value, "not_null must be no-throw move constructible");
+
diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp
index 9885a68..9fff184 100644
--- a/tests/owner_tests.cpp
+++ b/tests/owner_tests.cpp
@@ -14,18 +14,25 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
-#include <gsl/gsl>
+#endif
-#include <functional>
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
-#include <memory>
+#include <gsl/pointers> // for owner
using namespace gsl;
+GSL_SUPPRESS(f.23) // NO-FORMAT: attribute
void f(int* i) { *i += 1; }
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute // TODO: false positive
+GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
TEST_CASE("basic_test")
{
owner<int*> p = new int(120);
diff --git a/tests/sloppy_notnull_tests.cpp b/tests/sloppy_notnull_tests.cpp
new file mode 100644
index 0000000..51983f5
--- /dev/null
+++ b/tests/sloppy_notnull_tests.cpp
@@ -0,0 +1,124 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
+
+// Fix VS2015 build breaks in Release
+#pragma warning(disable : 4702) // unreachable code
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
+
+#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
+#include <samples/gsl_transition> // for sloppy_not_null
+
+namespace gsl
+{
+struct fail_fast;
+} // namespace gsl
+
+using namespace gsl;
+using namespace gsl_helpers;
+
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+bool helper(not_null<int*> p) { return *p == 12; }
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+bool helper_const(not_null<const int*> p) { return *p == 12; }
+
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+bool sloppy_helper(sloppy_not_null<int*> p) { return *p == 12; }
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+bool sloppy_helper_const(sloppy_not_null<const int*> p) { return *p == 12; }
+
+TEST_CASE("TestSloppyNotNull")
+{
+ {
+ // raw ptr <-> sloppy_not_null
+ int x = 42;
+
+ const sloppy_not_null<int*> snn = &x;
+
+ sloppy_helper(&x);
+ sloppy_helper_const(&x);
+
+ CHECK(*snn == 42);
+ }
+
+ {
+ // sloppy_not_null -> sloppy_not_null
+ int x = 42;
+
+ sloppy_not_null<int*> snn1{&x};
+ const sloppy_not_null<int*> snn2{&x};
+
+ sloppy_helper(snn1);
+ sloppy_helper_const(snn1);
+
+ CHECK(snn1 == snn2);
+ }
+
+ {
+ // sloppy_not_null -> not_null
+ int x = 42;
+
+ sloppy_not_null<int*> snn{&x};
+
+ const not_null<int*> nn1 = snn;
+ const not_null<int*> nn2{snn};
+
+ helper(snn);
+ helper_const(snn);
+
+ CHECK(snn == nn1);
+ CHECK(snn == nn2);
+ }
+
+ {
+ // not_null -> sloppy_not_null
+ int x = 42;
+
+ not_null<int*> nn{&x};
+
+ const sloppy_not_null<int*> snn1{nn};
+ const sloppy_not_null<int*> snn2 = nn;
+
+ sloppy_helper(nn);
+ sloppy_helper_const(nn);
+
+ CHECK(snn1 == nn);
+ CHECK(snn2 == nn);
+
+ std::hash<sloppy_not_null<int*>> hash_snn;
+ std::hash<not_null<int*>> hash_nn;
+
+ CHECK(hash_nn(snn1) == hash_nn(nn));
+ CHECK(hash_snn(snn1) == hash_nn(nn));
+ CHECK(hash_nn(snn1) == hash_nn(snn2));
+ CHECK(hash_snn(snn1) == hash_snn(nn));
+ }
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ sloppy_not_null<int*> p{nullptr};
+ }
+#endif
+}
+
+static_assert(std::is_nothrow_move_constructible<sloppy_not_null<void*>>::value,
+ "sloppy_not_null must be no-throw move constructible");
diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp
index 69a7923..07a59c8 100644
--- a/tests/span_tests.cpp
+++ b/tests/span_tests.cpp
@@ -14,17 +14,32 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426 26497) // from catch
-#include <gsl/span>
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
+
+#include <gsl/gsl_byte> // for byte
+#include <gsl/gsl_util> // for narrow_cast, at
+#include <gsl/span> // for span, span_iterator, operator==, operator!=
+
+#include <array> // for array
+#include <iostream> // for ptrdiff_t
+#include <iterator> // for reverse_iterator, operator-, operator==
+#include <memory> // for unique_ptr, shared_ptr, make_unique, allo...
+#include <regex> // for match_results, sub_match, match_results<>...
+#include <stddef.h> // for ptrdiff_t
+#include <string> // for string
+#include <type_traits> // for integral_constant<>::value, is_default_co...
+#include <vector> // for vector
-#include <iostream>
-#include <list>
-#include <map>
-#include <memory>
-#include <regex>
-#include <string>
-#include <vector>
+namespace gsl {
+struct fail_fast;
+} // namespace gsl
using namespace std;
using namespace gsl;
@@ -37,42 +52,48 @@ struct BaseClass
struct DerivedClass : BaseClass
{
};
+struct AddressOverloaded
+{
+ AddressOverloaded operator&() const { return {}; }
+};
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("default_constructor")
{
{
span<int> s;
- CHECK((s.length() == 0 && s.data() == nullptr));
+ CHECK((s.size() == 0 && s.data() == nullptr));
span<const int> cs;
- CHECK((cs.length() == 0 && cs.data() == nullptr));
+ CHECK((cs.size() == 0 && cs.data() == nullptr));
}
{
span<int, 0> s;
- CHECK((s.length() == 0 && s.data() == nullptr));
+ CHECK((s.size() == 0 && s.data() == nullptr));
span<const int, 0> cs;
- CHECK((cs.length() == 0 && cs.data() == nullptr));
+ CHECK((cs.size() == 0 && cs.data() == nullptr));
}
{
#ifdef CONFIRM_COMPILATION_ERRORS
span<int, 1> s;
- CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
+ CHECK((s.size() == 1 && s.data() == nullptr)); // explains why it can't compile
#endif
}
{
span<int> s{};
- CHECK((s.length() == 0 && s.data() == nullptr));
+ CHECK((s.size() == 0 && s.data() == nullptr));
span<const int> cs{};
- CHECK((cs.length() == 0 && cs.data() == nullptr));
+ CHECK((cs.size() == 0 && cs.data() == nullptr));
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("size_optimization")
{
{
@@ -86,136 +107,122 @@ TEST_CASE("size_optimization")
}
}
-TEST_CASE("from_nullptr_constructor")
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+TEST_CASE("from_nullptr_size_constructor")
{
{
- span<int> s = nullptr;
- CHECK((s.length() == 0 && s.data() == nullptr));
-
- span<const int> cs = nullptr;
- CHECK((cs.length() == 0 && cs.data() == nullptr));
- }
-
- {
- span<int, 0> s = nullptr;
- CHECK((s.length() == 0 && s.data() == nullptr));
-
- span<const int, 0> cs = nullptr;
- CHECK((cs.length() == 0 && cs.data() == nullptr));
- }
+ span<int> s{nullptr, narrow_cast<span<int>::index_type>(0)};
+ CHECK((s.size() == 0 && s.data() == nullptr));
- {
-#ifdef CONFIRM_COMPILATION_ERRORS
- span<int, 1> s = nullptr;
- CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
-#endif
+ span<const int> cs{nullptr, narrow_cast<span<int>::index_type>(0)};
+ CHECK((cs.size() == 0 && cs.data() == nullptr));
}
{
- span<int> s{nullptr};
- CHECK((s.length() == 0 && s.data() == nullptr));
+ span<int, 0> s{nullptr, narrow_cast<span<int>::index_type>(0)};
+ CHECK((s.size() == 0 && s.data() == nullptr));
- span<const int> cs{nullptr};
- CHECK((cs.length() == 0 && cs.data() == nullptr));
- }
-
- {
- span<int*> s{nullptr};
- CHECK((s.length() == 0 && s.data() == nullptr));
-
- span<const int*> cs{nullptr};
- CHECK((cs.length() == 0 && cs.data() == nullptr));
- }
-}
-
-TEST_CASE("from_nullptr_length_constructor")
-{
- {
- span<int> s{nullptr, static_cast<span<int>::index_type>(0)};
- CHECK((s.length() == 0 && s.data() == nullptr));
-
- span<const int> cs{nullptr, static_cast<span<int>::index_type>(0)};
- CHECK((cs.length() == 0 && cs.data() == nullptr));
- }
-
- {
- span<int, 0> s{nullptr, static_cast<span<int>::index_type>(0)};
- CHECK((s.length() == 0 && s.data() == nullptr));
-
- span<const int, 0> cs{nullptr, static_cast<span<int>::index_type>(0)};
- CHECK((cs.length() == 0 && cs.data() == nullptr));
+ span<const int, 0> cs{nullptr, narrow_cast<span<int>::index_type>(0)};
+ CHECK((cs.size() == 0 && cs.data() == nullptr));
}
{
auto workaround_macro = []() {
- span<int, 1> s{nullptr, static_cast<span<int>::index_type>(0)};
+ const span<int, 1> s{nullptr, narrow_cast<span<int>::index_type>(0)};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
- auto workaround_macro = []() { span<int> s{nullptr, 1}; };
+ auto workaround_macro = []() { const span<int> s{nullptr, 1}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
- auto const_workaround_macro = []() { span<const int> cs{nullptr, 1}; };
+ auto const_workaround_macro = []() { const span<const int> cs{nullptr, 1}; };
CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
}
{
- auto workaround_macro = []() { span<int, 0> s{nullptr, 1}; };
+ auto workaround_macro = []() { const span<int, 0> s{nullptr, 1}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
- auto const_workaround_macro = []() { span<const int, 0> s{nullptr, 1}; };
+ auto const_workaround_macro = []() { const span<const int, 0> s{nullptr, 1}; };
CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
}
{
- span<int*> s{nullptr, static_cast<span<int>::index_type>(0)};
- CHECK((s.length() == 0 && s.data() == nullptr));
+ span<int*> s{nullptr, narrow_cast<span<int>::index_type>(0)};
+ CHECK((s.size() == 0 && s.data() == nullptr));
- span<const int*> cs{nullptr, static_cast<span<int>::index_type>(0)};
- CHECK((cs.length() == 0 && cs.data() == nullptr));
+ span<const int*> cs{nullptr, narrow_cast<span<int>::index_type>(0)};
+ CHECK((cs.size() == 0 && cs.data() == nullptr));
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("from_pointer_length_constructor")
{
int arr[4] = {1, 2, 3, 4};
{
- span<int> s{&arr[0], 2};
- CHECK((s.length() == 2 && s.data() == &arr[0]));
- CHECK((s[0] == 1 && s[1] == 2));
+ for(int i = 0; i<4 ; ++i)
+ {
+ {
+ span<int> s = { &arr[0], i };
+ CHECK(s.size() == i);
+ CHECK(s.data() == &arr[0]);
+ CHECK(s.empty() == (i == 0));
+ for (int j = 0; j < i; ++j)
+ {
+ CHECK(arr[j] == s[j]);
+ CHECK(arr[j] == s.at(j));
+ CHECK(arr[j] == s(j));
+ }
+ }
+ {
+ span<int> s = { &arr[i], 4-narrow_cast<ptrdiff_t>(i) };
+ CHECK(s.size() == 4-i);
+ CHECK(s.data() == &arr[i]);
+ CHECK(s.empty() == (4-i == 0));
+ for (int j = 0; j < 4-i; ++j)
+ {
+ CHECK(arr[j+i] == s[j]);
+ CHECK(arr[j+i] == s.at(j));
+ CHECK(arr[j+i] == s(j));
+ }
+ }
+ }
}
{
span<int, 2> s{&arr[0], 2};
- CHECK((s.length() == 2 && s.data() == &arr[0]));
+ CHECK((s.size() == 2 && s.data() == &arr[0]));
CHECK((s[0] == 1 && s[1] == 2));
}
{
int* p = nullptr;
- span<int> s{p, static_cast<span<int>::index_type>(0)};
- CHECK((s.length() == 0 && s.data() == nullptr));
+ span<int> s{p, narrow_cast<span<int>::index_type>(0)};
+ CHECK((s.size() == 0 && s.data() == nullptr));
}
{
int* p = nullptr;
- auto workaround_macro = [=]() { span<int> s{p, 2}; };
+ auto workaround_macro = [=]() { const span<int> s{p, 2}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
auto s = make_span(&arr[0], 2);
- CHECK((s.length() == 2 && s.data() == &arr[0]));
+ CHECK((s.size() == 2 && s.data() == &arr[0]));
CHECK((s[0] == 1 && s[1] == 2));
}
{
int* p = nullptr;
- auto s = make_span(p, static_cast<span<int>::index_type>(0));
- CHECK((s.length() == 0 && s.data() == nullptr));
+ auto s = make_span(p, narrow_cast<span<int>::index_type>(0));
+ CHECK((s.size() == 0 && s.data() == nullptr));
}
{
@@ -225,30 +232,32 @@ TEST_CASE("from_pointer_length_constructor")
}
}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_pointer_pointer_constructor")
{
int arr[4] = {1, 2, 3, 4};
{
span<int> s{&arr[0], &arr[2]};
- CHECK((s.length() == 2 && s.data() == &arr[0]));
+ CHECK((s.size() == 2 && s.data() == &arr[0]));
CHECK((s[0] == 1 && s[1] == 2));
}
{
span<int, 2> s{&arr[0], &arr[2]};
- CHECK((s.length() == 2 && s.data() == &arr[0]));
+ CHECK((s.size() == 2 && s.data() == &arr[0]));
CHECK((s[0] == 1 && s[1] == 2));
}
{
span<int> s{&arr[0], &arr[0]};
- CHECK((s.length() == 0 && s.data() == &arr[0]));
+ CHECK((s.size() == 0 && s.data() == &arr[0]));
}
{
span<int, 0> s{&arr[0], &arr[0]};
- CHECK((s.length() == 0 && s.data() == &arr[0]));
+ CHECK((s.size() == 0 && s.data() == &arr[0]));
}
// this will fail the std::distance() precondition, which asserts on MSVC debug builds
@@ -267,13 +276,13 @@ TEST_CASE("from_pointer_pointer_constructor")
{
int* p = nullptr;
span<int> s{p, p};
- CHECK((s.length() == 0 && s.data() == nullptr));
+ CHECK((s.size() == 0 && s.data() == nullptr));
}
{
int* p = nullptr;
span<int, 0> s{p, p};
- CHECK((s.length() == 0 && s.data() == nullptr));
+ CHECK((s.size() == 0 && s.data() == nullptr));
}
// this will fail the std::distance() precondition, which asserts on MSVC debug builds
@@ -285,19 +294,19 @@ TEST_CASE("from_pointer_pointer_constructor")
{
auto s = make_span(&arr[0], &arr[2]);
- CHECK((s.length() == 2 && s.data() == &arr[0]));
+ CHECK((s.size() == 2 && s.data() == &arr[0]));
CHECK((s[0] == 1 && s[1] == 2));
}
{
auto s = make_span(&arr[0], &arr[0]);
- CHECK((s.length() == 0 && s.data() == &arr[0]));
+ CHECK((s.size() == 0 && s.data() == &arr[0]));
}
{
int* p = nullptr;
auto s = make_span(p, p);
- CHECK((s.length() == 0 && s.data() == nullptr));
+ CHECK((s.size() == 0 && s.data() == nullptr));
}
}
@@ -306,13 +315,13 @@ TEST_CASE("from_array_constructor")
int arr[5] = {1, 2, 3, 4, 5};
{
- span<int> s{arr};
- CHECK((s.length() == 5 && s.data() == &arr[0]));
+ const span<int> s{arr};
+ CHECK((s.size() == 5 && s.data() == &arr[0]));
}
{
- span<int, 5> s{arr};
- CHECK((s.length() == 5 && s.data() == &arr[0]));
+ const span<int, 5> s{arr};
+ CHECK((s.size() == 5 && s.data() == &arr[0]));
}
int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
@@ -324,18 +333,18 @@ TEST_CASE("from_array_constructor")
{
span<int, 0> s{arr};
- CHECK((s.length() == 0 && s.data() == &arr[0]));
+ CHECK((s.size() == 0 && s.data() == &arr[0]));
}
{
span<int> s{arr2d};
- CHECK((s.length() == 6 && s.data() == &arr2d[0][0]));
+ CHECK((s.size() == 6 && s.data() == &arr2d[0][0]));
CHECK((s[0] == 1 && s[5] == 6));
}
{
span<int, 0> s{arr2d};
- CHECK((s.length() == 0 && s.data() == &arr2d[0][0]));
+ CHECK((s.size() == 0 && s.data() == &arr2d[0][0]));
}
{
@@ -343,8 +352,8 @@ TEST_CASE("from_array_constructor")
}
#endif
{
- span<int[3]> s{&(arr2d[0]), 1};
- CHECK((s.length() == 1 && s.data() == &arr2d[0]));
+ const span<int[3]> s{std::addressof(arr2d[0]), 1};
+ CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0])));
}
int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
@@ -352,13 +361,13 @@ TEST_CASE("from_array_constructor")
#ifdef CONFIRM_COMPILATION_ERRORS
{
span<int> s{arr3d};
- CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0]));
+ CHECK((s.size() == 12 && s.data() == &arr3d[0][0][0]));
CHECK((s[0] == 1 && s[11] == 12));
}
{
span<int, 0> s{arr3d};
- CHECK((s.length() == 0 && s.data() == &arr3d[0][0][0]));
+ CHECK((s.size() == 0 && s.data() == &arr3d[0][0][0]));
}
{
@@ -367,48 +376,62 @@ TEST_CASE("from_array_constructor")
{
span<int, 12> s{arr3d};
- CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0]));
+ CHECK((s.size() == 12 && s.data() == &arr3d[0][0][0]));
CHECK((s[0] == 1 && s[5] == 6));
}
#endif
{
- span<int[3][2]> s{&arr3d[0], 1};
- CHECK((s.length() == 1 && s.data() == &arr3d[0]));
+ const span<int[3][2]> s{std::addressof(arr3d[0]), 1};
+ CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0])));
}
{
- auto s = make_span(arr);
- CHECK((s.length() == 5 && s.data() == &arr[0]));
+ const auto s = make_span(arr);
+ CHECK((s.size() == 5 && s.data() == std::addressof(arr[0])));
}
{
- auto s = make_span(&(arr2d[0]), 1);
- CHECK((s.length() == 1 && s.data() == &arr2d[0]));
+ const auto s = make_span(std::addressof(arr2d[0]), 1);
+ CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0])));
}
{
- auto s = make_span(&arr3d[0], 1);
- CHECK((s.length() == 1 && s.data() == &arr3d[0]));
+ const auto s = make_span(std::addressof(arr3d[0]), 1);
+ CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0])));
}
+
+ AddressOverloaded ao_arr[5] = {};
+
+ {
+ const span<AddressOverloaded, 5> s{ao_arr};
+ CHECK((s.size() == 5 && s.data() == std::addressof(ao_arr[0])));
+ }
+
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("from_dynamic_array_constructor")
{
double(*arr)[3][4] = new double[100][3][4];
{
span<double> s(&arr[0][0][0], 10);
- CHECK((s.length() == 10 && s.data() == &arr[0][0][0]));
+ CHECK((s.size() == 10 && s.data() == &arr[0][0][0]));
}
{
auto s = make_span(&arr[0][0][0], 10);
- CHECK((s.length() == 10 && s.data() == &arr[0][0][0]));
+ CHECK((s.size() == 10 && s.data() == &arr[0][0][0]));
}
delete[] arr;
}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_std_array_constructor")
{
std::array<int, 4> arr = {1, 2, 3, 4};
@@ -429,6 +452,13 @@ TEST_CASE("from_std_array_constructor")
CHECK((cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data()));
}
+ std::array<AddressOverloaded, 4> ao_arr{};
+
+ {
+ span<AddressOverloaded, 4> fs{ao_arr};
+ CHECK((fs.size() == narrow_cast<ptrdiff_t>(ao_arr.size()) && ao_arr.data() == fs.data()));
+ }
+
#ifdef CONFIRM_COMPILATION_ERRORS
{
span<int, 2> s{arr};
@@ -469,8 +499,26 @@ TEST_CASE("from_std_array_constructor")
auto s = make_span(arr);
CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()));
}
+
+ // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 7.1, 7.2, 7.3 - issue #590
+ {
+ span<int> s1 = make_span(arr);
+
+ static span<int> s2;
+ s2 = s1;
+
+ #if __GNUC__ == 6 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__)
+ // Known to be broken in gcc 6.4 with optimizations
+ // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116
+ CHECK(s1.size() == 4);
+ CHECK(s2.size() == 0);
+ #else
+ CHECK(s1.size() == s2.size());
+ #endif
+ }
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_const_std_array_constructor")
{
const std::array<int, 4> arr = {1, 2, 3, 4};
@@ -485,6 +533,13 @@ TEST_CASE("from_const_std_array_constructor")
CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()));
}
+ const std::array<AddressOverloaded, 4> ao_arr{};
+
+ {
+ span<const AddressOverloaded, 4> s{ao_arr};
+ CHECK((s.size() == narrow_cast<ptrdiff_t>(ao_arr.size()) && s.data() == ao_arr.data()));
+ }
+
#ifdef CONFIRM_COMPILATION_ERRORS
{
span<const int, 2> s{arr};
@@ -514,6 +569,7 @@ TEST_CASE("from_const_std_array_constructor")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_std_array_const_constructor")
{
std::array<const int, 4> arr = {1, 2, 3, 4};
@@ -554,104 +610,7 @@ TEST_CASE("from_std_array_const_constructor")
}
}
-TEST_CASE("from_unique_pointer_construction")
-{
- {
- auto ptr = std::make_unique<int>(4);
-
- {
- span<int> s{ptr};
- CHECK((s.length() == 1 && s.data() == ptr.get()));
- CHECK(s[0] == 4);
- }
-
- {
- auto s = make_span(ptr);
- CHECK((s.length() == 1 && s.data() == ptr.get()));
- CHECK(s[0] == 4);
- }
- }
-
- {
- auto ptr = std::unique_ptr<int>{nullptr};
-
- {
- span<int> s{ptr};
- CHECK((s.length() == 0 && s.data() == nullptr));
- }
-
- {
- auto s = make_span(ptr);
- CHECK((s.length() == 0 && s.data() == nullptr));
- }
- }
-
- {
- auto arr = std::make_unique<int[]>(4);
-
- for (auto i = 0U; i < 4; i++) arr[i] = gsl::narrow_cast<int>(i + 1);
-
- {
- span<int> s{arr, 4};
- CHECK((s.length() == 4 && s.data() == arr.get()));
- CHECK((s[0] == 1 && s[1] == 2));
- }
-
- {
- auto s = make_span(arr, 4);
- CHECK((s.length() == 4 && s.data() == arr.get()));
- CHECK((s[0] == 1 && s[1] == 2));
- }
- }
-
- {
- auto arr = std::unique_ptr<int[]>{nullptr};
-
- {
- span<int> s{arr, 0};
- CHECK((s.length() == 0 && s.data() == nullptr));
- }
-
- {
- auto s = make_span(arr, 0);
- CHECK((s.length() == 0 && s.data() == nullptr));
- }
- }
-}
-
-TEST_CASE("from_shared_pointer_construction")
-{
- {
- auto ptr = std::make_shared<int>(4);
-
- {
- span<int> s{ptr};
- CHECK((s.length() == 1 && s.data() == ptr.get()));
- CHECK((s[0] == 4));
- }
-
- {
- auto s = make_span(ptr);
- CHECK((s.length() == 1 && s.data() == ptr.get()));
- CHECK((s[0] == 4));
- }
- }
-
- {
- auto ptr = std::shared_ptr<int>{nullptr};
-
- {
- span<int> s{ptr};
- CHECK((s.length() == 0 && s.data() == nullptr));
- }
-
- {
- auto s = make_span(ptr);
- CHECK((s.length() == 0 && s.data() == nullptr));
- }
- }
-}
-
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_container_constructor")
{
std::vector<int> v = {1, 2, 3};
@@ -744,6 +703,7 @@ TEST_CASE("from_container_constructor")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_convertible_span_constructor")
{
{
@@ -781,6 +741,7 @@ TEST_CASE("from_convertible_span_constructor")
#endif
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("copy_move_and_assignment")
{
span<int> s1;
@@ -789,163 +750,179 @@ TEST_CASE("copy_move_and_assignment")
int arr[] = {3, 4, 5};
span<const int> s2 = arr;
- CHECK((s2.length() == 3 && s2.data() == &arr[0]));
+ CHECK((s2.size() == 3 && s2.data() == &arr[0]));
s2 = s1;
CHECK(s2.empty());
auto get_temp_span = [&]() -> span<int> { return {&arr[1], 2}; };
- auto use_span = [&](span<const int> s) { CHECK((s.length() == 2 && s.data() == &arr[1])); };
+ auto use_span = [&](span<const int> s) { CHECK((s.size() == 2 && s.data() == &arr[1])); };
use_span(get_temp_span());
s1 = get_temp_span();
- CHECK((s1.length() == 2 && s1.data() == &arr[1]));
+ CHECK((s1.size() == 2 && s1.data() == &arr[1]));
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("first")
{
int arr[5] = {1, 2, 3, 4, 5};
{
span<int, 5> av = arr;
- CHECK(av.first<2>().length() == 2);
- CHECK(av.first(2).length() == 2);
+ CHECK(av.first<2>().size() == 2);
+ CHECK(av.first(2).size() == 2);
}
{
span<int, 5> av = arr;
- CHECK(av.first<0>().length() == 0);
- CHECK(av.first(0).length() == 0);
+ CHECK(av.first<0>().size() == 0);
+ CHECK(av.first(0).size() == 0);
}
{
span<int, 5> av = arr;
- CHECK(av.first<5>().length() == 5);
- CHECK(av.first(5).length() == 5);
+ CHECK(av.first<5>().size() == 5);
+ CHECK(av.first(5).size() == 5);
}
{
span<int, 5> av = arr;
#ifdef CONFIRM_COMPILATION_ERRORS
- CHECK(av.first<6>().length() == 6);
- CHECK(av.first<-1>().length() == -1);
+ CHECK(av.first<6>().size() == 6);
+ CHECK(av.first<-1>().size() == -1);
#endif
- CHECK_THROWS_AS(av.first(6).length(), fail_fast);
+ CHECK_THROWS_AS(av.first(6).size(), fail_fast);
}
{
span<int> av;
- CHECK(av.first<0>().length() == 0);
- CHECK(av.first(0).length() == 0);
+ CHECK(av.first<0>().size() == 0);
+ CHECK(av.first(0).size() == 0);
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("last")
{
int arr[5] = {1, 2, 3, 4, 5};
{
span<int, 5> av = arr;
- CHECK(av.last<2>().length() == 2);
- CHECK(av.last(2).length() == 2);
+ CHECK(av.last<2>().size() == 2);
+ CHECK(av.last(2).size() == 2);
}
{
span<int, 5> av = arr;
- CHECK(av.last<0>().length() == 0);
- CHECK(av.last(0).length() == 0);
+ CHECK(av.last<0>().size() == 0);
+ CHECK(av.last(0).size() == 0);
}
{
span<int, 5> av = arr;
- CHECK(av.last<5>().length() == 5);
- CHECK(av.last(5).length() == 5);
+ CHECK(av.last<5>().size() == 5);
+ CHECK(av.last(5).size() == 5);
}
{
span<int, 5> av = arr;
#ifdef CONFIRM_COMPILATION_ERRORS
- CHECK(av.last<6>().length() == 6);
+ CHECK(av.last<6>().size() == 6);
#endif
- CHECK_THROWS_AS(av.last(6).length(), fail_fast);
+ CHECK_THROWS_AS(av.last(6).size(), fail_fast);
}
{
span<int> av;
- CHECK(av.last<0>().length() == 0);
- CHECK(av.last(0).length() == 0);
+ CHECK(av.last<0>().size() == 0);
+ CHECK(av.last(0).size() == 0);
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("subspan")
{
int arr[5] = {1, 2, 3, 4, 5};
{
span<int, 5> av = arr;
- CHECK((av.subspan<2, 2>().length() == 2));
- CHECK(av.subspan(2, 2).length() == 2);
- CHECK(av.subspan(2, 3).length() == 3);
+ CHECK((av.subspan<2, 2>().size() == 2));
+ CHECK(decltype(av.subspan<2, 2>())::extent == 2);
+ CHECK(av.subspan(2, 2).size() == 2);
+ CHECK(av.subspan(2, 3).size() == 3);
}
{
span<int, 5> av = arr;
- CHECK((av.subspan<0, 0>().length() == 0));
- CHECK(av.subspan(0, 0).length() == 0);
+ CHECK((av.subspan<0, 0>().size() == 0));
+ CHECK(decltype(av.subspan<0,0>())::extent == 0);
+ CHECK(av.subspan(0, 0).size() == 0);
}
{
span<int, 5> av = arr;
- CHECK((av.subspan<0, 5>().length() == 5));
- CHECK(av.subspan(0, 5).length() == 5);
- CHECK_THROWS_AS(av.subspan(0, 6).length(), fail_fast);
- CHECK_THROWS_AS(av.subspan(1, 5).length(), fail_fast);
+ CHECK((av.subspan<0, 5>().size() == 5));
+ CHECK(decltype(av.subspan<0, 5>())::extent == 5);
+ CHECK(av.subspan(0, 5).size() == 5);
+
+ CHECK_THROWS_AS(av.subspan(0, 6).size(), fail_fast);
+ CHECK_THROWS_AS(av.subspan(1, 5).size(), fail_fast);
}
{
span<int, 5> av = arr;
- CHECK((av.subspan<4, 0>().length() == 0));
- CHECK(av.subspan(4, 0).length() == 0);
- CHECK(av.subspan(5, 0).length() == 0);
- CHECK_THROWS_AS(av.subspan(6, 0).length(), fail_fast);
+ CHECK((av.subspan<4, 0>().size() == 0));
+ CHECK(decltype(av.subspan<4, 0>())::extent == 0);
+ CHECK(av.subspan(4, 0).size() == 0);
+ CHECK(av.subspan(5, 0).size() == 0);
+ CHECK_THROWS_AS(av.subspan(6, 0).size(), fail_fast);
+ }
+
+ {
+ span<int, 5> av = arr;
+ CHECK((av.subspan<1>().size() == 4));
+ CHECK(decltype(av.subspan<1>())::extent == 4);
}
{
span<int> av;
- CHECK((av.subspan<0, 0>().length() == 0));
- CHECK(av.subspan(0, 0).length() == 0);
- CHECK_THROWS_AS((av.subspan<1, 0>().length()), fail_fast);
+ CHECK((av.subspan<0, 0>().size() == 0));
+ CHECK((decltype(av.subspan<0, 0>())::extent == 0));
+ CHECK(av.subspan(0, 0).size() == 0);
+ CHECK_THROWS_AS((av.subspan<1, 0>().size()), fail_fast);
}
{
span<int> av;
- CHECK(av.subspan(0).length() == 0);
- CHECK_THROWS_AS(av.subspan(1).length(), fail_fast);
+ CHECK(av.subspan(0).size() == 0);
+ CHECK_THROWS_AS(av.subspan(1).size(), fail_fast);
}
{
span<int> av = arr;
- CHECK(av.subspan(0).length() == 5);
- CHECK(av.subspan(1).length() == 4);
- CHECK(av.subspan(4).length() == 1);
- CHECK(av.subspan(5).length() == 0);
- CHECK_THROWS_AS(av.subspan(6).length(), fail_fast);
+ CHECK(av.subspan(0).size() == 5);
+ CHECK(av.subspan(1).size() == 4);
+ CHECK(av.subspan(4).size() == 1);
+ CHECK(av.subspan(5).size() == 0);
+ CHECK_THROWS_AS(av.subspan(6).size(), fail_fast);
const auto av2 = av.subspan(1);
for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2);
}
{
span<int, 5> av = arr;
- CHECK(av.subspan(0).length() == 5);
- CHECK(av.subspan(1).length() == 4);
- CHECK(av.subspan(4).length() == 1);
- CHECK(av.subspan(5).length() == 0);
- CHECK_THROWS_AS(av.subspan(6).length(), fail_fast);
+ CHECK(av.subspan(0).size() == 5);
+ CHECK(av.subspan(1).size() == 4);
+ CHECK(av.subspan(4).size() == 1);
+ CHECK(av.subspan(5).size() == 0);
+ CHECK_THROWS_AS(av.subspan(6).size(), fail_fast);
const auto av2 = av.subspan(1);
for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2);
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("at_call")
{
int arr[4] = {1, 2, 3, 4};
@@ -965,6 +942,7 @@ TEST_CASE("at_call")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("operator_function_call")
{
int arr[4] = {1, 2, 3, 4};
@@ -984,6 +962,7 @@ TEST_CASE("operator_function_call")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("iterator_default_init")
{
span<int>::iterator it1;
@@ -991,6 +970,7 @@ TEST_CASE("iterator_default_init")
CHECK(it1 == it2);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("const_iterator_default_init")
{
span<int>::const_iterator it1;
@@ -998,6 +978,7 @@ TEST_CASE("const_iterator_default_init")
CHECK(it1 == it2);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("iterator_conversions")
{
span<int>::iterator badIt;
@@ -1020,6 +1001,7 @@ TEST_CASE("iterator_conversions")
CHECK(cit3 == s.cend());
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("iterator_comparisons")
{
int a[] = {1, 2, 3, 4};
@@ -1067,6 +1049,7 @@ TEST_CASE("iterator_comparisons")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("begin_end")
{
{
@@ -1122,6 +1105,7 @@ TEST_CASE("begin_end")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("cbegin_cend")
{
{
@@ -1174,6 +1158,7 @@ TEST_CASE("cbegin_cend")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("rbegin_rend")
{
{
@@ -1216,6 +1201,7 @@ TEST_CASE("rbegin_rend")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("crbegin_crend")
{
{
@@ -1255,11 +1241,12 @@ TEST_CASE("crbegin_crend")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("comparison_operators")
{
{
- span<int> s1 = nullptr;
- span<int> s2 = nullptr;
+ span<int> s1;
+ span<int> s2;
CHECK(s1 == s2);
CHECK(!(s1 != s2));
CHECK(!(s1 < s2));
@@ -1296,7 +1283,7 @@ TEST_CASE("comparison_operators")
{
int arr[] = {2, 1}; // bigger
- span<int> s1 = nullptr;
+ span<int> s1;
span<int> s2 = arr;
CHECK(s1 != s2);
@@ -1375,23 +1362,24 @@ TEST_CASE("comparison_operators")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_bytes")
{
int a[] = {1, 2, 3, 4};
{
const span<const int> s = a;
- CHECK(s.length() == 4);
+ CHECK(s.size() == 4);
const span<const byte> bs = as_bytes(s);
CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
- CHECK(bs.length() == s.length_bytes());
+ CHECK(bs.size() == s.size_bytes());
}
{
span<int> s;
const auto bs = as_bytes(s);
- CHECK(bs.length() == s.length());
- CHECK(bs.length() == 0);
+ CHECK(bs.size() == s.size());
+ CHECK(bs.size() == 0);
CHECK(bs.size_bytes() == 0);
CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
CHECK(bs.data() == nullptr);
@@ -1401,10 +1389,11 @@ TEST_CASE("as_bytes")
span<int> s = a;
const auto bs = as_bytes(s);
CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
- CHECK(bs.length() == s.length_bytes());
+ CHECK(bs.size() == s.size_bytes());
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_writeable_bytes")
{
int a[] = {1, 2, 3, 4};
@@ -1413,18 +1402,18 @@ TEST_CASE("as_writeable_bytes")
#ifdef CONFIRM_COMPILATION_ERRORS
// you should not be able to get writeable bytes for const objects
span<const int> s = a;
- CHECK(s.length() == 4);
+ CHECK(s.size() == 4);
span<const byte> bs = as_writeable_bytes(s);
CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
- CHECK(bs.length() == s.length_bytes());
+ CHECK(bs.size() == s.size_bytes());
#endif
}
{
span<int> s;
const auto bs = as_writeable_bytes(s);
- CHECK(bs.length() == s.length());
- CHECK(bs.length() == 0);
+ CHECK(bs.size() == s.size());
+ CHECK(bs.size() == 0);
CHECK(bs.size_bytes() == 0);
CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
CHECK(bs.data() == nullptr);
@@ -1434,22 +1423,23 @@ TEST_CASE("as_writeable_bytes")
span<int> s = a;
const auto bs = as_writeable_bytes(s);
CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
- CHECK(bs.length() == s.length_bytes());
+ CHECK(bs.size() == s.size_bytes());
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("fixed_size_conversions")
{
int arr[] = {1, 2, 3, 4};
// converting to an span from an equal size array is ok
span<int, 4> s4 = arr;
- CHECK(s4.length() == 4);
+ CHECK(s4.size() == 4);
// converting to dynamic_range is always ok
{
span<int> s = s4;
- CHECK(s.length() == s4.length());
+ CHECK(s.size() == s4.size());
static_cast<void>(s);
}
@@ -1468,7 +1458,7 @@ TEST_CASE("fixed_size_conversions")
{
span<int> s = arr;
auto f = [&]() {
- span<int, 2> s2 = s;
+ const span<int, 2> s2 = s;
static_cast<void>(s2);
};
CHECK_THROWS_AS(f(), fail_fast);
@@ -1478,7 +1468,7 @@ TEST_CASE("fixed_size_conversions")
// you can convert statically
{
- const span<int, 2> s2 = {arr, 2};
+ const span<int, 2> s2 = {&arr[0], 2};
static_cast<void>(s2);
}
{
@@ -1507,7 +1497,7 @@ TEST_CASE("fixed_size_conversions")
#endif
{
auto f = [&]() {
- span<int, 4> _s4 = {arr2, 2};
+ const span<int, 4> _s4 = {arr2, 2};
static_cast<void>(_s4);
};
CHECK_THROWS_AS(f(), fail_fast);
@@ -1516,12 +1506,13 @@ TEST_CASE("fixed_size_conversions")
// this should fail - we are trying to assign a small dynamic span to a fixed_size larger one
span<int> av = arr2;
auto f = [&]() {
- span<int, 4> _s4 = av;
+ const span<int, 4> _s4 = av;
static_cast<void>(_s4);
};
CHECK_THROWS_AS(f(), fail_fast);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("interop_with_std_regex")
{
char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'};
@@ -1545,6 +1536,7 @@ TEST_CASE("interop_with_std_regex")
CHECK(match[0].second == (f_it + 1));
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("interop_with_gsl_at")
{
int arr[5] = {1, 2, 3, 4, 5};
@@ -1558,3 +1550,4 @@ TEST_CASE("default_constructible")
CHECK((std::is_default_constructible<span<int, 0>>::value));
CHECK((!std::is_default_constructible<span<int, 42>>::value));
}
+
diff --git a/tests/strided_span_tests.cpp b/tests/strided_span_tests.cpp
index a1ecfcb..2310f5b 100644
--- a/tests/strided_span_tests.cpp
+++ b/tests/strided_span_tests.cpp
@@ -14,16 +14,28 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
-#include <gsl/multi_span>
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
+
+#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
-#include <iostream>
-#include <list>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
+namespace gsl {
+struct fail_fast;
+} // namespace gsl
using namespace std;
using namespace gsl;
@@ -43,8 +55,8 @@ TEST_CASE("span_section_test")
int a[30][4][5];
const auto av = as_multi_span(a);
- const auto sub = av.section({15, 0, 0}, gsl::index<3>{2, 2, 2});
- const auto subsub = sub.section({1, 0, 0}, gsl::index<3>{1, 1, 1});
+ 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;
}
@@ -55,17 +67,20 @@ TEST_CASE("span_section")
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});
+ CHECK(!av_section_1.empty());
CHECK((av_section_1[{0, 0}] == 12));
CHECK((av_section_1[{0, 1}] == 13));
CHECK((av_section_1[{1, 0}] == 22));
CHECK((av_section_1[{2, 3}] == 35));
const strided_span<int, 2> av_section_2 = av_section_1.section({1, 2}, {2, 2});
+ CHECK(!av_section_2.empty());
CHECK((av_section_2[{0, 0}] == 24));
CHECK((av_section_2[{0, 1}] == 25));
CHECK((av_section_2[{1, 0}] == 34));
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_constructors")
{
// Check stride constructor
@@ -74,18 +89,18 @@ TEST_CASE("strided_span_constructors")
const int carr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
strided_span<int, 1> sav1{arr, {{9}, {1}}}; // T -> T
- CHECK(sav1.bounds().index_bounds() == index<1>{9});
+ CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{9});
CHECK(sav1.bounds().stride() == 1);
CHECK((sav1[0] == 1 && sav1[8] == 9));
strided_span<const int, 1> sav2{carr, {{4}, {2}}}; // const T -> const T
- CHECK(sav2.bounds().index_bounds() == index<1>{4});
- CHECK(sav2.bounds().strides() == index<1>{2});
+ CHECK(sav2.bounds().index_bounds() == multi_span_index<1>{4});
+ CHECK(sav2.bounds().strides() == multi_span_index<1>{2});
CHECK((sav2[0] == 1 && sav2[3] == 7));
strided_span<int, 2> sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T
- CHECK((sav3.bounds().index_bounds() == index<2>{2, 2}));
- CHECK((sav3.bounds().strides() == index<2>{6, 2}));
+ CHECK((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2}));
+ CHECK((sav3.bounds().strides() == multi_span_index<2>{6, 2}));
CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7));
}
@@ -98,8 +113,8 @@ TEST_CASE("strided_span_constructors")
const multi_span<int> src = arr;
strided_span<int, 1> sav{src, {2, 1}};
- CHECK(sav.bounds().index_bounds() == index<1>{2});
- CHECK(sav.bounds().strides() == index<1>{1});
+ CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav.bounds().strides() == multi_span_index<1>{1});
CHECK(sav[1] == 2);
#if _MSC_VER > 1800
@@ -110,8 +125,8 @@ TEST_CASE("strided_span_constructors")
strided_span<const int, 1> sav_c{multi_span<const int>{src},
strided_bounds<1>{2, 1}};
#endif
- CHECK(sav_c.bounds().index_bounds() == index<1>{2});
- CHECK(sav_c.bounds().strides() == index<1>{1});
+ CHECK(sav_c.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav_c.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_c[1] == 2);
#if _MSC_VER > 1800
@@ -120,8 +135,8 @@ TEST_CASE("strided_span_constructors")
strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src},
strided_bounds<1>{2, 1}};
#endif
- CHECK(sav_v.bounds().index_bounds() == index<1>{2});
- CHECK(sav_v.bounds().strides() == index<1>{1});
+ CHECK(sav_v.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav_v.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_v[1] == 2);
#if _MSC_VER > 1800
@@ -130,8 +145,8 @@ TEST_CASE("strided_span_constructors")
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}};
#endif
- CHECK(sav_cv.bounds().index_bounds() == index<1>{2});
- CHECK(sav_cv.bounds().strides() == index<1>{1});
+ CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2);
}
@@ -140,8 +155,8 @@ TEST_CASE("strided_span_constructors")
const multi_span<const int> src{arr};
strided_span<const int, 1> sav_c{src, {2, 1}};
- CHECK(sav_c.bounds().index_bounds() == index<1>{2});
- CHECK(sav_c.bounds().strides() == index<1>{1});
+ CHECK(sav_c.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav_c.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_c[1] == 2);
#if _MSC_VER > 1800
@@ -151,8 +166,8 @@ TEST_CASE("strided_span_constructors")
strided_bounds<1>{2, 1}};
#endif
- CHECK(sav_cv.bounds().index_bounds() == index<1>{2});
- CHECK(sav_cv.bounds().strides() == index<1>{1});
+ CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2);
}
@@ -161,8 +176,8 @@ TEST_CASE("strided_span_constructors")
const multi_span<volatile int> src{arr};
strided_span<volatile int, 1> sav_v{src, {2, 1}};
- CHECK(sav_v.bounds().index_bounds() == index<1>{2});
- CHECK(sav_v.bounds().strides() == index<1>{1});
+ CHECK(sav_v.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav_v.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_v[1] == 2);
#if _MSC_VER > 1800
@@ -171,8 +186,8 @@ TEST_CASE("strided_span_constructors")
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}};
#endif
- CHECK(sav_cv.bounds().index_bounds() == index<1>{2});
- CHECK(sav_cv.bounds().strides() == index<1>{1});
+ CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2);
}
@@ -181,8 +196,8 @@ TEST_CASE("strided_span_constructors")
const multi_span<const volatile int> src{arr};
strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
- CHECK(sav_cv.bounds().index_bounds() == index<1>{2});
- CHECK(sav_cv.bounds().strides() == index<1>{1});
+ CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2);
}
}
@@ -201,7 +216,7 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src{arr, {2, 1}};
strided_span<const int, 1> sav{src};
- CHECK(sav.bounds().index_bounds() == index<1>{2});
+ CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav.bounds().stride() == 1);
CHECK(sav[1] == 5);
@@ -216,15 +231,15 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> sav1{src1};
- CHECK(sav1.bounds().index_bounds() == index<1>{2});
+ CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav1.bounds().stride() == 1);
CHECK(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};
- CHECK((sav2.bounds().index_bounds() == index<2>{3, 2}));
- CHECK((sav2.bounds().strides() == index<2>{2, 1}));
+ CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
+ CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5));
}
@@ -236,8 +251,8 @@ TEST_CASE("strided_span_constructors")
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);
- CHECK(sav.bounds().index_bounds() == index<1>{2});
- CHECK(sav.bounds().strides() == index<1>{1});
+ CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav.bounds().strides() == multi_span_index<1>{1});
CHECK(sav[0] == 1);
CHECK(&sav_ref == &sav);
}
@@ -249,8 +264,8 @@ TEST_CASE("strided_span_constructors")
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);
- CHECK(sav1.bounds().index_bounds() == index<1>{2});
- CHECK(sav1.bounds().strides() == index<1>{1});
+ CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{2});
+ CHECK(sav1.bounds().strides() == multi_span_index<1>{1});
CHECK(sav1[0] == 3);
CHECK(&sav1_ref == &sav1);
@@ -259,13 +274,14 @@ TEST_CASE("strided_span_constructors")
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);
- CHECK((sav2.bounds().index_bounds() == index<2>{3, 2}));
- CHECK((sav2.bounds().strides() == index<2>{2, 1}));
+ CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
+ CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5));
CHECK(&sav2_ref == &sav2);
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_slice")
{
std::vector<int> data(5 * 10);
@@ -292,9 +308,10 @@ TEST_CASE("strided_span_slice")
CHECK(sav[4][9] == 49);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_column_major")
{
- // strided_span may be used to accomodate more peculiar
+ // strided_span may be used to accommodate more peculiar
// use cases, such as column-major multidimensional array
// (aka. "FORTRAN" layout).
@@ -317,13 +334,14 @@ TEST_CASE("strided_span_column_major")
// Section
strided_span<int, 2> cm_sec = cm_sav.section({2, 1}, {3, 2});
- CHECK((cm_sec.bounds().index_bounds() == index<2>{3, 2}));
+ CHECK((cm_sec.bounds().index_bounds() == multi_span_index<2>{3, 2}));
CHECK((cm_sec[{0, 0}] == 8));
CHECK((cm_sec[{0, 1}] == 9));
CHECK((cm_sec[{1, 0}] == 11));
CHECK((cm_sec[{2, 1}] == 15));
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_bounds")
{
int arr[] = {0, 1, 2, 3};
@@ -366,7 +384,7 @@ TEST_CASE("strided_span_bounds")
{
// strided array ctor with matching strided bounds
strided_span<int, 1> sav{arr, {4, 1}};
- CHECK(sav.bounds().index_bounds() == index<1>{4});
+ CHECK(sav.bounds().index_bounds() == multi_span_index<1>{4});
CHECK(sav[3] == 3);
CHECK_THROWS_AS(sav[4], fail_fast);
}
@@ -374,7 +392,7 @@ TEST_CASE("strided_span_bounds")
{
// strided array ctor with smaller strided bounds
strided_span<int, 1> sav{arr, {2, 1}};
- CHECK(sav.bounds().index_bounds() == index<1>{2});
+ CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav[1] == 1);
CHECK_THROWS_AS(sav[2], fail_fast);
}
@@ -382,7 +400,7 @@ TEST_CASE("strided_span_bounds")
{
// strided array ctor with fitting irregular bounds
strided_span<int, 1> sav{arr, {2, 3}};
- CHECK(sav.bounds().index_bounds() == index<1>{2});
+ CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav[0] == 0);
CHECK(sav[1] == 3);
CHECK_THROWS_AS(sav[2], fail_fast);
@@ -428,7 +446,7 @@ TEST_CASE("strided_span_bounds")
strided_span<int, 2> sav7{av.as_multi_span(dim<2>(), dim<2>()),
{{1, 1}, {1, 1}, {1, 1}}};
- index<1> index{0, 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}}};
@@ -440,6 +458,7 @@ TEST_CASE("strided_span_bounds")
#endif
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_type_conversion")
{
int arr[] = {0, 1, 2, 3};
@@ -537,13 +556,16 @@ TEST_CASE("strided_span_type_conversion")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
TEST_CASE("empty_strided_spans")
{
{
multi_span<int, 0> empty_av(nullptr);
strided_span<int, 1> empty_sav{empty_av, {0, 1}};
- CHECK(empty_sav.bounds().index_bounds() == index<1>{0});
+ CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
+ CHECK(empty_sav.empty());
CHECK_THROWS_AS(empty_sav[0], fail_fast);
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast);
@@ -557,7 +579,7 @@ TEST_CASE("empty_strided_spans")
{
strided_span<int, 1> empty_sav{nullptr, 0, {0, 1}};
- CHECK(empty_sav.bounds().index_bounds() == index<1>{0});
+ CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_sav[0], fail_fast);
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast);
@@ -569,6 +591,8 @@ TEST_CASE("empty_strided_spans")
}
}
+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
@@ -577,7 +601,7 @@ void iterate_every_other_element(multi_span<int, dynamic_range> av)
#if _MSC_VER > 1800
auto bounds = strided_bounds<1>({length}, {2});
#else
- auto bounds = strided_bounds<1>(index<1>{length}, index<1>{2});
+ 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);
@@ -594,6 +618,7 @@ void iterate_every_other_element(multi_span<int, dynamic_range> av)
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_section_iteration")
{
int arr[8] = {4, 0, 5, 1, 6, 2, 7, 3};
@@ -611,6 +636,11 @@ TEST_CASE("strided_span_section_iteration")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("dynamic_strided_span_section_iteration")
{
auto arr = new int[8];
@@ -625,6 +655,9 @@ TEST_CASE("dynamic_strided_span_section_iteration")
delete[] arr;
}
+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};
@@ -633,7 +666,7 @@ void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_
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 = index<3>{i, j, k}; // avoid braces in the CHECK macro
+ auto idx = multi_span_index<3>{i, j, k}; // avoid braces in the CHECK macro
CHECK(section[idx] == expected[2 * i + 2 * j + k]);
}
}
@@ -651,6 +684,9 @@ void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("strided_span_section_iteration_3d")
{
int arr[3][4][2]{};
@@ -665,6 +701,11 @@ TEST_CASE("strided_span_section_iteration_3d")
}
}
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("dynamic_strided_span_section_iteration_3d")
{
const auto height = 12, width = 2;
@@ -697,6 +738,9 @@ TEST_CASE("dynamic_strided_span_section_iteration_3d")
delete[] arr;
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("strided_span_conversion")
{
// get an multi_span of 'c' values from the list of X's
@@ -715,7 +759,7 @@ TEST_CASE("strided_span_conversion")
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, 4)), dim(d1), dim(d2));
+ auto av = as_multi_span(as_bytes(as_multi_span(&arr[0], 4)), dim(d1), dim(d2));
CHECK(av.bounds().index_bounds()[0] == 4);
CHECK(av.bounds().index_bounds()[1] == 12);
diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp
index 229a117..fd3e3e6 100644
--- a/tests/string_span_tests.cpp
+++ b/tests/string_span_tests.cpp
@@ -14,18 +14,55 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
-#include <gsl/gsl> //owner
-#include <gsl/string_span>
+#endif
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
-#include <cstdlib>
-#include <map>
-#include <vector>
+#include <gsl/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
+
+#include <algorithm> // for move, find
+#include <cstddef> // for size_t
+#include <map> // for map
+#include <string> // for basic_string, string, char_traits, operat...
+#include <type_traits> // for remove_reference<>::type
+#include <vector> // for vector, allocator
using namespace std;
using namespace gsl;
+// Generic string functions
+
+namespace generic
+{
+
+template <typename CharT>
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(f.23) // NO-FORMAT: attribute
+auto strlen(const CharT* s)
+{
+ auto p = s;
+ while (*p) ++p;
+ return p - s;
+}
+
+template <typename CharT>
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+auto strnlen(const CharT* s, std::size_t n)
+{
+ return std::find(s, s + n, CharT{0}) - s;
+}
+
+} // namespace generic
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestLiteralConstruction")
{
cwstring_span<> v = ensure_z(L"Hello");
@@ -35,6 +72,7 @@ TEST_CASE("TestLiteralConstruction")
wstring_span<> v2 = ensure0(L"Hello");
#endif
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConstructFromStdString")
{
@@ -43,6 +81,7 @@ TEST_CASE("TestConstructFromStdString")
CHECK(v.length() == static_cast<cstring_span<>::index_type>(s.length()));
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConstructFromStdVector")
{
std::vector<char> vec(5, 'h');
@@ -50,6 +89,7 @@ TEST_CASE("TestConstructFromStdVector")
CHECK(v.length() == static_cast<string_span<>::index_type>(vec.size()));
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestStackArrayConstruction")
{
wchar_t stack_string[] = L"Hello";
@@ -75,6 +115,7 @@ TEST_CASE("TestStackArrayConstruction")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConstructFromConstCharPointer")
{
const char* s = "Hello";
@@ -82,6 +123,7 @@ TEST_CASE("TestConstructFromConstCharPointer")
CHECK(v.length() == 5);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConversionToConst")
{
char stack_string[] = "Hello";
@@ -90,6 +132,7 @@ TEST_CASE("TestConversionToConst")
CHECK(v.length() == v2.length());
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConversionFromConst")
{
char stack_string[] = "Hello";
@@ -101,6 +144,7 @@ TEST_CASE("TestConversionFromConst")
#endif
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestToString")
{
auto s = gsl::to_string(cstring_span<>{});
@@ -113,6 +157,7 @@ TEST_CASE("TestToString")
CHECK(s2.length() == 5);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestToBasicString")
{
auto s = gsl::to_basic_string<char, std::char_traits<char>, ::std::allocator<char>>(
@@ -126,6 +171,8 @@ TEST_CASE("TestToBasicString")
CHECK(s2.length() == 5);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("EqualityAndImplicitConstructors")
{
{
@@ -352,6 +399,8 @@ TEST_CASE("EqualityAndImplicitConstructors")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("ComparisonAndImplicitConstructors")
{
{
@@ -422,6 +471,12 @@ TEST_CASE("ComparisonAndImplicitConstructors")
CHECK(span >= string_span<>(vec));
}
}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
+GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("ConstrutorsEnsureZ")
{
// remove z from literals
@@ -452,6 +507,8 @@ TEST_CASE("ConstrutorsEnsureZ")
}
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("Constructors")
{
// creating cstring_span
@@ -485,12 +542,6 @@ TEST_CASE("Constructors")
CHECK(span.length() == 0);
}
- // from nullptr
- {
- cstring_span<> span(nullptr);
- CHECK(span.length() == 0);
- }
-
// from string literal
{
cstring_span<> span = "Hello";
@@ -748,7 +799,7 @@ TEST_CASE("Constructors")
}
template <typename T>
-T move_wrapper(T && t)
+T move_wrapper(T&& t)
{
return std::move(t);
}
@@ -864,6 +915,8 @@ czstring_span<> CreateTempName(string_span<> span)
return {ret};
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("zstring")
{
@@ -874,7 +927,7 @@ TEST_CASE("zstring")
zstring_span<> zspan({buf, 1});
- CHECK(strlen(zspan.assume_z()) == 0);
+ CHECK(generic::strlen(zspan.assume_z()) == 0);
CHECK(zspan.as_string_span().size() == 0);
CHECK(zspan.ensure_z().size() == 0);
}
@@ -884,7 +937,7 @@ TEST_CASE("zstring")
char buf[1];
buf[0] = 'a';
- auto workaround_macro = [&]() { zstring_span<> zspan({buf, 1}); };
+ auto workaround_macro = [&]() { const zstring_span<> zspan({buf, 1}); };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
@@ -895,7 +948,7 @@ TEST_CASE("zstring")
auto name = CreateTempName({buf, 10});
if (!name.empty()) {
czstring<> str = name.assume_z();
- CHECK(strlen(str) == 3);
+ CHECK(generic::strlen(str) == 3);
CHECK(*(str + 3) == '\0');
}
}
@@ -918,6 +971,8 @@ cwzstring_span<> CreateTempNameW(wstring_span<> span)
return {ret};
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("wzstring")
{
@@ -928,7 +983,7 @@ TEST_CASE("wzstring")
wzstring_span<> zspan({buf, 1});
- CHECK(wcsnlen(zspan.assume_z(), 1) == 0);
+ CHECK(generic::strnlen(zspan.assume_z(), 1) == 0);
CHECK(zspan.as_string_span().size() == 0);
CHECK(zspan.ensure_z().size() == 0);
}
@@ -938,7 +993,7 @@ TEST_CASE("wzstring")
wchar_t buf[1];
buf[0] = L'a';
- const auto workaround_macro = [&]() { wzstring_span<> zspan({buf, 1}); };
+ const auto workaround_macro = [&]() { const wzstring_span<> zspan({buf, 1}); };
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
@@ -949,7 +1004,119 @@ TEST_CASE("wzstring")
const auto name = CreateTempNameW({buf, 10});
if (!name.empty()) {
cwzstring<> str = name.assume_z();
- CHECK(wcsnlen(str, 10) == 3);
+ CHECK(generic::strnlen(str, 10) == 3);
+ CHECK(*(str + 3) == L'\0');
+ }
+ }
+}
+
+cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
+{
+ Expects(span.size() > 1);
+
+ int last = 0;
+ if (span.size() > 4) {
+ span[0] = u't';
+ span[1] = u'm';
+ span[2] = u'p';
+ last = 3;
+ }
+ span[last] = u'\0';
+
+ auto ret = span.subspan(0, 4);
+ return {ret};
+}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+TEST_CASE("u16zstring")
+{
+
+ // create zspan from zero terminated string
+ {
+ char16_t buf[1];
+ buf[0] = L'\0';
+
+ u16zstring_span<> zspan({buf, 1});
+
+ CHECK(generic::strnlen(zspan.assume_z(), 1) == 0);
+ CHECK(zspan.as_string_span().size() == 0);
+ CHECK(zspan.ensure_z().size() == 0);
+ }
+
+ // create zspan from non-zero terminated string
+ {
+ char16_t buf[1];
+ buf[0] = u'a';
+
+ const auto workaround_macro = [&]() { const u16zstring_span<> zspan({buf, 1}); };
+ CHECK_THROWS_AS(workaround_macro(), fail_fast);
+ }
+
+ // usage scenario: create zero-terminated temp file name and pass to a legacy API
+ {
+ char16_t buf[10];
+
+ const auto name = CreateTempNameU16({buf, 10});
+ if (!name.empty()) {
+ cu16zstring<> str = name.assume_z();
+ CHECK(generic::strnlen(str, 10) == 3);
+ CHECK(*(str + 3) == L'\0');
+ }
+ }
+}
+
+cu32zstring_span<> CreateTempNameU32(u32string_span<> span)
+{
+ Expects(span.size() > 1);
+
+ int last = 0;
+ if (span.size() > 4) {
+ span[0] = U't';
+ span[1] = U'm';
+ span[2] = U'p';
+ last = 3;
+ }
+ span[last] = U'\0';
+
+ auto ret = span.subspan(0, 4);
+ return {ret};
+}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+TEST_CASE("u32zstring")
+{
+
+ // create zspan from zero terminated string
+ {
+ char32_t buf[1];
+ buf[0] = L'\0';
+
+ u32zstring_span<> zspan({buf, 1});
+
+ CHECK(generic::strnlen(zspan.assume_z(), 1) == 0);
+ CHECK(zspan.as_string_span().size() == 0);
+ CHECK(zspan.ensure_z().size() == 0);
+ }
+
+ // create zspan from non-zero terminated string
+ {
+ char32_t buf[1];
+ buf[0] = u'a';
+
+ const auto workaround_macro = [&]() { const u32zstring_span<> zspan({buf, 1}); };
+ CHECK_THROWS_AS(workaround_macro(), fail_fast);
+ }
+
+ // usage scenario: create zero-terminated temp file name and pass to a legacy API
+ {
+ char32_t buf[10];
+
+ const auto name = CreateTempNameU32({buf, 10});
+ if (!name.empty()) {
+ cu32zstring<> str = name.assume_z();
+ CHECK(generic::strnlen(str, 10) == 3);
CHECK(*(str + 3) == L'\0');
}
}
@@ -961,3 +1128,106 @@ TEST_CASE("Issue305")
CHECK(foo["foo"] == 0);
CHECK(foo["bar"] == 1);
}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
+TEST_CASE("char16_t type")
+{
+ gsl::cu16string_span<> ss1 = gsl::ensure_z(u"abc");
+ CHECK(ss1.size() == 3);
+ CHECK(ss1.size_bytes() == 6);
+
+ std::u16string s1 = gsl::to_string(ss1);
+ CHECK(s1 == u"abc");
+
+ std::u16string s2 = u"abc";
+ gsl::u16string_span<> ss2 = s2;
+ CHECK(ss2.size() == 3);
+
+ gsl::u16string_span<> ss3 = ss2.subspan(1, 1);
+ CHECK(ss3.size() == 1);
+ CHECK(ss3[0] == u'b');
+
+ char16_t buf[4]{u'a', u'b', u'c', u'\0'};
+ gsl::u16string_span<> ss4{buf, 4};
+ CHECK(ss4[3] == u'\0');
+
+ gsl::cu16zstring_span<> ss5(u"abc");
+ CHECK(ss5.as_string_span().size() == 3);
+
+ gsl::cu16string_span<> ss6 = ss5.as_string_span();
+ CHECK(ss6 == ss1);
+
+ std::vector<char16_t> v7 = {u'a', u'b', u'c'};
+ gsl::cu16string_span<> ss7{v7};
+ CHECK(ss7 == ss1);
+
+ gsl::cu16string_span<> ss8 = gsl::ensure_z(u"abc");
+ gsl::cu16string_span<> ss9 = gsl::ensure_z(u"abc");
+ CHECK(ss8 == ss9);
+
+ ss9 = gsl::ensure_z(u"abd");
+ CHECK(ss8 < ss9);
+ CHECK(ss8 <= ss9);
+ CHECK(ss8 != ss9);
+}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
+TEST_CASE("char32_t type")
+{
+ gsl::cu32string_span<> ss1 = gsl::ensure_z(U"abc");
+ CHECK(ss1.size() == 3);
+ CHECK(ss1.size_bytes() == 12);
+
+ std::u32string s1 = gsl::to_string(ss1);
+ CHECK(s1 == U"abc");
+
+ std::u32string s2 = U"abc";
+ gsl::u32string_span<> ss2 = s2;
+ CHECK(ss2.size() == 3);
+
+ gsl::u32string_span<> ss3 = ss2.subspan(1, 1);
+ CHECK(ss3.size() == 1);
+ CHECK(ss3[0] == U'b');
+
+ char32_t buf[4]{U'a', U'b', U'c', U'\0'};
+ gsl::u32string_span<> ss4{buf, 4};
+ CHECK(ss4[3] == u'\0');
+
+ gsl::cu32zstring_span<> ss5(U"abc");
+ CHECK(ss5.as_string_span().size() == 3);
+
+ gsl::cu32string_span<> ss6 = ss5.as_string_span();
+ CHECK(ss6 == ss1);
+
+ gsl::cu32string_span<> ss8 = gsl::ensure_z(U"abc");
+ gsl::cu32string_span<> ss9 = gsl::ensure_z(U"abc");
+ CHECK(ss8 == ss9);
+
+ ss9 = gsl::ensure_z(U"abd");
+ CHECK(ss8 < ss9);
+ CHECK(ss8 <= ss9);
+ CHECK(ss8 != ss9);
+}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+TEST_CASE("as_bytes")
+{
+ cwzstring_span<> v(L"qwerty");
+ const auto s = v.as_string_span();
+ const auto bs = as_bytes(s);
+ CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
+ CHECK(bs.size() == s.size_bytes());
+}
+
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
+TEST_CASE("as_writeable_bytes")
+{
+ wchar_t buf[]{L"qwerty"};
+ wzstring_span<> v(buf);
+ const auto s = v.as_string_span();
+ const auto bs = as_writeable_bytes(s);
+ CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
+ CHECK(bs.size() == s.size_bytes());
+}
diff --git a/tests/test.cpp b/tests/test.cpp
index bae194d..dbdebb6 100644
--- a/tests/test.cpp
+++ b/tests/test.cpp
@@ -15,4 +15,12 @@
///////////////////////////////////////////////////////////////////////////////
#define CATCH_CONFIG_MAIN
+
+#ifdef _MSC_VER
+
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26401 26409 26415 26418 26426 26429 26432 26433 26434 26435 26436 26439 26440 26443 26444 26446 26447 26451 26460 26461 26466 26472 26481 26482 26485 26492 26493 26494 26495 26496 26497) // from catch
+#endif // _MSC_VER
+
#include <catch/catch.hpp>
diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp
index 67cceb5..05f8d0f 100644
--- a/tests/utils_tests.cpp
+++ b/tests/utils_tests.cpp
@@ -14,14 +14,31 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <catch/catch.hpp>
+#ifdef _MSC_VER
+// blanket turn off warnings from CppCoreCheck from catch
+// so people aren't annoyed by them when running the tool.
+#pragma warning(disable : 26440 26426) // from catch
-#include <gsl/gsl>
+#endif
-#include <functional>
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
+
+#include <gsl/gsl_util> // for narrow, finally, narrow_cast, narrowing_e...
+
+#include <algorithm> // for move
+#include <functional> // for reference_wrapper, _Bind_helper<>::type
+#include <limits> // for numeric_limits
+#include <stdint.h> // for uint32_t, int32_t
+#include <type_traits> // for is_same
using namespace gsl;
+TEST_CASE("sanity check for gsl::index typedef")
+{
+ static_assert(std::is_same<gsl::index, std::ptrdiff_t>::value,
+ "gsl::index represents wrong arithmetic type");
+}
+
void f(int& i) { i += 1; }
TEST_CASE("finally_lambda")
@@ -75,6 +92,7 @@ TEST_CASE("finally_function_ptr")
CHECK(j == 1);
}
+GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("narrow_cast")
{
int n = 120;
@@ -86,6 +104,7 @@ TEST_CASE("narrow_cast")
CHECK(uc == 44);
}
+GSL_SUPPRESS(con.5) // NO-FORMAT: attribute
TEST_CASE("narrow")
{
int n = 120;