Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/GSL.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kobets <dmitrykobets@microsoft.com>2022-09-27 01:27:01 +0300
committerDmitry Kobets <dmitrykobets@microsoft.com>2022-09-27 01:27:01 +0300
commit8840d871995e06e36ac7b2c1f3a1d1a9c447365f (patch)
tree553888391284f68e7791cc35764ff6d1a16c2c20
parentd569ed65d05791fa6589115e1bfea879c8e9c591 (diff)
parent10df83d292bf5bbdc487e57dc8c2dc8c7a01f4d1 (diff)
Merge remote-tracking branch 'origin/main' into final_action-revision
-rw-r--r--.github/workflows/android.yml2
-rw-r--r--.github/workflows/ios.yml6
-rw-r--r--.travis.yml337
-rw-r--r--CMakeLists.txt2
-rw-r--r--README.md40
-rw-r--r--SECURITY.md41
-rw-r--r--azure-pipelines.yml66
-rw-r--r--include/gsl/algorithm4
-rw-r--r--include/gsl/assert1
-rw-r--r--include/gsl/gsl16
-rw-r--r--include/gsl/gsl_algorithm5
-rw-r--r--include/gsl/gsl_assert2
-rw-r--r--include/gsl/gsl_byte2
-rw-r--r--include/gsl/gsl_narrow2
-rw-r--r--include/gsl/gsl_util2
-rw-r--r--include/gsl/narrow44
-rw-r--r--include/gsl/pointers19
-rw-r--r--include/gsl/span44
-rw-r--r--include/gsl/span_ext23
-rw-r--r--include/gsl/string_span30
-rw-r--r--include/gsl/util35
-rw-r--r--pipelines/jobs.yml63
-rw-r--r--pipelines/setup_apple.yml9
-rw-r--r--pipelines/setup_clang.yml13
-rw-r--r--pipelines/setup_gcc.yml14
-rw-r--r--pipelines/steps.yml17
-rw-r--r--tests/CMakeLists.txt97
-rw-r--r--tests/CMakeLists.txt.in2
-rw-r--r--tests/algorithm_tests.cpp27
-rw-r--r--tests/assertion_tests.cpp13
-rw-r--r--tests/at_tests.cpp95
-rw-r--r--tests/byte_tests.cpp6
-rw-r--r--tests/deathTestCommon.h11
-rw-r--r--tests/no_exception_ensure_tests.cpp7
-rw-r--r--tests/notnull_tests.cpp72
-rw-r--r--tests/owner_tests.cpp6
-rw-r--r--tests/span_compatibility_tests.cpp8
-rw-r--r--tests/span_ext_tests.cpp563
-rw-r--r--tests/span_tests.cpp1699
-rw-r--r--tests/strict_notnull_tests.cpp37
-rw-r--r--tests/string_span_tests.cpp64
-rw-r--r--tests/utils_tests.cpp18
42 files changed, 1770 insertions, 1794 deletions
diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
index 836b444..49e8c2e 100644
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -29,7 +29,7 @@ jobs:
echo "Emulator starting"
- name: Configure
- run: cmake -Werror=dev -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=16 -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Debug ..
+ run: cmake -Werror=dev -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/25.0.8775105/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=16 -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Debug ..
- name: Build
run: cmake --build . --parallel
diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml
index 9d29bbc..0ef9fa3 100644
--- a/.github/workflows/ios.yml
+++ b/.github/workflows/ios.yml
@@ -25,11 +25,11 @@ jobs:
-GXcode \
-DCMAKE_SYSTEM_NAME=iOS \
"-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
- -DCMAKE_OSX_DEPLOYMENT_TARGET=8 \
+ -DCMAKE_OSX_DEPLOYMENT_TARGET=9 \
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
"-DMACOSX_BUNDLE_GUI_IDENTIFIER=GSL.\$(EXECUTABLE_NAME)" \
- -DMACOSX_BUNDLE_BUNDLE_VERSION=3.0.1 \
- -DMACOSX_BUNDLE_SHORT_VERSION_STRING=3.0.1 \
+ -DMACOSX_BUNDLE_BUNDLE_VERSION=3.1.0 \
+ -DMACOSX_BUNDLE_SHORT_VERSION_STRING=3.1.0 \
..
- name: Build
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index a57955c..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,337 +0,0 @@
-
-language: cpp
-notifications:
- email: false
-
-# Use Linux unless specified otherwise
-os: linux
-dist: bionic
-
-cache:
- directories:
- - ${TRAVIS_BUILD_DIR}/deps
-
-stages:
- - name: Latest # Compiler with the latest major version
- - name: Previous # Compilers with the major version Latest - 1
- - name: Validation # run other jobs
-
-jobs:
- include:
-
- ##########################################################################
- # Validate CMake configuration
- ##########################################################################
-
- - name: CMake 3.1.3 - latest
- stage: Validation
- env: &CMAKE_VERSION_LIST
- - CMAKE_VERSION: '"3.17.0 3.16.5 3.15.7 3.14.7 3.13.5 3.12.4 3.11.4 3.10.3 3.9.6 3.8.2 3.7.2 3.6.3 3.5.2 3.4.3 3.3.2 3.2.3 3.1.3"'
- - GSL_CXX_STANDARD: 14
- addons: # Get latest release (candidate)
- apt:
- sources:
- - sourceline: 'deb https://apt.kitware.com/ubuntu/ bionic main'
- key_url: 'https://apt.kitware.com/keys/kitware-archive-latest.asc'
- - sourceline: 'deb https://apt.kitware.com/ubuntu/ bionic-rc main'
- packages:
- - cmake
- script:
- - |
- cd ./build
- ( set -eu
- for CMAKE in ${CMAKE_path[@]}; do test_CMake_generate $CMAKE; done
- export CXX=clang++
- for CMAKE in ${CMAKE_path[@]}; do test_CMake_generate $CMAKE; done
- )
-
- - name: CMake 3.2.3 - 3.17.0
- stage: Validation
- os: osx
- osx_image: xcode11.3
- env:
- - CMAKE_VERSION: '"3.17.0 3.16.5 3.15.7 3.14.7 3.13.5 3.12.4 3.11.4 3.10.3 3.9.6 3.8.2 3.7.2 3.6.3 3.5.2 3.4.3 3.3.2 3.2.3"'
- script:
- - |
- cd ./build
- ( set -eu
- for CMAKE in ${CMAKE_path[@]}; do test_CMake_generate $CMAKE; done
- )
-
- ##########################################################################
- # AppleClang on OSX
- ##########################################################################
-
-
-
- # Xcode 10.3
- - name: AppleClang Xcode-10.3 C++14 Debug
- stage: Previous
- env: BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- os: osx
- osx_image: xcode10.3 # AppleClang 10.0.1 same compiler as Xcode 10.2
- - name: AppleClang Xcode-10.3 C++14 Release
- env: BUILD_TYPE=Release GSL_CXX_STANDARD=14
- os: osx
- osx_image: xcode10.3
- - name: AppleClang Xcode-10.3 C++17 Debug
- env: BUILD_TYPE=Debug GSL_CXX_STANDARD=17
- os: osx
- osx_image: xcode10.3
- - name: AppleClang Xcode-10.3 C++17 Release
- env: BUILD_TYPE=Release GSL_CXX_STANDARD=17
- os: osx
- osx_image: xcode10.3
-
-
- # Xcode 11.4
- - name: AppleClang Xcode-11.4 C++17 Debug
- stage: Latest
- env: BUILD_TYPE=Debug GSL_CXX_STANDARD=17
- os: osx
- osx_image: xcode11.4
- - name: AppleClang Xcode-11.4 C++17 Release
- env: BUILD_TYPE=Release GSL_CXX_STANDARD=17
- os: osx
- osx_image: xcode11.4
- - name: AppleClang Xcode-11.4 C++14 Debug
- env: BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- os: osx
- osx_image: xcode11.4
- - name: AppleClang Xcode-11.4 C++14 Release
- env: BUILD_TYPE=Release GSL_CXX_STANDARD=14
- os: osx
- osx_image: xcode11.4
-
- ##########################################################################
- # Clang on Linux
- ##########################################################################
-
- # Clang 9
- - name: Clang-9 C++14 Debug
- stage: Previous
- env: CXX=clang++-9 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- addons: &clang9
- apt:
- sources:
- - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
- key_url: https://apt.llvm.org/llvm-snapshot.gpg.key
- packages:
- - clang-9
- - name: Clang-9 C++14 Release
- env: CXX=clang++-9 BUILD_TYPE=Release GSL_CXX_STANDARD=14
- addons: *clang9
- - name: Clang-9 C++17 Debug
- env: CXX=clang++-9 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
- addons: *clang9
- - name: Clang-9 C++17 Release
- env: CXX=clang++-9 BUILD_TYPE=Release GSL_CXX_STANDARD=17
- addons: *clang9
-
- # Clang 10
- - name: Clang-10 C++14 Debug
- stage: Latest
- env: CXX=clang++-10 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- addons: &clang10
- apt:
- sources:
- - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
- key_url: https://apt.llvm.org/llvm-snapshot.gpg.key
- packages:
- - clang-10
- - name: Clang-10 C++14 Release
- env: CXX=clang++-10 BUILD_TYPE=Release GSL_CXX_STANDARD=14
- addons: *clang10
- - name: Clang-10 C++17 Debug
- env: CXX=clang++-10 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
- addons: *clang10
- - name: Clang-10 C++17 Release
- env: CXX=clang++-10 BUILD_TYPE=Release GSL_CXX_STANDARD=17
- addons: *clang10
-
- ##########################################################################
- # GCC on Linux
- ##########################################################################
-
- # GCC 8
- - name: GCC-8 C++14 Debug
- stage: Previous
- env: CXX=g++-8 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- addons: &gcc8
- apt:
- packages: g++-8
- - name: GCC-8 C++14 Release
- env: CXX=g++-8 BUILD_TYPE=Release GSL_CXX_STANDARD=14
- addons: *gcc8
- - name: GCC-8 C++17 Debug
- env: CXX=g++-8 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
- addons: *gcc8
- - name: GCC-8 C++17 Release
- env: CXX=g++-8 BUILD_TYPE=Release GSL_CXX_STANDARD=17
- addons: *gcc8
-
- # GCC 9
- - name: GCC-9 C++14 Debug
- stage: Latest
- env: CXX=g++-9 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- addons: &gcc9
- apt:
- sources:
- - sourceline: ppa:ubuntu-toolchain-r/test
- packages:
- - g++-9
- - name: GCC-9 C++14 Release
- env: CXX=g++-9 BUILD_TYPE=Release GSL_CXX_STANDARD=14
- addons: *gcc9
- - name: GCC-9 C++17 Debug
- env: CXX=g++-9 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
- addons: *gcc9
- - name: GCC-9 C++17 Release
- env: CXX=g++-9 BUILD_TYPE=Release GSL_CXX_STANDARD=17
- addons: *gcc9
-
-before_install:
- - |
- # Configuration
- JOBS=2 # Travis machines have 2 cores
- # Dependencies required by the CI (cached directory)
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- - |
- # Setup
- mkdir -p "${DEPS_DIR:?}" && cd "${DEPS_DIR:?}"
- mkdir -p ~/tools && cd ~/tools
- if [[ ${TRAVIS_OS_NAME:?} == "osx" ]]; then
- export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
- fi
- - |
- # Helper functions
- # usage: if [[ $(check_url '<url>') ]]; then ...
- function check_url {( set +e
- if [[ "$1" =~ 'github.com' ]]; then # check for first byte
- if curl --fail --silent --output /dev/null --connect-timeout 12 --range 0-0 "$1"
- then echo true; fi
- else # request head
- if curl --fail --silent --output /dev/null --connect-timeout 12 --head "$1"
- then echo true; fi
- fi
- return
- )}
-
-install:
- ############################################################################
- # Install a different CMake version (or several)
- ############################################################################
- - |
- # Install CMake versions
- ( set -euo pipefail
- if [[ ${CMAKE_VERSION:-} ]]; then
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
- OS="Linux"; EXT="sh"
- if [[ ! ("${CMAKE_VERSION:-}" =~ .+[' '].+) ]]; then
- # Single entry -> default CMake version
- CMAKE_DEFAULT_DIR="/usr/local"
- fi
- elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then OS="Darwin"; EXT="tar.gz"
- else echo "CMake install not supported for this OS."; exit 1
- fi
- CMAKE_INSTALLER="install-cmake.${EXT}"
- fi
- for VERSION in ${CMAKE_VERSION:-}; do
- CMAKE_URL="https://github.com/Kitware/CMake/releases/download/v${VERSION}/cmake-${VERSION}-${OS}-x86_64.${EXT}"
- if [[ $(check_url "$CMAKE_URL") ]]; then
- curl -sSL ${CMAKE_URL} -o ${CMAKE_INSTALLER}
- CMAKE_DIR="${CMAKE_DEFAULT_DIR:-"${HOME}/tools/cmake-${VERSION}"}"
- mkdir -p ${CMAKE_DIR}
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
- chmod +x ${CMAKE_INSTALLER}
- sudo ./${CMAKE_INSTALLER} --prefix=${CMAKE_DIR} --skip-license
- else # OSX
- mkdir -p ./CMake_tmp
- tar --extract --gzip --file=${CMAKE_INSTALLER} --directory=./CMake_tmp
- mv ./CMake_tmp/*/CMake.app/Contents/* ${CMAKE_DIR}
- fi
- rm --recursive --force ./CMake_tmp ${CMAKE_INSTALLER}
- else echo 'Invalid url!'; echo "Version: ${VERSION}"
- fi
- done
- )
- if [[ ${CMAKE_VERSION:-} && "${TRAVIS_OS_NAME:?}" == "osx" && ! ("${CMAKE_VERSION:-}" =~ .+[' '].+) ]]
- then # Single entry -> default CMake version
- export PATH=${HOME}/tools/cmake-${CMAKE_VERSION:?}/bin:$PATH
- fi
- CMAKE_path=("cmake") # start with installed CMake version
- for VERSION in ${CMAKE_VERSION:-}; do
- tmp_path="$HOME/tools/cmake-${VERSION:?}/bin/cmake"
- if [[ -x "$(command -v ${tmp_path:?})" ]]; then CMAKE_path+=("${tmp_path:?}"); fi
- done
- function test_CMake_generate {
- # $1: cmake or full path to cmake
- shopt -s extglob
- if [[ "$1" == "cmake" || -x "$(command -v $1)" && "$1" =~ .*cmake$ ]]; then
- echo "----------------"
- $1 --version
- echo "Configuration = ${BUILD_TYPE:-Debug}"
- $1 -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} ${CMAKE_GEN_FLAGS[@]:?} ..
- rm -rf !(tests/googletest-*)
- if [[ ! ${BUILD_TYPE:-} ]]; then echo "" && echo "Configuration = Release"
- $1 -DCMAKE_BUILD_TYPE=Release ${CMAKE_GEN_FLAGS[@]:?} ..
- rm -rf !(tests/googletest-*)
- fi
- else echo "Non existing command: $1"
- fi
- }
- - |
- # CMake wrapper (Trusty, Xenial & Bionic); restore default behaviour.
- if [[ "${TRAVIS_OS_NAME:?}" == "linux" &&
- "$(lsb_release --codename)" =~ (trusty|xenial|bionic)$ ]]
- then
- if [[ -x $(command -v /usr/local/bin/cmake) ]]; then
- function cmake { command /usr/local/bin/cmake $@; }
- elif [[ -x $(command -v /usr/bin/cmake) ]]; then
- function cmake { command /usr/bin/cmake $@; }
- fi
- fi
-
- ############################################################################
- # [linux]: Install the right version of libc++
- # Based on https://github.com/ldionne/hana/blob/master/.travis.yml
- ############################################################################
- - |
- 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"
- 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:
- - |
- cd "${TRAVIS_BUILD_DIR:?}"
- mkdir build && cd build
- if [[ ${GSL_CXX_STANDARD:-} ]]; then
- CMAKE_GEN_FLAGS=("-DGSL_CXX_STANDARD=$GSL_CXX_STANDARD")
- fi
- CMAKE_GEN_FLAGS+=("-Wdev -Werror=dev --warn-uninitialized")
-
-script:
- # generate build files
- - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE:?} ${CMAKE_GEN_FLAGS[@]:?}
- # build and run tests
- - cmake --build . -- -j${JOBS}
- - ctest --output-on-failure -j${JOBS}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b59ec7a..5e0d9c0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(guidelineSupportLibrary)
project(GSL
- VERSION 3.1.0
+ VERSION 4.0.0
LANGUAGES CXX
)
diff --git a/README.md b/README.md
index e396057..a0c44f3 100644
--- a/README.md
+++ b/README.md
@@ -30,14 +30,14 @@ not_null | &#x2611; | restricts a pointer / smart po
span | &#x2611; | a view over a contiguous sequence of memory. Based on the standardized verison of `std::span`, however `gsl::span` enforces bounds checking. See the [wiki](https://github.com/microsoft/GSL/wiki/gsl::span-and-std::span) for additional information.
span_p | &#x2610; | spans a range starting from a pointer to the first place for which the predicate is true
basic_zstring | &#x2611; | A pointer to a C-string (zero-terminated array) with a templated char type
-zstring | &#x2611; | An alias to `basic_zstring` with a char type of char
-czstring | &#x2611; | An alias to `basic_zstring` with a char type of const char
-wzstring | &#x2611; | An alias to `basic_zstring` with a char type of wchar_t
-cwzstring | &#x2611; | An alias to `basic_zstring` with a char type of const wchar_t
-u16zstring | &#x2611; | An alias to `basic_zstring` with a char type of char16_t
-cu16zstring | &#x2611; | An alias to `basic_zstring` with a char type of const char16_t
-u32zstring | &#x2611; | An alias to `basic_zstring` with a char type of char32_t
-cu32zstring | &#x2611; | An alias to `basic_zstring` with a char type of const char32_t
+zstring | &#x2611; | An alias to `basic_zstring` with dynamic extent and a char type of char
+czstring | &#x2611; | An alias to `basic_zstring` with dynamic extent and a char type of const char
+wzstring | &#x2611; | An alias to `basic_zstring` with dynamic extent and a char type of wchar_t
+cwzstring | &#x2611; | An alias to `basic_zstring` with dynamic extent and a char type of const wchar_t
+u16zstring | &#x2611; | An alias to `basic_zstring` with dynamic extent and a char type of char16_t
+cu16zstring | &#x2611; | An alias to `basic_zstring` with dynamic extent and a char type of const char16_t
+u32zstring | &#x2611; | An alias to `basic_zstring` with dynamic extent and a char type of char32_t
+cu32zstring | &#x2611; | An alias to `basic_zstring` with dynamic extent and a char type of const char32_t
[**2. Owners**][cg-owners] | |
unique_ptr | &#x2611; | an alias to `std::unique_ptr`
shared_ptr | &#x2611; | an alias to `std::shared_ptr`
@@ -85,17 +85,25 @@ This is based on [CppCoreGuidelines semi-specification](https://github.com/isocp
[cg-concepts]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslconcept-concepts
# Quick Start
-## Supported Compilers
-The GSL officially supports the current and previous major release of MSVC, GCC, Clang, and XCode's Apple-Clang.
-See our latest test results for the most up-to-date list of supported configurations.
+## Supported Compilers / Toolsets
+The GSL officially supports the latest and previous major versions of VS with MSVC & LLVM, GCC, Clang, and XCode with Apple-Clang.
+Within these two major versions, we try to target the latest minor updates / revisions (although this may be affected by
+delays between a toolchain's release and when it becomes widely available for use).
+Below is a table showing the versions currently being tested.
Compiler |Toolset Versions Currently Tested
:------- |--:
- XCode |11.4 & 10.3
- GCC |9 & 8
- Clang |11 & 10
- Visual Studio with MSVC | VS2017 (15.9) & VS2019 (16.4)
- Visual Studio with LLVM | VS2017 (Clang 9) & VS2019 (Clang 10)
+ XCode | 13.2.1 & 12.5.1
+ GCC | 11[^1] & 10[^2]
+ Clang | 12[^2] & 11[^2]
+ Visual Studio with MSVC | VS2022[^3] & VS2019[^4]
+ Visual Studio with LLVM | VS2022[^3] & VS2019[^4]
+
+
+[^1]: Precise version may be found in the [latest CI results](https://dev.azure.com/cppstat/GSL/_build?definitionId=1&branchFilter=26).
+[^2]: Precise version may be found in the [latest CI results](https://dev.azure.com/cppstat/GSL/_build?definitionId=1&branchFilter=26). Should be the version specified [here](https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md#language-and-runtime).
+[^3]: Precise version may be found in the [latest CI results](https://dev.azure.com/cppstat/GSL/_build?definitionId=1&branchFilter=26). Should be the version specified [here](https://github.com/actions/virtual-environments/blob/main/images/win/Windows2022-Readme.md#visual-studio-enterprise-2022).
+[^4]: Precise version may be found in the [latest CI results](https://dev.azure.com/cppstat/GSL/_build?definitionId=1&branchFilter=26). Should be the version specified [here](https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#visual-studio-enterprise-2019).
---
If you successfully port GSL to another platform, we would love to hear from you!
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..869fdfe
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,41 @@
+<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
+
+## Security
+
+Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
+
+If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
+
+## Reporting Security Issues
+
+**Please do not report security vulnerabilities through public GitHub issues.**
+
+Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
+
+If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
+
+You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
+
+Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
+
+ * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
+ * Full paths of source file(s) related to the manifestation of the issue
+ * The location of the affected source code (tag/branch/commit or direct URL)
+ * Any special configuration required to reproduce the issue
+ * Step-by-step instructions to reproduce the issue
+ * Proof-of-concept or exploit code (if possible)
+ * Impact of the issue, including how an attacker might exploit the issue
+
+This information will help us triage your report more quickly.
+
+If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
+
+## Preferred Languages
+
+We prefer all communications to be in English.
+
+## Policy
+
+Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
+
+<!-- END MICROSOFT SECURITY.MD BLOCK -->
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 0d1219a..ba16ee9 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -4,65 +4,63 @@ trigger:
pr:
autoCancel: true
-# GCC
stages:
- stage: GCC
dependsOn: []
- variables:
- - name: CC
- value: gcc
- - name: CXX
- value: g++
jobs:
- template: ./pipelines/jobs.yml
parameters:
- jobName: 'Validate GCC latest'
- imageName: ubuntu-20.04
- - template: ./pipelines/jobs.yml
- parameters:
- jobName: 'Validate GCC Previous'
- imageName: ubuntu-18.04
+ compiler: gcc
+ image: ubuntu-20.04
+ compilerVersions: [ 11, 10 ]
+ setupfile: 'setup_gcc.yml'
-# Clang
- stage: Clang
dependsOn: []
- variables:
- - name: CC
- value: clang
- - name: CXX
- value: clang++
jobs:
- template: ./pipelines/jobs.yml
parameters:
- jobName: 'Validate Clang latest'
- imageName: ubuntu-20.04
+ compiler: clang
+ image: ubuntu-20.04
+ compilerVersions: [ 12, 11 ]
+ setupfile: 'setup_clang.yml'
+
+- stage: Xcode
+ dependsOn: []
+ jobs:
- template: ./pipelines/jobs.yml
parameters:
- jobName: 'Validate Clang Previous'
- imageName: ubuntu-18.04
+ compiler: 'Xcode'
+ image: macOS-11
+ compilerVersions: [ '12.5.1', '13.2.1' ]
+ setupfile: 'setup_apple.yml'
-# MSVC
-- stage: MSVC
+- stage: VS_MSVC
dependsOn: []
jobs:
- template: ./pipelines/jobs.yml
parameters:
- jobName: 'Validate MSVC latest'
- imageName: windows-latest
+ compiler: 'VS2019 (MSVC)'
+ compilerVersions: [ 'default' ]
+ image: windows-2019
- template: ./pipelines/jobs.yml
parameters:
- jobName: 'Validate MSVC Previous'
- imageName: vs2017-win2016
+ compiler: 'VS2022 (MSVC)'
+ compilerVersions: [ 'default' ]
+ image: windows-2022
-# Apple-Clang
-- stage: Apple_Clang
+- stage: VS_LLVM
dependsOn: []
jobs:
- template: ./pipelines/jobs.yml
parameters:
- jobName: 'Validate Apple-Clang latest'
- imageName: macos-10.15
+ compiler: 'VS2019 (LLVM)'
+ compilerVersions: [ 'default' ]
+ image: windows-2019
+ extraCmakeArgs: '-T ClangCL'
- template: ./pipelines/jobs.yml
parameters:
- jobName: 'Validate Apple-Clang Previous'
- imageName: macos-10.14
+ compiler: 'VS2022 (LLVM)'
+ compilerVersions: [ 'default' ]
+ image: windows-2022
+ extraCmakeArgs: '-T ClangCL'
diff --git a/include/gsl/algorithm b/include/gsl/algorithm
index b27475d..584f5cd 100644
--- a/include/gsl/algorithm
+++ b/include/gsl/algorithm
@@ -17,8 +17,8 @@
#ifndef GSL_ALGORITHM_H
#define GSL_ALGORITHM_H
-#include <gsl/assert> // for Expects
-#include <gsl/span> // for dynamic_extent, span
+#include "assert" // for Expects
+#include "span" // for dynamic_extent, span
#include <algorithm> // for copy_n
#include <cstddef> // for ptrdiff_t
diff --git a/include/gsl/assert b/include/gsl/assert
index 0cc54f6..a601204 100644
--- a/include/gsl/assert
+++ b/include/gsl/assert
@@ -22,6 +22,7 @@
// Currently terminate is a no-op in this mode, so we add termination behavior back
//
#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
+#define GSL_KERNEL_MODE
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h>
diff --git a/include/gsl/gsl b/include/gsl/gsl
index adadc40..3d9e288 100644
--- a/include/gsl/gsl
+++ b/include/gsl/gsl
@@ -17,16 +17,16 @@
#ifndef GSL_GSL_H
#define GSL_GSL_H
-#include <gsl/algorithm> // copy
-#include <gsl/assert> // Ensures/Expects
-#include <gsl/byte> // byte
-#include <gsl/pointers> // owner, not_null
-#include <gsl/span> // span
-#include <gsl/string_span> // zstring, string_span, zstring_builder...
-#include <gsl/util> // finally()/narrow_cast()...
+#include "algorithm" // copy
+#include "assert" // Ensures/Expects
+#include "byte" // byte
+#include "pointers" // owner, not_null
+#include "span" // span
+#include "string_span" // zstring, string_span, zstring_builder...
+#include "util" // finally()/narrow_cast()...
#ifdef __cpp_exceptions
-#include <gsl/narrow> // narrow()
+#include "narrow" // narrow()
#endif
#endif // GSL_GSL_H
diff --git a/include/gsl/gsl_algorithm b/include/gsl/gsl_algorithm
index 9f1dd50..951679a 100644
--- a/include/gsl/gsl_algorithm
+++ b/include/gsl/gsl_algorithm
@@ -1,3 +1,4 @@
#pragma once
-#pragma message("This header will soon be removed. Use <gsl/algorithm> instead of <gsl/gsl_algorithm>")
-#include <gsl/algorithm>
+#pragma message( \
+ "This header will soon be removed. Use <gsl/algorithm> instead of <gsl/gsl_algorithm>")
+#include "algorithm"
diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert
index b83a772..222ce30 100644
--- a/include/gsl/gsl_assert
+++ b/include/gsl/gsl_assert
@@ -1,3 +1,3 @@
#pragma once
#pragma message("This header will soon be removed. Use <gsl/assert> instead of <gsl/gsl_assert>")
-#include <gsl/assert>
+#include "assert"
diff --git a/include/gsl/gsl_byte b/include/gsl/gsl_byte
index 4f198ce..831bb2d 100644
--- a/include/gsl/gsl_byte
+++ b/include/gsl/gsl_byte
@@ -1,3 +1,3 @@
#pragma once
#pragma message("This header will soon be removed. Use <gsl/byte> instead of <gsl/gsl_byte>")
-#include <gsl/byte>
+#include "byte"
diff --git a/include/gsl/gsl_narrow b/include/gsl/gsl_narrow
index 6c2cd10..3e3e8cf 100644
--- a/include/gsl/gsl_narrow
+++ b/include/gsl/gsl_narrow
@@ -1,3 +1,3 @@
#pragma once
#pragma message("This header will soon be removed. Use <gsl/narrow> instead of <gsl/gsl_narrow>")
-#include <gsl/narrow>
+#include "narrow"
diff --git a/include/gsl/gsl_util b/include/gsl/gsl_util
index 6a6d77e..a7ed739 100644
--- a/include/gsl/gsl_util
+++ b/include/gsl/gsl_util
@@ -1,3 +1,3 @@
#pragma once
#pragma message("This header will soon be removed. Use <gsl/util> instead of <gsl/gsl_util>")
-#include <gsl/util>
+#include "util"
diff --git a/include/gsl/narrow b/include/gsl/narrow
index d47d9fd..7578c8b 100644
--- a/include/gsl/narrow
+++ b/include/gsl/narrow
@@ -16,8 +16,9 @@
#ifndef GSL_NARROW_H
#define GSL_NARROW_H
-#include <gsl/assert> // for Expects
-#include <gsl/util> // for narrow_cast
+#include "assert" // for GSL_SUPPRESS
+#include "util" // for narrow_cast
+#include <exception> // for std::exception
namespace gsl
{
struct narrowing_error : public std::exception
@@ -26,22 +27,55 @@ struct narrowing_error : public std::exception
};
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
-template <class T, class U>
+template <class T, class U, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
-// clang-format on
+GSL_SUPPRESS(es.46) // NO-FORMAT: attribute // The warning suggests that a floating->unsigned conversion can occur
+ // in the static_cast below, and that gsl::narrow should be used instead.
+ // Suppress this warning, since gsl::narrow is defined in terms of
+ // static_cast
+ // clang-format on
constexpr T narrow(U u) noexcept(false)
{
constexpr const bool is_different_signedness =
(std::is_signed<T>::value != std::is_signed<U>::value);
- const T t = narrow_cast<T>(u);
+GSL_SUPPRESS(es.103) // NO-FORMAT: attribute // don't overflow
+GSL_SUPPRESS(es.104) // NO-FORMAT: attribute // don't underflow
+GSL_SUPPRESS(p.2) // NO-FORMAT: attribute // don't rely on undefined behavior
+ const T t = narrow_cast<T>(u); // While this is technically undefined behavior in some cases (i.e., if the source value is of floating-point type
+ // and cannot fit into the destination integral type), the resultant behavior is benign on the platforms
+ // that we target (i.e., no hardware trap representations are hit).
+#if defined(__clang__) || defined(__GNUC__)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
if (static_cast<U>(t) != u || (is_different_signedness && ((t < T{}) != (u < U{}))))
{
throw narrowing_error{};
}
+#if defined(__clang__) || defined(__GNUC__)
+ #pragma GCC diagnostic pop
+#endif
+
+ return t;
+}
+
+template <class T, class U, typename std::enable_if<!std::is_arithmetic<T>::value>::type* = nullptr>
+// clang-format off
+GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
+ // clang-format on
+ constexpr T narrow(U u) noexcept(false)
+{
+ const T t = narrow_cast<T>(u);
+
+ if (static_cast<U>(t) != u)
+ {
+ throw narrowing_error{};
+ }
return t;
}
diff --git a/include/gsl/pointers b/include/gsl/pointers
index 2f1b15f..a0a77ac 100644
--- a/include/gsl/pointers
+++ b/include/gsl/pointers
@@ -17,7 +17,7 @@
#ifndef GSL_POINTERS_H
#define GSL_POINTERS_H
-#include <gsl/assert> // for Ensures, Expects
+#include "assert" // for Ensures, Expects
#include <algorithm> // for forward
#include <cstddef> // for ptrdiff_t, nullptr_t, size_t
@@ -34,12 +34,19 @@ namespace gsl
namespace details
{
-template<typename T, typename = void>
-struct is_comparable_to_nullptr : std::false_type {};
+ template <typename T, typename = void>
+ struct is_comparable_to_nullptr : std::false_type
+ {
+ };
-template <typename T>
-struct is_comparable_to_nullptr<T, std::enable_if_t<std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value>> : std::true_type {};
-} // namespace details
+ template <typename T>
+ struct is_comparable_to_nullptr<
+ T,
+ std::enable_if_t<std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value>>
+ : std::true_type
+ {
+ };
+} // namespace details
//
// GSL.owner: ownership pointers
diff --git a/include/gsl/span b/include/gsl/span
index 506eb4c..49e1502 100644
--- a/include/gsl/span
+++ b/include/gsl/span
@@ -17,15 +17,21 @@
#ifndef GSL_SPAN_H
#define GSL_SPAN_H
-#include <gsl/assert> // for Expects
-#include <gsl/byte> // for byte
-#include <gsl/util> // for narrow_cast
+#include "assert" // for Expects
+#include "byte" // for byte
+#include "span_ext" // for span specialization of gsl::at and other span-related extensions
+#include "util" // for narrow_cast
#include <array> // for array
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
#include <iterator> // for reverse_iterator, distance, random_access_...
+#include <memory> // for pointer_traits
#include <type_traits> // for enable_if_t, declval, is_convertible, inte...
+#if defined(__has_include) && __has_include(<version>)
+#include <version>
+#endif
+
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
@@ -60,12 +66,6 @@
namespace gsl
{
-// [views.constants], constants
-constexpr const std::size_t dynamic_extent = narrow_cast<std::size_t>(-1);
-
-template <class ElementType, std::size_t Extent = dynamic_extent>
-class span;
-
// implementation details
namespace details
{
@@ -115,6 +115,9 @@ namespace details
class span_iterator
{
public:
+#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts))
+ using iterator_concept = std::contiguous_iterator_tag;
+#endif // __cpp_lib_ranges
using iterator_category = std::random_access_iterator_tag;
using value_type = std::remove_cv_t<Type>;
using difference_type = std::ptrdiff_t;
@@ -334,8 +337,26 @@ namespace details
pointer begin_ = nullptr;
pointer end_ = nullptr;
pointer current_ = nullptr;
+
+ template <typename Ptr>
+ friend struct std::pointer_traits;
};
+}} // namespace gsl::details
+namespace std
+{
+template <class Type>
+struct pointer_traits<::gsl::details::span_iterator<Type>>
+{
+ using pointer = ::gsl::details::span_iterator<Type>;
+ using element_type = Type;
+ using difference_type = ptrdiff_t;
+
+ static constexpr element_type* to_address(const pointer i) noexcept { return i.current_; }
+};
+} // namespace std
+
+namespace gsl { namespace details {
template <std::size_t Ext>
class extent_type
{
@@ -687,14 +708,11 @@ private:
template <class OtherExtentType>
constexpr storage_type(KnownNotNull data, OtherExtentType ext)
: ExtentType(ext), data_(data.p)
- {
- Expects(ExtentType::size() != dynamic_extent);
- }
+ {}
template <class OtherExtentType>
constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
{
- Expects(ExtentType::size() != dynamic_extent);
Expects(data || ExtentType::size() == 0);
}
diff --git a/include/gsl/span_ext b/include/gsl/span_ext
index b7c12cf..516cc99 100644
--- a/include/gsl/span_ext
+++ b/include/gsl/span_ext
@@ -27,16 +27,29 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <gsl/span> // for span
-#include <gsl/util> // for narrow_cast, narrow
+#include "assert" // GSL_KERNEL_MODE
+#include "util" // for narrow_cast, narrow
-#include <algorithm> // for lexicographical_compare
-#include <cstddef> // for ptrdiff_t, size_t
+#include <cstddef> // for ptrdiff_t, size_t
#include <utility>
+#ifndef GSL_KERNEL_MODE
+#include <algorithm> // for lexicographical_compare
+#endif // GSL_KERNEL_MODE
+
namespace gsl
{
+// [span.views.constants], constants
+GSL_INLINE constexpr const std::size_t dynamic_extent = narrow_cast<std::size_t>(-1);
+
+template <class ElementType, std::size_t Extent = dynamic_extent>
+class span;
+
+// std::equal and std::lexicographical_compare are not /kernel compatible
+// so all comparison operators must be removed for kernel mode.
+#ifndef GSL_KERNEL_MODE
+
// [span.comparison], span comparison operators
template <class ElementType, std::size_t FirstExtent, std::size_t SecondExtent>
constexpr bool operator==(span<ElementType, FirstExtent> l, span<ElementType, SecondExtent> r)
@@ -74,6 +87,8 @@ constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent>
return !(l < r);
}
+#endif // GSL_KERNEL_MODE
+
//
// make_span() - Utility functions for creating spans
//
diff --git a/include/gsl/string_span b/include/gsl/string_span
index a76236d..397c561 100644
--- a/include/gsl/string_span
+++ b/include/gsl/string_span
@@ -17,9 +17,9 @@
#ifndef GSL_STRING_SPAN_H
#define GSL_STRING_SPAN_H
-#include <gsl/assert> // for Ensures, Expects
-#include <gsl/span_ext> // for operator!=, operator==, dynamic_extent
-#include <gsl/util> // for narrow_cast
+#include "assert" // for Ensures, Expects
+#include "span_ext" // for operator!=, operator==, dynamic_extent
+#include "util" // for narrow_cast
#include <algorithm> // for equal, lexicographical_compare
#include <array> // for array
@@ -59,29 +59,21 @@ namespace gsl
template <typename CharT, std::size_t Extent = dynamic_extent>
using basic_zstring = CharT*;
-template <std::size_t Extent = dynamic_extent>
-using czstring = basic_zstring<const char, Extent>;
+using czstring = basic_zstring<const char, dynamic_extent>;
-template <std::size_t Extent = dynamic_extent>
-using cwzstring = basic_zstring<const wchar_t, Extent>;
+using cwzstring = basic_zstring<const wchar_t, dynamic_extent>;
-template <std::size_t Extent = dynamic_extent>
-using cu16zstring = basic_zstring<const char16_t, Extent>;
+using cu16zstring = basic_zstring<const char16_t, dynamic_extent>;
-template <std::size_t Extent = dynamic_extent>
-using cu32zstring = basic_zstring<const char32_t, Extent>;
+using cu32zstring = basic_zstring<const char32_t, dynamic_extent>;
-template <std::size_t Extent = dynamic_extent>
-using zstring = basic_zstring<char, Extent>;
+using zstring = basic_zstring<char, dynamic_extent>;
-template <std::size_t Extent = dynamic_extent>
-using wzstring = basic_zstring<wchar_t, Extent>;
+using wzstring = basic_zstring<wchar_t, dynamic_extent>;
-template <std::size_t Extent = dynamic_extent>
-using u16zstring = basic_zstring<char16_t, Extent>;
+using u16zstring = basic_zstring<char16_t, dynamic_extent>;
-template <std::size_t Extent = dynamic_extent>
-using u32zstring = basic_zstring<char32_t, Extent>;
+using u32zstring = basic_zstring<char32_t, dynamic_extent>;
namespace details
{
diff --git a/include/gsl/util b/include/gsl/util
index 8d3f381..db6a85e 100644
--- a/include/gsl/util
+++ b/include/gsl/util
@@ -17,7 +17,7 @@
#ifndef GSL_UTIL_H
#define GSL_UTIL_H
-#include <gsl/assert> // for Expects
+#include "assert" // for Expects
#include <array>
#include <cstddef> // for ptrdiff_t, size_t
@@ -25,6 +25,13 @@
#include <type_traits> // for is_signed, integral_constant
#include <utility> // for exchange, forward
+#if defined(__has_include) && __has_include(<version>)
+#include <version>
+#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
+#include <span>
+#endif // __cpp_lib_span >= 202002L
+#endif //__has_include(<version>)
+
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
@@ -38,6 +45,12 @@
#define GSL_NODISCARD
#endif // defined(__cplusplus) && (__cplusplus >= 201703L)
+#if defined(__cpp_inline_variables)
+#define GSL_INLINE inline
+#else
+#define GSL_INLINE
+#endif
+
namespace gsl
{
//
@@ -81,8 +94,8 @@ GSL_NODISCARD auto finally(F&& f) noexcept
template <class T, class U>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
-// clang-format on
-constexpr T narrow_cast(U&& u) noexcept
+ // clang-format on
+ constexpr T narrow_cast(U&& u) noexcept
{
return static_cast<T>(std::forward<U>(u));
}
@@ -94,7 +107,7 @@ template <class T, std::size_t N>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
-// clang-format on
+ // clang-format on
constexpr T& at(T (&arr)[N], const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(N));
@@ -105,7 +118,7 @@ template <class Cont>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
-// clang-format on
+ // clang-format on
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
@@ -116,13 +129,21 @@ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
template <class T>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
-// clang-format on
-constexpr T at(const std::initializer_list<T> cont, const index i)
+ // clang-format on
+ constexpr T at(const std::initializer_list<T> cont, const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
return *(cont.begin() + i);
}
+#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
+template <class T, size_t extent = std::dynamic_extent>
+constexpr auto at(std::span<T, extent> sp, const index i) -> decltype(sp[sp.size()])
+{
+ Expects(i >= 0 && i < narrow_cast<index>(sp.size()));
+ return sp[gsl::narrow_cast<size_t>(i)];
+}
+#endif // __cpp_lib_span >= 202002L
} // namespace gsl
#if defined(_MSC_VER) && !defined(__clang__)
diff --git a/pipelines/jobs.yml b/pipelines/jobs.yml
index dad2414..aabd3db 100644
--- a/pipelines/jobs.yml
+++ b/pipelines/jobs.yml
@@ -1,26 +1,43 @@
parameters:
- jobName: ''
- imageName: ''
+ CXXVersions: [ 14, 17, 20 ]
+ buildTypes: [ 'Debug', 'Release' ]
+ image: ''
+
+ compiler: ''
+ compilerVersions: ["default"] # if default value, simply uses whatever version is on the machine.
+ # the text of this default value doesn't actually matter.
+ setupfile: ''
+ extraCmakeArgs: ''
jobs:
-- job:
- displayName: ${{ parameters.imageName }}
- pool:
- vmImage: ${{ parameters.imageName }}
- strategy:
- matrix:
- 14_debug:
- GSL_CXX_STANDARD: '14'
- BUILD_TYPE: 'Debug'
- 14_release:
- GSL_CXX_STANDARD: '14'
- BUILD_TYPE: 'Release'
- 17_debug:
- GSL_CXX_STANDARD: '17'
- BUILD_TYPE: 'Debug'
- 17_release:
- GSL_CXX_STANDARD: '17'
- BUILD_TYPE: 'Release'
- continueOnError: false
- steps:
- - template: ./steps.yml
+- ${{ each compilerVersion in parameters.compilerVersions }}:
+ - ${{ each CXXVersion in parameters.CXXVersions }}:
+ - ${{ each buildType in parameters.buildTypes }}:
+ - job:
+ displayName: ${{ format('{0} {1} C++{2} {3}', parameters.compiler, compilerVersion, CXXVersion, buildType) }}
+ pool:
+ vmImage: ${{ parameters.image }}
+ continueOnError: false
+
+ steps:
+ - ${{ if not(eq(parameters.setupfile, '')) }}:
+ - template: ${{ parameters.setupfile }}
+ parameters:
+ version: ${{ compilerVersion }}
+
+ - task: CMake@1
+ name: Configure
+ inputs:
+ workingDirectory: build
+ cmakeArgs: '-DGSL_CXX_STANDARD=${{ CXXVersion }} -DCMAKE_BUILD_TYPE=${{ buildType }} -DCI_TESTING:BOOL=ON -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -Werror=dev ${{ parameters.extraCmakeArgs }} .. '
+
+ - task: CMake@1
+ name: Build
+ inputs:
+ workingDirectory: build
+ cmakeArgs: '--build . '
+
+ - script: ctest . --output-on-failure --no-compress-output
+ name: CTest
+ workingDirectory: build
+ failOnStderr: true
diff --git a/pipelines/setup_apple.yml b/pipelines/setup_apple.yml
new file mode 100644
index 0000000..6a256a5
--- /dev/null
+++ b/pipelines/setup_apple.yml
@@ -0,0 +1,9 @@
+parameters:
+ version: 0
+
+steps:
+ - script: |
+ if [ "${{ parameters.version }}" != "default" ]; then sudo xcode-select -switch /Applications/Xcode_${{ parameters.version }}.app; fi
+
+ displayName: "Setup Xcode Version"
+ failOnStderr: true
diff --git a/pipelines/setup_clang.yml b/pipelines/setup_clang.yml
new file mode 100644
index 0000000..58403b4
--- /dev/null
+++ b/pipelines/setup_clang.yml
@@ -0,0 +1,13 @@
+parameters:
+ version: 0
+
+steps:
+ - script: |
+ echo "##vso[task.setvariable variable=CXX;]${CXX}"
+ echo "##vso[task.setvariable variable=CC;]${CC}"
+
+ displayName: "Setup Clang Version"
+ failOnStderr: true
+ env:
+ CC: clang-${{ parameters.version }}
+ CXX: clang++-${{ parameters.version }}
diff --git a/pipelines/setup_gcc.yml b/pipelines/setup_gcc.yml
new file mode 100644
index 0000000..6480f67
--- /dev/null
+++ b/pipelines/setup_gcc.yml
@@ -0,0 +1,14 @@
+parameters:
+ version: 0
+
+steps:
+ - script: |
+ echo "##vso[task.setvariable variable=CXX;]${CXX}"
+ echo "##vso[task.setvariable variable=CC;]${CC}"
+ if [ "${{ parameters.version }}" = "11" ]; then sudo apt-get install $CXX; fi
+
+ displayName: "Setup GCC Version"
+ failOnStderr: true
+ env:
+ CC: gcc-${{ parameters.version }}
+ CXX: g++-${{ parameters.version }}
diff --git a/pipelines/steps.yml b/pipelines/steps.yml
index 41a7fca..e69de29 100644
--- a/pipelines/steps.yml
+++ b/pipelines/steps.yml
@@ -1,17 +0,0 @@
-steps:
- - task: CMake@1
- name: Configure
- inputs:
- workingDirectory: build
- cmakeArgs: '-DCMAKE_CXX_STANDARD=$(GSL_CXX_STANDARD) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -Werror=dev .. '
-
- - task: CMake@1
- name: Build
- inputs:
- workingDirectory: build
- cmakeArgs: '--build . '
-
- - script: ctest . --output-on-failure --no-compress-output
- name: CTest
- workingDirectory: build
- failOnStderr: true
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 368ce75..68e18ec 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -9,8 +9,12 @@ include(ExternalProject)
# will make visual studio generated project group files
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+if(CI_TESTING AND GSL_CXX_STANDARD EQUAL 20)
+ add_compile_definitions(FORCE_STD_SPAN_TESTS=1)
+endif()
+
if(IOS)
- add_compile_definitions(GTEST_HAS_DEATH_TEST=1)
+ add_compile_definitions(GTEST_HAS_DEATH_TEST=1 IOS_PROCESS_DELAY_WORKAROUND=1)
endif()
pkg_search_module(GTestMain gtest_main)
@@ -54,10 +58,11 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
find_package(Microsoft.GSL REQUIRED)
endif()
-if (MSVC AND (GSL_CXX_STANDARD EQUAL 17))
+if (MSVC AND (GSL_CXX_STANDARD GREATER_EQUAL 17))
set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-)
endif()
+include(CheckCXXCompilerFlag)
# this interface adds compile options to how the tests are run
# please try to keep entries ordered =)
add_library(gsl_tests_config INTERFACE)
@@ -84,6 +89,7 @@ if(MSVC) # MSVC or simulating MSVC
>
$<$<CXX_COMPILER_ID:Clang>:
-Weverything
+ -Wfloat-equal
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-covered-switch-default # GTest
@@ -101,6 +107,10 @@ if(MSVC) # MSVC or simulating MSVC
>
>
)
+ check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID)
+ if (WARN_RESERVED_ID)
+ target_compile_options(gsl_tests_config INTERFACE "-Wno-reserved-identifier")
+ endif()
else()
target_compile_options(gsl_tests_config INTERFACE
-fno-strict-aliasing
@@ -113,6 +123,7 @@ else()
-Wpedantic
-Wshadow
-Wsign-conversion
+ -Wfloat-equal
-Wno-deprecated-declarations # Allow tests for [[deprecated]] elements
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Weverything
@@ -135,6 +146,11 @@ else()
$<$<AND:$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,4.99>,$<VERSION_LESS:$<CXX_COMPILER_VERSION>,6>>:
$<$<EQUAL:${GSL_CXX_STANDARD},17>:-Wno-undefined-func-template>
>
+ $<$<AND:$<EQUAL:${GSL_CXX_STANDARD},20>,$<OR:$<CXX_COMPILER_VERSION:11.0.0>,$<CXX_COMPILER_VERSION:10.0.0>>>:
+ -Wno-zero-as-null-pointer-constant # failing Clang Ubuntu 20.04 tests, seems to be a bug with clang 10.0.0
+ # and clang 11.0.0. (operator< is being re-written by the compiler
+ # as operator<=> and raising the warning)
+ >
>
$<$<CXX_COMPILER_ID:AppleClang>:
$<$<AND:$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,9.1>,$<VERSION_LESS:$<CXX_COMPILER_VERSION>,10>>:
@@ -164,36 +180,27 @@ target_include_directories(gsl_tests_config SYSTEM INTERFACE
googletest/googletest/include
)
-set_property(TARGET PROPERTY FOLDER "GSL_tests")
-
-function(add_gsl_test name)
- add_executable(${name} ${name}.cpp)
- target_link_libraries(${name}
- Microsoft.GSL::GSL
- gsl_tests_config
- ${GTestMain_LIBRARIES}
- )
- add_test(
- ${name}
- ${name}
- )
- # group all tests under GSL_tests
- set_property(TARGET ${name} PROPERTY FOLDER "GSL_tests")
-endfunction()
-
-add_gsl_test(span_tests)
-add_gsl_test(span_ext_tests)
-add_gsl_test(span_compatibility_tests)
-add_gsl_test(string_span_tests)
-add_gsl_test(at_tests)
-add_gsl_test(notnull_tests)
-add_gsl_test(assertion_tests)
-add_gsl_test(utils_tests)
-add_gsl_test(owner_tests)
-add_gsl_test(byte_tests)
-add_gsl_test(algorithm_tests)
-add_gsl_test(strict_notnull_tests)
+add_executable(gsl_tests
+ algorithm_tests.cpp
+ assertion_tests.cpp
+ at_tests.cpp
+ byte_tests.cpp
+ notnull_tests.cpp
+ owner_tests.cpp
+ span_compatibility_tests.cpp
+ span_ext_tests.cpp
+ span_tests.cpp
+ strict_notnull_tests.cpp
+ string_span_tests.cpp
+ utils_tests.cpp
+)
+target_link_libraries(gsl_tests
+ Microsoft.GSL::GSL
+ gsl_tests_config
+ ${GTestMain_LIBRARIES}
+)
+add_test(gsl_tests gsl_tests)
# No exception tests
@@ -222,12 +229,17 @@ if(MSVC) # MSVC or simulating MSVC
>
$<$<CXX_COMPILER_ID:Clang>:
-Weverything
+ -Wfloat-equal
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-missing-prototypes
-Wno-unknown-attributes
>
)
+ check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID)
+ if (WARN_RESERVED_ID)
+ target_compile_options(gsl_tests_config_noexcept INTERFACE "-Wno-reserved-identifier")
+ endif()
else()
target_compile_options(gsl_tests_config_noexcept INTERFACE
-fno-exceptions
@@ -241,6 +253,7 @@ else()
-Wpedantic
-Wshadow
-Wsign-conversion
+ -Wfloat-equal
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Weverything
-Wno-c++98-compat
@@ -268,19 +281,9 @@ else()
)
endif(MSVC)
-function(add_gsl_test_noexcept name)
- add_executable(${name} ${name}.cpp)
- target_link_libraries(${name}
- Microsoft.GSL::GSL
- gsl_tests_config_noexcept
- ${GTestMain_LIBRARIES}
- )
- 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_ensure_tests)
+add_executable(gsl_noexcept_tests no_exception_ensure_tests.cpp)
+target_link_libraries(gsl_noexcept_tests
+ Microsoft.GSL::GSL
+ gsl_tests_config_noexcept
+)
+add_test(gsl_noexcept_tests gsl_noexcept_tests)
diff --git a/tests/CMakeLists.txt.in b/tests/CMakeLists.txt.in
index 1b10044..2535f8f 100644
--- a/tests/CMakeLists.txt.in
+++ b/tests/CMakeLists.txt.in
@@ -4,7 +4,7 @@ project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG 389cb68b87193358358ae87cc56d257fd0d80189
+ GIT_TAG 1b18723e874b256c1e39378c6774a90701d70f7a
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
diff --git a/tests/algorithm_tests.cpp b/tests/algorithm_tests.cpp
index 0f209ac..e369be0 100644
--- a/tests/algorithm_tests.cpp
+++ b/tests/algorithm_tests.cpp
@@ -14,23 +14,19 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <gtest/gtest.h>
+#include <array> // for array
+#include <cstddef> // for size_t
#include <gsl/algorithm> // for copy
-#include <gsl/span> // for span
-#include <array> // for array
-#include <cstddef> // for size_t
+#include <gsl/span> // for span
+#include <gtest/gtest.h>
-namespace
-{
- static constexpr char deathstring[] = "Expected Death";
-}
+#include "deathTestCommon.h"
namespace gsl
{
struct fail_fast;
} // namespace gsl
-using namespace std;
using namespace gsl;
TEST(algorithm_tests, same_type)
@@ -76,8 +72,8 @@ TEST(algorithm_tests, same_type)
std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{};
- const span<int> src_span(src);
- const span<int, 10> dst_span(dst);
+ const gsl::span<int> src_span(src);
+ const gsl::span<int, 10> dst_span(dst);
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
@@ -204,10 +200,11 @@ TEST(algorithm_tests, incompatible_type)
TEST(algorithm_tests, small_destination_span)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. small_destination_span";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
std::array<int, 12> src{1, 2, 3, 4};
std::array<int, 4> dst{};
@@ -217,9 +214,9 @@ TEST(algorithm_tests, small_destination_span)
const span<int> dst_span_dyn(dst);
const span<int, 4> dst_span_static(dst);
- EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), deathstring);
- EXPECT_DEATH(copy(src_span_dyn, dst_span_static), deathstring);
- EXPECT_DEATH(copy(src_span_static, dst_span_dyn), deathstring);
+ EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), expected);
+ EXPECT_DEATH(copy(src_span_dyn, dst_span_static), expected);
+ EXPECT_DEATH(copy(src_span_static, dst_span_dyn), expected);
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);
diff --git a/tests/assertion_tests.cpp b/tests/assertion_tests.cpp
index 6b5fb0b..dd3ca06 100644
--- a/tests/assertion_tests.cpp
+++ b/tests/assertion_tests.cpp
@@ -14,14 +14,14 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <gtest/gtest.h>
+#include "deathTestCommon.h"
#include <gsl/assert> // for fail_fast (ptr only), Ensures, Expects
+#include <gtest/gtest.h>
using namespace gsl;
namespace
{
-static constexpr char deathstring[] = "Expected Death";
int f(int i)
{
@@ -39,23 +39,22 @@ int g(int i)
TEST(assertion_tests, expects)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. expects";
std::abort();
});
EXPECT_TRUE(f(2) == 2);
- EXPECT_DEATH(f(10), deathstring);
+ EXPECT_DEATH(f(10), GetExpectedDeathString(terminateHandler));
}
-
TEST(assertion_tests, ensures)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. ensures";
std::abort();
});
EXPECT_TRUE(g(2) == 3);
- EXPECT_DEATH(g(9), deathstring);
+ EXPECT_DEATH(g(9), GetExpectedDeathString(terminateHandler));
}
diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp
index 1285139..93e6b7b 100644
--- a/tests/at_tests.cpp
+++ b/tests/at_tests.cpp
@@ -22,31 +22,33 @@
#include <cstddef> // for size_t
#include <initializer_list> // for initializer_list
#include <vector> // for vector
+#if defined(__cplusplus) && __cplusplus >= 202002L
+#include <span>
+#endif // __cplusplus >= 202002L
-namespace
-{
- static constexpr char deathstring[] = "Expected Death";
-}
+#include "deathTestCommon.h"
TEST(at_tests, static_array)
{
int a[4] = {1, 2, 3, 4};
const int(&c_a)[4] = a;
- for (int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; ++i)
+ {
EXPECT_TRUE(&gsl::at(a, i) == &a[i]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[i]);
}
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. static_array";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
- EXPECT_DEATH(gsl::at(a, -1), deathstring);
- EXPECT_DEATH(gsl::at(a, 4), deathstring);
- EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
- EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
+ EXPECT_DEATH(gsl::at(a, -1), expected);
+ EXPECT_DEATH(gsl::at(a, 4), expected);
+ EXPECT_DEATH(gsl::at(c_a, -1), expected);
+ EXPECT_DEATH(gsl::at(c_a, 4), expected);
}
TEST(at_tests, std_array)
@@ -54,20 +56,22 @@ TEST(at_tests, std_array)
std::array<int, 4> a = {1, 2, 3, 4};
const std::array<int, 4>& c_a = a;
- for (int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; ++i)
+ {
EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]);
}
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. std_array";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
- EXPECT_DEATH(gsl::at(a, -1), deathstring);
- EXPECT_DEATH(gsl::at(a, 4), deathstring);
- EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
- EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
+ EXPECT_DEATH(gsl::at(a, -1), expected);
+ EXPECT_DEATH(gsl::at(a, 4), expected);
+ EXPECT_DEATH(gsl::at(c_a, -1), expected);
+ EXPECT_DEATH(gsl::at(c_a, 4), expected);
}
TEST(at_tests, std_vector)
@@ -75,41 +79,73 @@ TEST(at_tests, std_vector)
std::vector<int> a = {1, 2, 3, 4};
const std::vector<int>& c_a = a;
- for (int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; ++i)
+ {
EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]);
}
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. std_vector";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
- EXPECT_DEATH(gsl::at(a, -1), deathstring);
- EXPECT_DEATH(gsl::at(a, 4), deathstring);
- EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
- EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
+ EXPECT_DEATH(gsl::at(a, -1), expected);
+ EXPECT_DEATH(gsl::at(a, 4), expected);
+ EXPECT_DEATH(gsl::at(c_a, -1), expected);
+ EXPECT_DEATH(gsl::at(c_a, 4), expected);
}
TEST(at_tests, InitializerList)
{
const std::initializer_list<int> a = {1, 2, 3, 4};
- for (int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; ++i)
+ {
EXPECT_TRUE(gsl::at(a, i) == i + 1);
EXPECT_TRUE(gsl::at({1, 2, 3, 4}, i) == i + 1);
}
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. InitializerList";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
+
+ EXPECT_DEATH(gsl::at(a, -1), expected);
+ EXPECT_DEATH(gsl::at(a, 4), expected);
+ EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), expected);
+ EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), expected);
+}
+
+#if defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
+TEST(at_tests, std_span)
+{
+ std::vector<int> vec{1, 2, 3, 4, 5};
+ std::span sp{vec};
+
+ std::vector<int> cvec{1, 2, 3, 4, 5};
+ std::span csp{cvec};
+
+ for (gsl::index i = 0; i < gsl::narrow_cast<gsl::index>(vec.size()); ++i)
+ {
+ EXPECT_TRUE(&gsl::at(sp, i) == &vec[gsl::narrow_cast<size_t>(i)]);
+ EXPECT_TRUE(&gsl::at(csp, i) == &cvec[gsl::narrow_cast<size_t>(i)]);
+ }
+
+ const auto terminateHandler = std::set_terminate([] {
+ std::cerr << "Expected Death. std_span";
+ std::abort();
+ });
+ const auto expected = GetExpectedDeathString(terminateHandler);
- EXPECT_DEATH(gsl::at(a, -1), deathstring);
- EXPECT_DEATH(gsl::at(a, 4), deathstring);
- EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), deathstring);
- EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), deathstring);
+ EXPECT_DEATH(gsl::at(sp, -1), expected);
+ EXPECT_DEATH(gsl::at(sp, gsl::narrow_cast<gsl::index>(sp.size())), expected);
+ EXPECT_DEATH(gsl::at(csp, -1), expected);
+ EXPECT_DEATH(gsl::at(csp, gsl::narrow_cast<gsl::index>(sp.size())), expected);
}
+#endif // defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910
static constexpr bool test_constexpr()
@@ -119,7 +155,8 @@ static constexpr bool test_constexpr()
std::array<int, 4> a2 = {1, 2, 3, 4};
const std::array<int, 4>& c_a2 = a2;
- for (int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; ++i)
+ {
if (&gsl::at(a1, i) != &a1[i]) return false;
if (&gsl::at(c_a1, i) != &a1[i]) return false;
// requires C++17:
diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp
index 2a86cac..4432fc9 100644
--- a/tests/byte_tests.cpp
+++ b/tests/byte_tests.cpp
@@ -37,7 +37,9 @@ TEST(byte_tests, construction)
EXPECT_TRUE(static_cast<unsigned char>(b) == 4);
}
+ // clang-format off
GSL_SUPPRESS(es.49)
+ // clang-format on
{
const byte b = byte(12);
EXPECT_TRUE(static_cast<unsigned char>(b) == 12);
@@ -55,7 +57,7 @@ TEST(byte_tests, construction)
#if defined(__cplusplus) && (__cplusplus >= 201703L)
{
- const byte b { 14 };
+ const byte b{14};
EXPECT_TRUE(static_cast<unsigned char>(b) == 14);
}
#endif
@@ -122,7 +124,7 @@ TEST(byte_tests, aliasing)
EXPECT_TRUE(res == i);
}
-}
+} // namespace
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);
diff --git a/tests/deathTestCommon.h b/tests/deathTestCommon.h
new file mode 100644
index 0000000..7bf2423
--- /dev/null
+++ b/tests/deathTestCommon.h
@@ -0,0 +1,11 @@
+#pragma once
+#include <gsl/assert>
+
+constexpr char deathstring[] = "Expected Death";
+constexpr char failed_set_terminate_deathstring[] = ".*";
+
+// This prevents a failed call to set_terminate from failing the test suite.
+constexpr const char* GetExpectedDeathString(std::terminate_handler handle)
+{
+ return handle ? deathstring : failed_set_terminate_deathstring;
+}
diff --git a/tests/no_exception_ensure_tests.cpp b/tests/no_exception_ensure_tests.cpp
index 2ec0ebb..5fde41c 100644
--- a/tests/no_exception_ensure_tests.cpp
+++ b/tests/no_exception_ensure_tests.cpp
@@ -14,8 +14,11 @@
//
///////////////////////////////////////////////////////////////////////////////
+#include <chrono>
#include <cstdlib> // for std::exit
#include <gsl/span> // for span
+#include <iostream>
+#include <thread>
int operator_subscript_no_throw() noexcept
{
@@ -42,6 +45,10 @@ void setup_termination_handler() noexcept
int main() noexcept
{
+ std::cout << "Running main() from " __FILE__ "\n";
+#if defined(IOS_PROCESS_DELAY_WORKAROUND)
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+#endif
setup_termination_handler();
operator_subscript_no_throw();
return -1;
diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp
index b95bb01..db22c72 100644
--- a/tests/notnull_tests.cpp
+++ b/tests/notnull_tests.cpp
@@ -25,13 +25,9 @@
#include <string> // for basic_string, operator==, string, operator<<
#include <typeinfo> // for type_info
+#include "deathTestCommon.h"
using namespace gsl;
-namespace
-{
-static constexpr char deathstring[] = "Expected Death";
-} //namespace
-
struct MyBase
{
};
@@ -64,7 +60,9 @@ struct CustomPtr
template <typename T, typename U>
std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
+ // clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ // clang-format on
return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -72,7 +70,9 @@ 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)
{
+ // clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ // clang-format on
return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -80,7 +80,9 @@ 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)
{
+ // clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ // clang-format on
return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -88,7 +90,9 @@ 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)
{
+ // clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ // clang-format on
return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -96,7 +100,9 @@ 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)
{
+ // clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ // clang-format on
return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -104,7 +110,9 @@ 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)
{
+ // clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+ // clang-format on
return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@@ -118,12 +126,19 @@ struct NonCopyableNonMovable
NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete;
};
-GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+namespace
+{
+// clang-format off
+GSL_SUPPRESS(f .4) // NO-FORMAT: attribute
+// clang-format on
bool helper(not_null<int*> p) { return *p == 12; }
-GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+// clang-format off
+GSL_SUPPRESS(f .4) // NO-FORMAT: attribute
+// clang-format on
bool helper_const(not_null<const int*> p) { return *p == 12; }
int* return_pointer() { return nullptr; }
+} // namespace
TEST(notnull_tests, TestNotNullConstructors)
{
@@ -142,10 +157,12 @@ TEST(notnull_tests, TestNotNullConstructors)
#endif
}
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullConstructors";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
+
{
// from shared pointer
int i = 12;
@@ -157,7 +174,7 @@ TEST(notnull_tests, TestNotNullConstructors)
std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
int* pi = nullptr;
- EXPECT_DEATH((not_null<decltype(pi)>(pi)), deathstring);
+ EXPECT_DEATH((not_null<decltype(pi)>(pi)), expected);
}
{
@@ -214,8 +231,8 @@ TEST(notnull_tests, TestNotNullConstructors)
{
// from returned pointer
- EXPECT_DEATH(helper(return_pointer()), deathstring);
- EXPECT_DEATH(helper_const(return_pointer()), deathstring);
+ EXPECT_DEATH(helper(return_pointer()), expected);
+ EXPECT_DEATH(helper_const(return_pointer()), expected);
}
}
@@ -275,17 +292,18 @@ TEST(notnull_tests, TestNotNullCasting)
TEST(notnull_tests, TestNotNullAssignment)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullAssignmentd";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
int i = 12;
not_null<int*> p(&i);
EXPECT_TRUE(helper(p));
int* q = nullptr;
- EXPECT_DEATH(p = not_null<int*>(q), deathstring);
+ EXPECT_DEATH(p = not_null<int*>(q), expected);
}
TEST(notnull_tests, TestNotNullRawPointerComparison)
@@ -434,17 +452,18 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
EXPECT_TRUE(*x == 42);
}
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullConstructorTypeDeduction";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
{
auto workaround_macro = []() {
int* p1 = nullptr;
const not_null x{p1};
};
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
{
@@ -452,14 +471,14 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
const int* p1 = nullptr;
const not_null x{p1};
};
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
{
int* p = nullptr;
- EXPECT_DEATH(helper(not_null{p}), deathstring);
- EXPECT_DEATH(helper_const(not_null{p}), deathstring);
+ EXPECT_DEATH(helper(not_null{p}), expected);
+ EXPECT_DEATH(helper_const(not_null{p}), expected);
}
#ifdef CONFIRM_COMPILATION_ERRORS
@@ -495,10 +514,11 @@ TEST(notnull_tests, TestMakeNotNull)
EXPECT_TRUE(*x == 42);
}
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestMakeNotNull";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
{
const auto workaround_macro = []() {
@@ -506,7 +526,7 @@ TEST(notnull_tests, TestMakeNotNull)
const auto x = make_not_null(p1);
EXPECT_TRUE(*x == 42);
};
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
{
@@ -515,21 +535,21 @@ TEST(notnull_tests, TestMakeNotNull)
const auto x = make_not_null(p1);
EXPECT_TRUE(*x == 42);
};
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
{
int* p = nullptr;
- EXPECT_DEATH(helper(make_not_null(p)), deathstring);
- EXPECT_DEATH(helper_const(make_not_null(p)), deathstring);
+ EXPECT_DEATH(helper(make_not_null(p)), expected);
+ EXPECT_DEATH(helper_const(make_not_null(p)), expected);
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
- EXPECT_DEATH(make_not_null(nullptr), deathstring);
- EXPECT_DEATH(helper(make_not_null(nullptr)), deathstring);
- EXPECT_DEATH(helper_const(make_not_null(nullptr)), deathstring);
+ EXPECT_DEATH(make_not_null(nullptr), expected);
+ EXPECT_DEATH(helper(make_not_null(nullptr)), expected);
+ EXPECT_DEATH(helper_const(make_not_null(nullptr)), expected);
}
#endif
}
diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp
index ca8222f..87c7cec 100644
--- a/tests/owner_tests.cpp
+++ b/tests/owner_tests.cpp
@@ -20,7 +20,7 @@
using namespace gsl;
-GSL_SUPPRESS(f.23) // NO-FORMAT: attribute
+GSL_SUPPRESS(f .23) // NO-FORMAT: attribute
void f(int* i) { *i += 1; }
TEST(owner_tests, basic_test)
@@ -34,10 +34,10 @@ TEST(owner_tests, basic_test)
TEST(owner_tests, check_pointer_constraint)
{
- #ifdef CONFIRM_COMPILATION_ERRORS
+#ifdef CONFIRM_COMPILATION_ERRORS
{
owner<int> integerTest = 10;
owner<std::shared_ptr<int>> sharedPtrTest(new int(10));
}
- #endif
+#endif
}
diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp
index 361db84..95d8223 100644
--- a/tests/span_compatibility_tests.cpp
+++ b/tests/span_compatibility_tests.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <gsl/byte> // for byte
-#include <gsl/span> // for span, span_iterator, operator==, operator!=
+#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <array> // for array
#include <cstddef> // for ptrdiff_t
@@ -55,14 +55,14 @@ void ArrayConvertibilityCheck()
EXPECT_TRUE(sp_const_nullptr_1.data() == stl_nullptr.data());
EXPECT_TRUE(sp_const_nullptr_1.size() == 3);
- span<const T* const> sp_const_nullptr_2{std::as_const(stl_nullptr)};
+ gsl::span<const T* const> sp_const_nullptr_2{std::as_const(stl_nullptr)};
EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data());
EXPECT_TRUE(sp_const_nullptr_2.size() == 3);
- static_assert(std::is_same<decltype(span{stl_nullptr}), span<T*, 3>>::value,
+ static_assert(std::is_same<decltype(gsl::span{stl_nullptr}), gsl::span<T*, 3>>::value,
"std::is_same< decltype(span{stl_nullptr}), span<T*, 3>>::value");
static_assert(
- std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<T* const, 3>>::value,
+ std::is_same<decltype(gsl::span{std::as_const(stl_nullptr)}), gsl::span<T* const, 3>>::value,
"std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<T* const, "
"3>>::value");
}
diff --git a/tests/span_ext_tests.cpp b/tests/span_ext_tests.cpp
index 4f07188..3d35f8f 100644
--- a/tests/span_ext_tests.cpp
+++ b/tests/span_ext_tests.cpp
@@ -16,27 +16,26 @@
#include <gtest/gtest.h>
+#include <gsl/span> // for span and span_ext
#include <gsl/util> // for narrow_cast, at
-#include <gsl/span_ext> // for operator==, operator!=, make_span
-#include <array> // for array
-#include <iostream> // for cerr
-#include <vector> // for vector
+#include <array> // for array
+#include <iostream> // for cerr
+#include <vector> // for vector
using namespace std;
using namespace gsl;
-namespace
-{
-static constexpr char deathstring[] = "Expected Death";
-} // namespace
+#include "deathTestCommon.h"
TEST(span_ext_test, make_span_from_pointer_length_constructor)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. from_pointer_length_constructor";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
+
int arr[4] = {1, 2, 3, 4};
{
@@ -49,7 +48,7 @@ TEST(span_ext_test, make_span_from_pointer_length_constructor)
{
int* p = nullptr;
- auto s = make_span(p, narrow_cast<span<int>::size_type>(0));
+ auto s = make_span(p, narrow_cast<gsl::span<int>::size_type>(0));
EXPECT_TRUE(s.size() == 0);
EXPECT_TRUE(s.data() == nullptr);
}
@@ -57,7 +56,7 @@ TEST(span_ext_test, make_span_from_pointer_length_constructor)
{
int* p = nullptr;
auto workaround_macro = [=]() { make_span(p, 2); };
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
}
@@ -88,273 +87,275 @@ TEST(span_ext_test, make_span_from_pointer_pointer_construction)
}
TEST(span_ext_test, make_span_from_array_constructor)
- {
- int arr[5] = {1, 2, 3, 4, 5};
- int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
- int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
-
- {
- const auto s = make_span(arr);
- EXPECT_TRUE(s.size() == 5);
- EXPECT_TRUE(s.data() == std::addressof(arr[0]));
- }
-
- {
- const auto s = make_span(std::addressof(arr2d[0]), 1);
- EXPECT_TRUE(s.size() == 1);
- EXPECT_TRUE(s.data() == std::addressof(arr2d[0]));
- }
-
- {
- const auto s = make_span(std::addressof(arr3d[0]), 1);
- EXPECT_TRUE(s.size() == 1);
- EXPECT_TRUE(s.data() == std::addressof(arr3d[0]));
- }
- }
-
- TEST(span_ext_test, make_span_from_dynamic_array_constructor)
- {
- double(*arr)[3][4] = new double[100][3][4];
-
- {
- auto s = make_span(&arr[0][0][0], 10);
- EXPECT_TRUE(s.size() == 10);
- EXPECT_TRUE(s.data() == &arr[0][0][0]);
- }
-
- delete[] arr;
- }
-
- TEST(span_ext_test, make_span_from_std_array_constructor)
- {
- std::array<int, 4> arr = {1, 2, 3, 4};
-
- {
- auto s = make_span(arr);
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
- }
-
- // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590
- {
- span<int> s1 = make_span(arr);
-
- static span<int> s2;
- s2 = s1;
-
- #if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \
- __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__)
- // Known to be broken in gcc 6.4 and 6.5 with optimizations
- // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116
- EXPECT_TRUE(s1.size() == 4);
- EXPECT_TRUE(s2.size() == 0);
- #else
- EXPECT_TRUE(s1.size() == s2.size());
- #endif
- }
- }
-
- TEST(span_ext_test, make_span_from_const_std_array_constructor)
- {
- const std::array<int, 4> arr = {1, 2, 3, 4};
-
- {
- auto s = make_span(arr);
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
- }
- }
-
- TEST(span_ext_test, make_span_from_std_array_const_constructor)
- {
- std::array<const int, 4> arr = {1, 2, 3, 4};
-
- {
- auto s = make_span(arr);
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
- }
- }
-
- TEST(span_ext_test, make_span_from_container_constructor)
- {
- std::vector<int> v = {1, 2, 3};
- const std::vector<int> cv = v;
-
- {
- auto s = make_span(v);
- EXPECT_TRUE(s.size() == v.size());
- EXPECT_TRUE(s.data() == v.data());
-
- auto cs = make_span(cv);
- EXPECT_TRUE(cs.size() == cv.size());
- EXPECT_TRUE(cs.data() == cv.data());
- }
- }
-
- TEST(span_test, interop_with_gsl_at)
- {
- int arr[5] = {1, 2, 3, 4, 5};
- span<int> s{arr};
- EXPECT_TRUE(at(s, 0) == 1);
- EXPECT_TRUE(at(s, 1) == 2);
- }
-
- TEST(span_ext_test, iterator_free_functions)
- {
- int a[] = {1, 2, 3, 4};
- span<int> s{a};
-
- EXPECT_TRUE((std::is_same<decltype(s.begin()), decltype(begin(s))>::value));
- EXPECT_TRUE((std::is_same<decltype(s.end()), decltype(end(s))>::value));
-
- EXPECT_TRUE((std::is_same<decltype(std::cbegin(s)), decltype(cbegin(s))>::value));
- EXPECT_TRUE((std::is_same<decltype(std::cend(s)), decltype(cend(s))>::value));
-
- EXPECT_TRUE((std::is_same<decltype(s.rbegin()), decltype(rbegin(s))>::value));
- EXPECT_TRUE((std::is_same<decltype(s.rend()), decltype(rend(s))>::value));
-
- EXPECT_TRUE((std::is_same<decltype(std::crbegin(s)), decltype(crbegin(s))>::value));
- EXPECT_TRUE((std::is_same<decltype(std::crend(s)), decltype(crend(s))>::value));
-
- EXPECT_TRUE(s.begin() == begin(s));
- EXPECT_TRUE(s.end() == end(s));
-
- EXPECT_TRUE(s.rbegin() == rbegin(s));
- EXPECT_TRUE(s.rend() == rend(s));
-
- EXPECT_TRUE(s.begin() == cbegin(s));
- EXPECT_TRUE(s.end() == cend(s));
-
- EXPECT_TRUE(s.rbegin() == crbegin(s));
- EXPECT_TRUE(s.rend() == crend(s));
- }
-
- TEST(span_ext_test, ssize_free_function)
- {
- int a[] = {1, 2, 3, 4};
- span<int> s{a};
-
- EXPECT_FALSE((std::is_same<decltype(s.size()), decltype(ssize(s))>::value));
- EXPECT_TRUE(s.size() == static_cast<std::size_t>(ssize(s)));
- }
-
- TEST(span_ext_test, comparison_operators)
- {
- {
- span<int> s1;
- span<int> s2;
- EXPECT_TRUE(s1 == s2);
- EXPECT_FALSE(s1 != s2);
- EXPECT_FALSE(s1 < s2);
- EXPECT_TRUE(s1 <= s2);
- EXPECT_FALSE(s1 > s2);
- EXPECT_TRUE(s1 >= s2);
- EXPECT_TRUE(s2 == s1);
- EXPECT_FALSE(s2 != s1);
- EXPECT_FALSE(s2 != s1);
- EXPECT_TRUE(s2 <= s1);
- EXPECT_FALSE(s2 > s1);
- EXPECT_TRUE(s2 >= s1);
- }
-
- {
- int arr[] = {2, 1};
- span<int> s1 = arr;
- span<int> s2 = arr;
-
- EXPECT_TRUE(s1 == s2);
- EXPECT_FALSE(s1 != s2);
- EXPECT_FALSE(s1 < s2);
- EXPECT_TRUE(s1 <= s2);
- EXPECT_FALSE(s1 > s2);
- EXPECT_TRUE(s1 >= s2);
- EXPECT_TRUE(s2 == s1);
- EXPECT_FALSE(s2 != s1);
- EXPECT_FALSE(s2 < s1);
- EXPECT_TRUE(s2 <= s1);
- EXPECT_FALSE(s2 > s1);
- EXPECT_TRUE(s2 >= s1);
- }
-
- {
- int arr[] = {2, 1}; // bigger
-
- span<int> s1;
- span<int> s2 = arr;
-
- EXPECT_TRUE(s1 != s2);
- EXPECT_TRUE(s2 != s1);
- EXPECT_FALSE(s1 == s2);
- EXPECT_FALSE(s2 == s1);
- EXPECT_TRUE(s1 < s2);
- EXPECT_FALSE(s2 < s1);
- EXPECT_TRUE(s1 <= s2);
- EXPECT_FALSE(s2 <= s1);
- EXPECT_TRUE(s2 > s1);
- EXPECT_FALSE(s1 > s2);
- EXPECT_TRUE(s2 >= s1);
- EXPECT_FALSE(s1 >= s2);
- }
-
- {
- int arr1[] = {1, 2};
- int arr2[] = {1, 2};
- span<int> s1 = arr1;
- span<int> s2 = arr2;
-
- EXPECT_TRUE(s1 == s2);
- EXPECT_FALSE(s1 != s2);
- EXPECT_FALSE(s1 < s2);
- EXPECT_TRUE(s1 <= s2);
- EXPECT_FALSE(s1 > s2);
- EXPECT_TRUE(s1 >= s2);
- EXPECT_TRUE(s2 == s1);
- EXPECT_FALSE(s2 != s1);
- EXPECT_FALSE(s2 < s1);
- EXPECT_TRUE(s2 <= s1);
- EXPECT_FALSE(s2 > s1);
- EXPECT_TRUE(s2 >= s1);
- }
-
- {
- int arr[] = {1, 2, 3};
-
- span<int> s1 = {&arr[0], 2}; // shorter
- span<int> s2 = arr; // longer
-
- EXPECT_TRUE(s1 != s2);
- EXPECT_TRUE(s2 != s1);
- EXPECT_FALSE(s1 == s2);
- EXPECT_FALSE(s2 == s1);
- EXPECT_TRUE(s1 < s2);
- EXPECT_FALSE(s2 < s1);
- EXPECT_TRUE(s1 <= s2);
- EXPECT_FALSE(s2 <= s1);
- EXPECT_TRUE(s2 > s1);
- EXPECT_FALSE(s1 > s2);
- EXPECT_TRUE(s2 >= s1);
- EXPECT_FALSE(s1 >= s2);
- }
-
- {
- int arr1[] = {1, 2}; // smaller
- int arr2[] = {2, 1}; // bigger
-
- span<int> s1 = arr1;
- span<int> s2 = arr2;
-
- EXPECT_TRUE(s1 != s2);
- EXPECT_TRUE(s2 != s1);
- EXPECT_FALSE(s1 == s2);
- EXPECT_FALSE(s2 == s1);
- EXPECT_TRUE(s1 < s2);
- EXPECT_FALSE(s2 < s1);
- EXPECT_TRUE(s1 <= s2);
- EXPECT_FALSE(s2 <= s1);
- EXPECT_TRUE(s2 > s1);
- EXPECT_FALSE(s1 > s2);
- EXPECT_TRUE(s2 >= s1);
- EXPECT_FALSE(s1 >= s2);
- }
- }
+{
+ int arr[5] = {1, 2, 3, 4, 5};
+ int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
+ int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+
+ {
+ const auto s = make_span(arr);
+ EXPECT_TRUE(s.size() == 5);
+ EXPECT_TRUE(s.data() == std::addressof(arr[0]));
+ }
+
+ {
+ const auto s = make_span(std::addressof(arr2d[0]), 1);
+ EXPECT_TRUE(s.size() == 1);
+ EXPECT_TRUE(s.data() == std::addressof(arr2d[0]));
+ }
+
+ {
+ const auto s = make_span(std::addressof(arr3d[0]), 1);
+ EXPECT_TRUE(s.size() == 1);
+ EXPECT_TRUE(s.data() == std::addressof(arr3d[0]));
+ }
+}
+
+TEST(span_ext_test, make_span_from_dynamic_array_constructor)
+{
+ double(*arr)[3][4] = new double[100][3][4];
+
+ {
+ auto s = make_span(&arr[0][0][0], 10);
+ EXPECT_TRUE(s.size() == 10);
+ EXPECT_TRUE(s.data() == &arr[0][0][0]);
+ }
+
+ delete[] arr;
+}
+
+TEST(span_ext_test, make_span_from_std_array_constructor)
+{
+ std::array<int, 4> arr = {1, 2, 3, 4};
+
+ {
+ auto s = make_span(arr);
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
+ }
+
+ // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590
+ {
+ gsl::span<int> s1 = make_span(arr);
+
+ static gsl::span<int> s2;
+ s2 = s1;
+
+#if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \
+ __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__)
+ // Known to be broken in gcc 6.4 and 6.5 with optimizations
+ // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116
+ EXPECT_TRUE(s1.size() == 4);
+ EXPECT_TRUE(s2.size() == 0);
+#else
+ EXPECT_TRUE(s1.size() == s2.size());
+#endif
+ }
+}
+
+TEST(span_ext_test, make_span_from_const_std_array_constructor)
+{
+ const std::array<int, 4> arr = {1, 2, 3, 4};
+
+ {
+ auto s = make_span(arr);
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
+ }
+}
+
+TEST(span_ext_test, make_span_from_std_array_const_constructor)
+{
+ std::array<const int, 4> arr = {1, 2, 3, 4};
+
+ {
+ auto s = make_span(arr);
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
+ }
+}
+
+TEST(span_ext_test, make_span_from_container_constructor)
+{
+ std::vector<int> v = {1, 2, 3};
+ const std::vector<int> cv = v;
+
+ {
+ auto s = make_span(v);
+ EXPECT_TRUE(s.size() == v.size());
+ EXPECT_TRUE(s.data() == v.data());
+
+ auto cs = make_span(cv);
+ EXPECT_TRUE(cs.size() == cv.size());
+ EXPECT_TRUE(cs.data() == cv.data());
+ }
+}
+
+TEST(span_test, interop_with_gsl_at)
+{
+ int arr[5] = {1, 2, 3, 4, 5};
+ gsl::span<int> s{arr};
+ EXPECT_TRUE(at(s, 0) == 1);
+ EXPECT_TRUE(at(s, 1) == 2);
+}
+
+TEST(span_ext_test, iterator_free_functions)
+{
+ int a[] = {1, 2, 3, 4};
+ gsl::span<int> s{a};
+
+ EXPECT_TRUE((std::is_same<decltype(s.begin()), decltype(begin(s))>::value));
+ EXPECT_TRUE((std::is_same<decltype(s.end()), decltype(end(s))>::value));
+
+ EXPECT_TRUE((std::is_same<decltype(std::cbegin(s)), decltype(cbegin(s))>::value));
+ EXPECT_TRUE((std::is_same<decltype(std::cend(s)), decltype(cend(s))>::value));
+
+ EXPECT_TRUE((std::is_same<decltype(s.rbegin()), decltype(rbegin(s))>::value));
+ EXPECT_TRUE((std::is_same<decltype(s.rend()), decltype(rend(s))>::value));
+
+ EXPECT_TRUE((std::is_same<decltype(std::crbegin(s)), decltype(crbegin(s))>::value));
+ EXPECT_TRUE((std::is_same<decltype(std::crend(s)), decltype(crend(s))>::value));
+
+ EXPECT_TRUE(s.begin() == begin(s));
+ EXPECT_TRUE(s.end() == end(s));
+
+ EXPECT_TRUE(s.rbegin() == rbegin(s));
+ EXPECT_TRUE(s.rend() == rend(s));
+
+ EXPECT_TRUE(s.begin() == cbegin(s));
+ EXPECT_TRUE(s.end() == cend(s));
+
+ EXPECT_TRUE(s.rbegin() == crbegin(s));
+ EXPECT_TRUE(s.rend() == crend(s));
+}
+
+TEST(span_ext_test, ssize_free_function)
+{
+ int a[] = {1, 2, 3, 4};
+ gsl::span<int> s{a};
+
+ EXPECT_FALSE((std::is_same<decltype(s.size()), decltype(ssize(s))>::value));
+ EXPECT_TRUE(s.size() == static_cast<std::size_t>(ssize(s)));
+}
+
+#ifndef GSL_KERNEL_MODE
+TEST(span_ext_test, comparison_operators)
+{
+ {
+ gsl::span<int> s1;
+ gsl::span<int> s2;
+ EXPECT_TRUE(s1 == s2);
+ EXPECT_FALSE(s1 != s2);
+ EXPECT_FALSE(s1 < s2);
+ EXPECT_TRUE(s1 <= s2);
+ EXPECT_FALSE(s1 > s2);
+ EXPECT_TRUE(s1 >= s2);
+ EXPECT_TRUE(s2 == s1);
+ EXPECT_FALSE(s2 != s1);
+ EXPECT_FALSE(s2 != s1);
+ EXPECT_TRUE(s2 <= s1);
+ EXPECT_FALSE(s2 > s1);
+ EXPECT_TRUE(s2 >= s1);
+ }
+
+ {
+ int arr[] = {2, 1};
+ gsl::span<int> s1 = arr;
+ gsl::span<int> s2 = arr;
+
+ EXPECT_TRUE(s1 == s2);
+ EXPECT_FALSE(s1 != s2);
+ EXPECT_FALSE(s1 < s2);
+ EXPECT_TRUE(s1 <= s2);
+ EXPECT_FALSE(s1 > s2);
+ EXPECT_TRUE(s1 >= s2);
+ EXPECT_TRUE(s2 == s1);
+ EXPECT_FALSE(s2 != s1);
+ EXPECT_FALSE(s2 < s1);
+ EXPECT_TRUE(s2 <= s1);
+ EXPECT_FALSE(s2 > s1);
+ EXPECT_TRUE(s2 >= s1);
+ }
+
+ {
+ int arr[] = {2, 1}; // bigger
+
+ gsl::span<int> s1;
+ gsl::span<int> s2 = arr;
+
+ EXPECT_TRUE(s1 != s2);
+ EXPECT_TRUE(s2 != s1);
+ EXPECT_FALSE(s1 == s2);
+ EXPECT_FALSE(s2 == s1);
+ EXPECT_TRUE(s1 < s2);
+ EXPECT_FALSE(s2 < s1);
+ EXPECT_TRUE(s1 <= s2);
+ EXPECT_FALSE(s2 <= s1);
+ EXPECT_TRUE(s2 > s1);
+ EXPECT_FALSE(s1 > s2);
+ EXPECT_TRUE(s2 >= s1);
+ EXPECT_FALSE(s1 >= s2);
+ }
+
+ {
+ int arr1[] = {1, 2};
+ int arr2[] = {1, 2};
+ gsl::span<int> s1 = arr1;
+ gsl::span<int> s2 = arr2;
+
+ EXPECT_TRUE(s1 == s2);
+ EXPECT_FALSE(s1 != s2);
+ EXPECT_FALSE(s1 < s2);
+ EXPECT_TRUE(s1 <= s2);
+ EXPECT_FALSE(s1 > s2);
+ EXPECT_TRUE(s1 >= s2);
+ EXPECT_TRUE(s2 == s1);
+ EXPECT_FALSE(s2 != s1);
+ EXPECT_FALSE(s2 < s1);
+ EXPECT_TRUE(s2 <= s1);
+ EXPECT_FALSE(s2 > s1);
+ EXPECT_TRUE(s2 >= s1);
+ }
+
+ {
+ int arr[] = {1, 2, 3};
+
+ gsl::span<int> s1 = {&arr[0], 2}; // shorter
+ gsl::span<int> s2 = arr; // longer
+
+ EXPECT_TRUE(s1 != s2);
+ EXPECT_TRUE(s2 != s1);
+ EXPECT_FALSE(s1 == s2);
+ EXPECT_FALSE(s2 == s1);
+ EXPECT_TRUE(s1 < s2);
+ EXPECT_FALSE(s2 < s1);
+ EXPECT_TRUE(s1 <= s2);
+ EXPECT_FALSE(s2 <= s1);
+ EXPECT_TRUE(s2 > s1);
+ EXPECT_FALSE(s1 > s2);
+ EXPECT_TRUE(s2 >= s1);
+ EXPECT_FALSE(s1 >= s2);
+ }
+
+ {
+ int arr1[] = {1, 2}; // smaller
+ int arr2[] = {2, 1}; // bigger
+
+ gsl::span<int> s1 = arr1;
+ gsl::span<int> s2 = arr2;
+
+ EXPECT_TRUE(s1 != s2);
+ EXPECT_TRUE(s2 != s1);
+ EXPECT_FALSE(s1 == s2);
+ EXPECT_FALSE(s2 == s1);
+ EXPECT_TRUE(s1 < s2);
+ EXPECT_FALSE(s2 < s1);
+ EXPECT_TRUE(s1 <= s2);
+ EXPECT_FALSE(s2 <= s1);
+ EXPECT_TRUE(s2 > s1);
+ EXPECT_FALSE(s1 > s2);
+ EXPECT_TRUE(s2 >= s1);
+ EXPECT_FALSE(s1 >= s2);
+ }
+}
+#endif // GSL_KERNEL_MODE
diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp
index b845d07..41ac3ae 100644
--- a/tests/span_tests.cpp
+++ b/tests/span_tests.cpp
@@ -17,19 +17,19 @@
#include <gtest/gtest.h>
#include <gsl/byte> // for byte
+#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <gsl/util> // for narrow_cast, at
-#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <array> // for array
+#include <cstddef> // for ptrdiff_t
#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 <cstddef> // for ptrdiff_t
#include <string> // for string
#include <type_traits> // for integral_constant<>::value, is_default_co...
-#include <vector> // for vector
#include <utility>
+#include <vector> // for vector
// the string_view include and macro are used in the deduction guide verification
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
@@ -40,13 +40,16 @@
#endif // __has_include(<string_view>)
#endif // __has_include
#endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
+#if defined(__cplusplus) && __cplusplus >= 202002L
+#include <span>
+#endif // __cplusplus >= 202002L
+
+#include "deathTestCommon.h"
-using namespace std;
using namespace gsl;
namespace
{
-static constexpr char deathstring[] = "Expected Death";
struct BaseClass
{
@@ -111,10 +114,12 @@ TEST(span_test, size_optimization)
TEST(span_test, from_nullptr_size_constructor)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. from_nullptr_size_constructor";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
+
{
span<int> s{nullptr, narrow_cast<span<int>::size_type>(0)};
EXPECT_TRUE(s.size() == 0);
@@ -128,21 +133,21 @@ TEST(span_test, from_nullptr_size_constructor)
auto workaround_macro = []() {
const span<int, 1> s{nullptr, narrow_cast<span<int>::size_type>(0)};
};
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
{
auto workaround_macro = []() { const span<int> s{nullptr, 1}; };
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
auto const_workaround_macro = []() { const span<const int> s{nullptr, 1}; };
- EXPECT_DEATH(const_workaround_macro(), deathstring);
+ EXPECT_DEATH(const_workaround_macro(), expected);
}
{
auto workaround_macro = []() { const span<int, 0> s{nullptr, 1}; };
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
auto const_workaround_macro = []() { const span<const int, 0> s{nullptr, 1}; };
- EXPECT_DEATH(const_workaround_macro(), deathstring);
+ EXPECT_DEATH(const_workaround_macro(), expected);
}
{
span<int*> s{nullptr, narrow_cast<span<int>::size_type>(0)};
@@ -157,10 +162,12 @@ TEST(span_test, from_nullptr_size_constructor)
TEST(span_test, from_pointer_length_constructor)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. from_pointer_length_constructor";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
+
int arr[4] = {1, 2, 3, 4};
{
@@ -171,8 +178,7 @@ TEST(span_test, from_pointer_length_constructor)
EXPECT_TRUE(s.size() == narrow_cast<std::size_t>(i));
EXPECT_TRUE(s.data() == &arr[0]);
EXPECT_TRUE(s.empty() == (i == 0));
- for (int j = 0; j < i; ++j)
- EXPECT_TRUE(arr[j] == s[narrow_cast<std::size_t>(j)]);
+ for (int j = 0; j < i; ++j) EXPECT_TRUE(arr[j] == s[narrow_cast<std::size_t>(j)]);
}
{
span<int> s = {&arr[i], 4 - narrow_cast<std::size_t>(i)};
@@ -204,7 +210,7 @@ TEST(span_test, from_pointer_length_constructor)
{
int* p = nullptr;
auto workaround_macro = [=]() { const span<int> s{p, 2}; };
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
}
@@ -242,14 +248,14 @@ TEST(span_test, from_pointer_pointer_construction)
// this will fail the std::distance() precondition, which asserts on MSVC debug builds
//{
// auto workaround_macro = [&]() { span<int> s{&arr[1], &arr[0]}; };
- // EXPECT_DEATH(workaround_macro(), deathstring);
+ // EXPECT_DEATH(workaround_macro(), expected);
//}
// this will fail the std::distance() precondition, which asserts on MSVC debug builds
//{
// int* p = nullptr;
// auto workaround_macro = [&]() { span<int> s{&arr[0], p}; };
- // EXPECT_DEATH(workaround_macro(), deathstring);
+ // EXPECT_DEATH(workaround_macro(), expected);
//}
{
@@ -270,897 +276,912 @@ TEST(span_test, from_pointer_pointer_construction)
//{
// int* p = nullptr;
// auto workaround_macro = [&]() { span<int> s{&arr[0], p}; };
- // EXPECT_DEATH(workaround_macro(), deathstring);
+ // EXPECT_DEATH(workaround_macro(), expected);
//}
}
TEST(span_test, from_array_constructor)
- {
- int arr[5] = {1, 2, 3, 4, 5};
+{
+ int arr[5] = {1, 2, 3, 4, 5};
- {
- const span<int> s{arr};
- EXPECT_TRUE(s.size() == 5);
- EXPECT_TRUE(s.data() == &arr[0]);
- }
+ {
+ const span<int> s{arr};
+ EXPECT_TRUE(s.size() == 5);
+ EXPECT_TRUE(s.data() == &arr[0]);
+ }
- {
- const span<int, 5> s{arr};
- EXPECT_TRUE(s.size() == 5);
- EXPECT_TRUE(s.data() == &arr[0]);
- }
+ {
+ const span<int, 5> s{arr};
+ EXPECT_TRUE(s.size() == 5);
+ EXPECT_TRUE(s.data() == &arr[0]);
+ }
- int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
+ int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
- #ifdef CONFIRM_COMPILATION_ERRORS
- {
- span<int, 6> s{arr};
- }
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ span<int, 6> s{arr};
+ }
- {
- span<int, 0> s{arr};
- EXPECT_TRUE(s.size() == 0);
- EXPECT_TRUE(s.data() == &arr[0]);
- }
+ {
+ span<int, 0> s{arr};
+ EXPECT_TRUE(s.size() == 0);
+ EXPECT_TRUE(s.data() == &arr[0]);
+ }
- {
- span<int> s{arr2d};
- EXPECT_TRUE(s.size() == 6);
- EXPECT_TRUE(s.data() == &arr2d[0][0]);
- EXPECT_TRUE(s[0] == 1);
- EXPECT_TRUE(s[5] == 6);
- }
+ {
+ span<int> s{arr2d};
+ EXPECT_TRUE(s.size() == 6);
+ EXPECT_TRUE(s.data() == &arr2d[0][0]);
+ EXPECT_TRUE(s[0] == 1);
+ EXPECT_TRUE(s[5] == 6);
+ }
- {
- span<int, 0> s{arr2d};
- EXPECT_TRUE(s.size() == 0);
- EXPECT_TRUE(s.data() == &arr2d[0][0]);
- }
+ {
+ span<int, 0> s{arr2d};
+ EXPECT_TRUE(s.size() == 0);
+ EXPECT_TRUE(s.data() == &arr2d[0][0]);
+ }
- {
- span<int, 6> s{arr2d};
- }
- #endif
- {
- const span<int[3]> s{std::addressof(arr2d[0]), 1};
- EXPECT_TRUE(s.size() == 1);
- EXPECT_TRUE(s.data() == std::addressof(arr2d[0]));
- }
+ {
+ span<int, 6> s{arr2d};
+ }
+#endif
+ {
+ const span<int[3]> s{std::addressof(arr2d[0]), 1};
+ EXPECT_TRUE(s.size() == 1);
+ EXPECT_TRUE(s.data() == std::addressof(arr2d[0]));
+ }
- int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- #ifdef CONFIRM_COMPILATION_ERRORS
- {
- span<int> s{arr3d};
- EXPECT_TRUE(s.size() == 12);
- EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
- EXPECT_TRUE(s[0] == 1);
- EXPECT_TRUE(s[11] == 12);
- }
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ span<int> s{arr3d};
+ EXPECT_TRUE(s.size() == 12);
+ EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
+ EXPECT_TRUE(s[0] == 1);
+ EXPECT_TRUE(s[11] == 12);
+ }
- {
- span<int, 0> s{arr3d};
- EXPECT_TRUE(s.size() == 0);
- EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
- }
+ {
+ span<int, 0> s{arr3d};
+ EXPECT_TRUE(s.size() == 0);
+ EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
+ }
- {
- span<int, 11> s{arr3d};
- }
+ {
+ span<int, 11> s{arr3d};
+ }
- {
- span<int, 12> s{arr3d};
- EXPECT_TRUE(s.size() == 12);
- EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
- EXPECT_TRUE(s[0] == 1);
- EXPECT_TRUE(s[5] == 6);
- }
- #endif
- {
- const span<int[3][2]> s{std::addressof(arr3d[0]), 1};
- EXPECT_TRUE(s.size() == 1);
- }
+ {
+ span<int, 12> s{arr3d};
+ EXPECT_TRUE(s.size() == 12);
+ EXPECT_TRUE(s.data() == &arr3d[0][0][0]);
+ EXPECT_TRUE(s[0] == 1);
+ EXPECT_TRUE(s[5] == 6);
+ }
+#endif
+ {
+ const span<int[3][2]> s{std::addressof(arr3d[0]), 1};
+ EXPECT_TRUE(s.size() == 1);
+ }
- AddressOverloaded ao_arr[5] = {};
+ AddressOverloaded ao_arr[5] = {};
- {
- const span<AddressOverloaded, 5> s{ao_arr};
- EXPECT_TRUE(s.size() == 5);
- EXPECT_TRUE(s.data() == std::addressof(ao_arr[0]));
- }
- }
+ {
+ const span<AddressOverloaded, 5> s{ao_arr};
+ EXPECT_TRUE(s.size() == 5);
+ EXPECT_TRUE(s.data() == std::addressof(ao_arr[0]));
+ }
+}
- TEST(span_test, from_dynamic_array_constructor)
- {
- double(*arr)[3][4] = new double[100][3][4];
+TEST(span_test, from_dynamic_array_constructor)
+{
+ double(*arr)[3][4] = new double[100][3][4];
- {
- span<double> s(&arr[0][0][0], 10);
- EXPECT_TRUE(s.size() == 10);
- EXPECT_TRUE(s.data() == &arr[0][0][0]);
- }
+ {
+ span<double> s(&arr[0][0][0], 10);
+ EXPECT_TRUE(s.size() == 10);
+ EXPECT_TRUE(s.data() == &arr[0][0][0]);
+ }
- delete[] arr;
- }
+ delete[] arr;
+}
- TEST(span_test, from_std_array_constructor)
- {
- std::array<int, 4> arr = {1, 2, 3, 4};
+TEST(span_test, from_std_array_constructor)
+{
+ std::array<int, 4> arr = {1, 2, 3, 4};
- {
- span<int> s{arr};
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
+ {
+ span<int> s{arr};
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
- span<const int> cs{arr};
- EXPECT_TRUE(cs.size() == arr.size());
- EXPECT_TRUE(cs.data() == arr.data());
- }
+ span<const int> cs{arr};
+ EXPECT_TRUE(cs.size() == arr.size());
+ EXPECT_TRUE(cs.data() == arr.data());
+ }
- {
- span<int, 4> s{arr};
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
+ {
+ span<int, 4> s{arr};
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
- span<const int, 4> cs{arr};
- EXPECT_TRUE(cs.size() == arr.size());
- EXPECT_TRUE(cs.data() == arr.data());
- }
+ span<const int, 4> cs{arr};
+ EXPECT_TRUE(cs.size() == arr.size());
+ EXPECT_TRUE(cs.data() == arr.data());
+ }
- {
- std::array<int, 0> empty_arr{};
- span<int> s{empty_arr};
- EXPECT_TRUE(s.size() == 0);
- EXPECT_TRUE(s.empty());
- }
+ {
+ std::array<int, 0> empty_arr{};
+ span<int> s{empty_arr};
+ EXPECT_TRUE(s.size() == 0);
+ EXPECT_TRUE(s.empty());
+ }
- std::array<AddressOverloaded, 4> ao_arr{};
+ std::array<AddressOverloaded, 4> ao_arr{};
- {
- span<AddressOverloaded, 4> fs{ao_arr};
- EXPECT_TRUE(fs.size() == ao_arr.size());
- EXPECT_TRUE(ao_arr.data() == fs.data());
- }
+ {
+ span<AddressOverloaded, 4> fs{ao_arr};
+ EXPECT_TRUE(fs.size() == ao_arr.size());
+ EXPECT_TRUE(ao_arr.data() == fs.data());
+ }
- #ifdef CONFIRM_COMPILATION_ERRORS
- {
- span<int, 2> s{arr};
- EXPECT_TRUE(s.size() == 2);
- EXPECT_TRUE(s.data() == arr.data());
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ span<int, 2> s{arr};
+ EXPECT_TRUE(s.size() == 2);
+ EXPECT_TRUE(s.data() == arr.data());
- span<const int, 2> cs{arr};
- EXPECT_TRUE(cs.size() == 2);
- EXPECT_TRUE(cs.data() == arr.data());
- }
+ span<const int, 2> cs{arr};
+ EXPECT_TRUE(cs.size() == 2);
+ EXPECT_TRUE(cs.data() == arr.data());
+ }
- {
- span<int, 0> s{arr};
- EXPECT_TRUE(s.size() == 0);
- EXPECT_TRUE(s.data() == arr.data());
+ {
+ span<int, 0> s{arr};
+ EXPECT_TRUE(s.size() == 0);
+ EXPECT_TRUE(s.data() == arr.data());
- span<const int, 0> cs{arr};
- EXPECT_TRUE(cs.size() == 0);
- EXPECT_TRUE(cs.data() == arr.data());
- }
+ span<const int, 0> cs{arr};
+ EXPECT_TRUE(cs.size() == 0);
+ EXPECT_TRUE(cs.data() == arr.data());
+ }
- {
- span<int, 5> s{arr};
- }
+ {
+ span<int, 5> s{arr};
+ }
- {
- auto get_an_array = []() -> std::array<int, 4> { return {1, 2, 3, 4}; };
- auto take_a_span = [](span<int> s) { static_cast<void>(s); };
- // try to take a temporary std::array
- take_a_span(get_an_array());
- }
- #endif
+ {
+ auto get_an_array = []() -> std::array<int, 4> { return {1, 2, 3, 4}; };
+ auto take_a_span = [](span<int> s) { static_cast<void>(s); };
+ // try to take a temporary std::array
+ take_a_span(get_an_array());
+ }
+#endif
- {
- auto get_an_array = []() -> std::array<int, 4> { return {1, 2, 3, 4}; };
- auto take_a_span = [](span<const int> s) { static_cast<void>(s); };
- // try to take a temporary std::array
- take_a_span(get_an_array());
- }
- }
+ {
+ auto get_an_array = []() -> std::array<int, 4> { return {1, 2, 3, 4}; };
+ auto take_a_span = [](span<const int> s) { static_cast<void>(s); };
+ // try to take a temporary std::array
+ take_a_span(get_an_array());
+ }
+}
- TEST(span_test, from_const_std_array_constructor)
- {
- const std::array<int, 4> arr = {1, 2, 3, 4};
+TEST(span_test, from_const_std_array_constructor)
+{
+ const std::array<int, 4> arr = {1, 2, 3, 4};
- {
- span<const int> s{arr};
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
- }
+ {
+ span<const int> s{arr};
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
+ }
- {
- span<const int, 4> s{arr};
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
- }
+ {
+ span<const int, 4> s{arr};
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
+ }
- const std::array<AddressOverloaded, 4> ao_arr{};
+ const std::array<AddressOverloaded, 4> ao_arr{};
- {
- span<const AddressOverloaded, 4> s{ao_arr};
- EXPECT_TRUE(s.size() == ao_arr.size());
- EXPECT_TRUE(s.data() == ao_arr.data());
- }
+ {
+ span<const AddressOverloaded, 4> s{ao_arr};
+ EXPECT_TRUE(s.size() == ao_arr.size());
+ EXPECT_TRUE(s.data() == ao_arr.data());
+ }
- #ifdef CONFIRM_COMPILATION_ERRORS
- {
- span<const int, 2> s{arr};
- EXPECT_TRUE(s.size() == 2);
- EXPECT_TRUE(s.data() == arr.data());
- }
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ span<const int, 2> s{arr};
+ EXPECT_TRUE(s.size() == 2);
+ EXPECT_TRUE(s.data() == arr.data());
+ }
- {
- span<const int, 0> s{arr};
- EXPECT_TRUE(s.size() == 0);
- EXPECT_TRUE(s.data() == arr.data());
- }
+ {
+ span<const int, 0> s{arr};
+ EXPECT_TRUE(s.size() == 0);
+ EXPECT_TRUE(s.data() == arr.data());
+ }
- {
- span<const int, 5> s{arr};
- }
- #endif
+ {
+ span<const int, 5> s{arr};
+ }
+#endif
- {
- auto get_an_array = []() -> const std::array<int, 4> { return {1, 2, 3, 4}; };
- auto take_a_span = [](span<const int> s) { static_cast<void>(s); };
- // try to take a temporary std::array
- take_a_span(get_an_array());
- }
- }
+ {
+ auto get_an_array = []() -> const std::array<int, 4> { return {1, 2, 3, 4}; };
+ auto take_a_span = [](span<const int> s) { static_cast<void>(s); };
+ // try to take a temporary std::array
+ take_a_span(get_an_array());
+ }
+}
- TEST(span_test, from_std_array_const_constructor)
- {
- std::array<const int, 4> arr = {1, 2, 3, 4};
+TEST(span_test, from_std_array_const_constructor)
+{
+ std::array<const int, 4> arr = {1, 2, 3, 4};
- {
- span<const int> s{arr};
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
- }
+ {
+ span<const int> s{arr};
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
+ }
- {
- span<const int, 4> s{arr};
- EXPECT_TRUE(s.size() == arr.size());
- EXPECT_TRUE(s.data() == arr.data());
- }
+ {
+ span<const int, 4> s{arr};
+ EXPECT_TRUE(s.size() == arr.size());
+ EXPECT_TRUE(s.data() == arr.data());
+ }
- #ifdef CONFIRM_COMPILATION_ERRORS
- {
- span<const int, 2> s{arr};
- EXPECT_TRUE(s.size() == 2);
- EXPECT_TRUE(s.data() == arr.data());
- }
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ span<const int, 2> s{arr};
+ EXPECT_TRUE(s.size() == 2);
+ EXPECT_TRUE(s.data() == arr.data());
+ }
- {
- span<const int, 0> s{arr};
- EXPECT_TRUE(s.size() == 0);
- EXPECT_TRUE(s.data() == arr.data());
- }
+ {
+ span<const int, 0> s{arr};
+ EXPECT_TRUE(s.size() == 0);
+ EXPECT_TRUE(s.data() == arr.data());
+ }
- {
- span<const int, 5> s{arr};
- }
+ {
+ span<const int, 5> s{arr};
+ }
- {
- span<int, 4> s{arr};
- }
- #endif
- }
+ {
+ span<int, 4> s{arr};
+ }
+#endif
+}
- TEST(span_test, from_container_constructor)
- {
- std::vector<int> v = {1, 2, 3};
- const std::vector<int> cv = v;
+TEST(span_test, from_container_constructor)
+{
+ std::vector<int> v = {1, 2, 3};
+ const std::vector<int> cv = v;
- {
- span<int> s{v};
- EXPECT_TRUE(s.size() == v.size());
- EXPECT_TRUE(s.data() == v.data());
+ {
+ span<int> s{v};
+ EXPECT_TRUE(s.size() == v.size());
+ EXPECT_TRUE(s.data() == v.data());
- span<const int> cs{v};
- EXPECT_TRUE(cs.size() == v.size());
- EXPECT_TRUE(cs.data() == v.data());
- }
+ span<const int> cs{v};
+ EXPECT_TRUE(cs.size() == v.size());
+ EXPECT_TRUE(cs.data() == v.data());
+ }
- std::string str = "hello";
- const std::string cstr = "hello";
+ std::string str = "hello";
+ const std::string cstr = "hello";
- {
- #ifdef CONFIRM_COMPILATION_ERRORS
- span<char> s{str};
- EXPECT_TRUE(s.size() == str.size());
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ span<char> s{str};
+ EXPECT_TRUE(s.size() == str.size());
EXPECT_TRUE(s.data() == str.data()));
- #endif
+#endif
span<const char> cs{str};
EXPECT_TRUE(cs.size() == str.size());
EXPECT_TRUE(cs.data() == str.data());
- }
+ }
- {
- #ifdef CONFIRM_COMPILATION_ERRORS
- span<char> s{cstr};
- #endif
- span<const char> cs{cstr};
- EXPECT_TRUE(cs.size() == cstr.size());
- EXPECT_TRUE(cs.data() == cstr.data());
- }
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ span<char> s{cstr};
+#endif
+ span<const char> cs{cstr};
+ EXPECT_TRUE(cs.size() == cstr.size());
+ EXPECT_TRUE(cs.data() == cstr.data());
+ }
- {
- #ifdef CONFIRM_COMPILATION_ERRORS
- auto get_temp_vector = []() -> std::vector<int> { return {}; };
- auto use_span = [](span<int> s) { static_cast<void>(s); };
- use_span(get_temp_vector());
- #endif
- }
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ auto get_temp_vector = []() -> std::vector<int> { return {}; };
+ auto use_span = [](span<int> s) { static_cast<void>(s); };
+ use_span(get_temp_vector());
+#endif
+ }
- {
- auto get_temp_vector = []() -> std::vector<int> { return {}; };
- auto use_span = [](span<const int> s) { static_cast<void>(s); };
- use_span(get_temp_vector());
- }
+ {
+ auto get_temp_vector = []() -> std::vector<int> { return {}; };
+ auto use_span = [](span<const int> s) { static_cast<void>(s); };
+ use_span(get_temp_vector());
+ }
- {
- #ifdef CONFIRM_COMPILATION_ERRORS
- auto get_temp_string = []() -> std::string { return {}; };
- auto use_span = [](span<char> s) { static_cast<void>(s); };
- use_span(get_temp_string());
- #endif
- }
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ auto get_temp_string = []() -> std::string { return {}; };
+ auto use_span = [](span<char> s) { static_cast<void>(s); };
+ use_span(get_temp_string());
+#endif
+ }
- {
- auto get_temp_string = []() -> std::string { return {}; };
- auto use_span = [](span<const char> s) { static_cast<void>(s); };
- use_span(get_temp_string());
- }
+ {
+ auto get_temp_string = []() -> std::string { return {}; };
+ auto use_span = [](span<const char> s) { static_cast<void>(s); };
+ use_span(get_temp_string());
+ }
- {
- #ifdef CONFIRM_COMPILATION_ERRORS
- auto get_temp_vector = []() -> const std::vector<int> { return {}; };
- auto use_span = [](span<const char> s) { static_cast<void>(s); };
- use_span(get_temp_vector());
- #endif
- }
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ auto get_temp_vector = []() -> const std::vector<int> { return {}; };
+ auto use_span = [](span<const char> s) { static_cast<void>(s); };
+ use_span(get_temp_vector());
+#endif
+ }
- {
- auto get_temp_string = []() -> const std::string { return {}; };
- auto use_span = [](span<const char> s) { static_cast<void>(s); };
- use_span(get_temp_string());
- }
+ {
+ auto get_temp_string = []() -> const std::string { return {}; };
+ auto use_span = [](span<const char> s) { static_cast<void>(s); };
+ use_span(get_temp_string());
+ }
- {
- #ifdef CONFIRM_COMPILATION_ERRORS
- std::map<int, int> m;
- span<int> s{m};
- #endif
- }
- }
-
- TEST(span_test, from_convertible_span_constructor){{span<DerivedClass> avd;
- span<const DerivedClass> avcd = avd;
- static_cast<void>(avcd);
- }
-
- {
- #ifdef CONFIRM_COMPILATION_ERRORS
- span<DerivedClass> avd;
- span<BaseClass> avb = avd;
- static_cast<void>(avb);
- #endif
- }
-
- #ifdef CONFIRM_COMPILATION_ERRORS
- {
- span<int> s;
- span<unsigned int> s2 = s;
- static_cast<void>(s2);
- }
-
- {
- span<int> s;
- span<const unsigned int> s2 = s;
- static_cast<void>(s2);
- }
-
- {
- span<int> s;
- span<short> s2 = s;
- static_cast<void>(s2);
- }
- #endif
- }
-
- TEST(span_test, copy_move_and_assignment)
- {
- span<int> s1;
- EXPECT_TRUE(s1.empty());
-
- int arr[] = {3, 4, 5};
-
- span<const int> s2 = arr;
- EXPECT_TRUE(s2.size() == 3);
- EXPECT_TRUE(s2.data() == &arr[0]);
-
- s2 = s1;
- EXPECT_TRUE(s2.empty());
-
- auto get_temp_span = [&]() -> span<int> { return {&arr[1], 2}; };
- auto use_span = [&](span<const int> s) {
- EXPECT_TRUE(s.size() == 2);
- EXPECT_TRUE(s.data() == &arr[1]);
- }; use_span(get_temp_span());
-
- s1 = get_temp_span();
- EXPECT_TRUE(s1.size() == 2);
- EXPECT_TRUE(s1.data() == &arr[1]);
- }
-
- TEST(span_test, first)
- {
- std::set_terminate([] {
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ std::map<int, int> m;
+ span<int> s{m};
+#endif
+ }
+}
+
+TEST(span_test, from_convertible_span_constructor){{span<DerivedClass> avd;
+span<const DerivedClass> avcd = avd;
+static_cast<void>(avcd);
+}
+
+{
+#ifdef CONFIRM_COMPILATION_ERRORS
+ span<DerivedClass> avd;
+ span<BaseClass> avb = avd;
+ static_cast<void>(avb);
+#endif
+}
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+{
+ span<int> s;
+ span<unsigned int> s2 = s;
+ static_cast<void>(s2);
+}
+
+{
+ span<int> s;
+ span<const unsigned int> s2 = s;
+ static_cast<void>(s2);
+}
+
+{
+ span<int> s;
+ span<short> s2 = s;
+ static_cast<void>(s2);
+}
+#endif
+}
+
+TEST(span_test, copy_move_and_assignment)
+{
+ span<int> s1;
+ EXPECT_TRUE(s1.empty());
+
+ int arr[] = {3, 4, 5};
+
+ span<const int> s2 = arr;
+ EXPECT_TRUE(s2.size() == 3);
+ EXPECT_TRUE(s2.data() == &arr[0]);
+
+ s2 = s1;
+ EXPECT_TRUE(s2.empty());
+
+ auto get_temp_span = [&]() -> span<int> { return {&arr[1], 2}; };
+ auto use_span = [&](span<const int> s) {
+ EXPECT_TRUE(s.size() == 2);
+ EXPECT_TRUE(s.data() == &arr[1]);
+ };
+ use_span(get_temp_span());
+
+ s1 = get_temp_span();
+ EXPECT_TRUE(s1.size() == 2);
+ EXPECT_TRUE(s1.data() == &arr[1]);
+}
+
+TEST(span_test, first)
+{
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. first";
std::abort();
});
- int arr[5] = {1, 2, 3, 4, 5};
+ const auto expected = GetExpectedDeathString(terminateHandler);
- {
- span<int, 5> av = arr;
- EXPECT_TRUE(av.first<2>().size() == 2);
- EXPECT_TRUE(av.first(2).size() == 2);
- }
+ int arr[5] = {1, 2, 3, 4, 5};
- {
- span<int, 5> av = arr;
- EXPECT_TRUE(av.first<0>().size() == 0);
- EXPECT_TRUE(av.first(0).size() == 0);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE(av.first<2>().size() == 2);
+ EXPECT_TRUE(av.first(2).size() == 2);
+ }
- {
- span<int, 5> av = arr;
- EXPECT_TRUE(av.first<5>().size() == 5);
- EXPECT_TRUE(av.first(5).size() == 5);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE(av.first<0>().size() == 0);
+ EXPECT_TRUE(av.first(0).size() == 0);
+ }
- {
- span<int, 5> av = arr;
- #ifdef CONFIRM_COMPILATION_ERRORS
- EXPECT_TRUE(av.first<6>().size() == 6);
- EXPECT_TRUE(av.first<-1>().size() == -1);
- #endif
- EXPECT_DEATH(av.first(6).size(), deathstring);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE(av.first<5>().size() == 5);
+ EXPECT_TRUE(av.first(5).size() == 5);
+ }
- {
- span<int> av;
- EXPECT_TRUE(av.first<0>().size() == 0);
- EXPECT_TRUE(av.first(0).size() == 0);
- }
- }
+ {
+ span<int, 5> av = arr;
+#ifdef CONFIRM_COMPILATION_ERRORS
+ EXPECT_TRUE(av.first<6>().size() == 6);
+ EXPECT_TRUE(av.first<-1>().size() == -1);
+#endif
+ EXPECT_DEATH(av.first(6).size(), expected);
+ }
+
+ {
+ span<int> av;
+ EXPECT_TRUE(av.first<0>().size() == 0);
+ EXPECT_TRUE(av.first(0).size() == 0);
+ }
+}
- TEST(span_test, last)
- {
- std::set_terminate([] {
+TEST(span_test, last)
+{
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. last";
std::abort();
});
- int arr[5] = {1, 2, 3, 4, 5};
+ const auto expected = GetExpectedDeathString(terminateHandler);
- {
- span<int, 5> av = arr;
- EXPECT_TRUE(av.last<2>().size() == 2);
- EXPECT_TRUE(av.last(2).size() == 2);
- }
+ int arr[5] = {1, 2, 3, 4, 5};
- {
- span<int, 5> av = arr;
- EXPECT_TRUE(av.last<0>().size() == 0);
- EXPECT_TRUE(av.last(0).size() == 0);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE(av.last<2>().size() == 2);
+ EXPECT_TRUE(av.last(2).size() == 2);
+ }
- {
- span<int, 5> av = arr;
- EXPECT_TRUE(av.last<5>().size() == 5);
- EXPECT_TRUE(av.last(5).size() == 5);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE(av.last<0>().size() == 0);
+ EXPECT_TRUE(av.last(0).size() == 0);
+ }
- {
- span<int, 5> av = arr;
- #ifdef CONFIRM_COMPILATION_ERRORS
- EXPECT_TRUE(av.last<6>().size() == 6);
- #endif
- EXPECT_DEATH(av.last(6).size(), deathstring);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE(av.last<5>().size() == 5);
+ EXPECT_TRUE(av.last(5).size() == 5);
+ }
- {
- span<int> av;
- EXPECT_TRUE(av.last<0>().size() == 0);
- EXPECT_TRUE(av.last(0).size() == 0);
- }
- }
+ {
+ span<int, 5> av = arr;
+#ifdef CONFIRM_COMPILATION_ERRORS
+ EXPECT_TRUE(av.last<6>().size() == 6);
+#endif
+ EXPECT_DEATH(av.last(6).size(), expected);
+ }
- TEST(span_test, subspan)
- {
- std::set_terminate([] {
+ {
+ span<int> av;
+ EXPECT_TRUE(av.last<0>().size() == 0);
+ EXPECT_TRUE(av.last(0).size() == 0);
+ }
+}
+
+TEST(span_test, subspan)
+{
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. subspan";
std::abort();
});
- int arr[5] = {1, 2, 3, 4, 5};
+ const auto expected = GetExpectedDeathString(terminateHandler);
- {
- span<int, 5> av = arr;
- EXPECT_TRUE((av.subspan<2, 2>().size()) == 2);
- EXPECT_TRUE(decltype(av.subspan<2, 2>())::extent == 2);
- EXPECT_TRUE(av.subspan(2, 2).size() == 2);
- EXPECT_TRUE(av.subspan(2, 3).size() == 3);
- }
+ int arr[5] = {1, 2, 3, 4, 5};
- {
- span<int, 5> av = arr;
- EXPECT_TRUE((av.subspan<0, 0>().size()) == 0);
- EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0);
- EXPECT_TRUE(av.subspan(0, 0).size() == 0);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE((av.subspan<2, 2>().size()) == 2);
+ EXPECT_TRUE(decltype(av.subspan<2, 2>())::extent == 2);
+ EXPECT_TRUE(av.subspan(2, 2).size() == 2);
+ EXPECT_TRUE(av.subspan(2, 3).size() == 3);
+ }
- {
- span<int, 5> av = arr;
- EXPECT_TRUE((av.subspan<0, 5>().size()) == 5);
- EXPECT_TRUE(decltype(av.subspan<0, 5>())::extent == 5);
- EXPECT_TRUE(av.subspan(0, 5).size() == 5);
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE((av.subspan<0, 0>().size()) == 0);
+ EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0);
+ EXPECT_TRUE(av.subspan(0, 0).size() == 0);
+ }
- EXPECT_DEATH(av.subspan(0, 6).size(), deathstring);
- EXPECT_DEATH(av.subspan(1, 5).size(), deathstring);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE((av.subspan<0, 5>().size()) == 5);
+ EXPECT_TRUE(decltype(av.subspan<0, 5>())::extent == 5);
+ EXPECT_TRUE(av.subspan(0, 5).size() == 5);
- {
- span<int, 5> av = arr;
- EXPECT_TRUE((av.subspan<4, 0>().size()) == 0);
- EXPECT_TRUE(decltype(av.subspan<4, 0>())::extent == 0);
- EXPECT_TRUE(av.subspan(4, 0).size() == 0);
- EXPECT_TRUE(av.subspan(5, 0).size() == 0);
- EXPECT_DEATH(av.subspan(6, 0).size(), deathstring);
- }
+ EXPECT_DEATH(av.subspan(0, 6).size(), expected);
+ EXPECT_DEATH(av.subspan(1, 5).size(), expected);
+ }
- {
- span<int, 5> av = arr;
- EXPECT_TRUE(av.subspan<1>().size() == 4);
- EXPECT_TRUE(decltype(av.subspan<1>())::extent == 4);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE((av.subspan<4, 0>().size()) == 0);
+ EXPECT_TRUE(decltype(av.subspan<4, 0>())::extent == 0);
+ EXPECT_TRUE(av.subspan(4, 0).size() == 0);
+ EXPECT_TRUE(av.subspan(5, 0).size() == 0);
+ EXPECT_DEATH(av.subspan(6, 0).size(), expected);
+ }
- {
- span<int> av;
- EXPECT_TRUE((av.subspan<0, 0>().size()) == 0);
- EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0);
- EXPECT_TRUE(av.subspan(0, 0).size() == 0);
- EXPECT_DEATH((av.subspan<1, 0>().size()), deathstring);
- }
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE(av.subspan<1>().size() == 4);
+ EXPECT_TRUE(decltype(av.subspan<1>())::extent == 4);
+ }
- {
- span<int> av;
- EXPECT_TRUE(av.subspan(0).size() == 0);
- EXPECT_DEATH(av.subspan(1).size(), deathstring);
- }
+ {
+ span<int> av;
+ EXPECT_TRUE((av.subspan<0, 0>().size()) == 0);
+ EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0);
+ EXPECT_TRUE(av.subspan(0, 0).size() == 0);
+ EXPECT_DEATH((av.subspan<1, 0>().size()), expected);
+ }
- {
- span<int> av = arr;
- EXPECT_TRUE(av.subspan(0).size() == 5);
- EXPECT_TRUE(av.subspan(1).size() == 4);
- EXPECT_TRUE(av.subspan(4).size() == 1);
- EXPECT_TRUE(av.subspan(5).size() == 0);
- EXPECT_DEATH(av.subspan(6).size(), deathstring);
- const auto av2 = av.subspan(1);
- for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast<int>(i) + 2);
- }
+ {
+ span<int> av;
+ EXPECT_TRUE(av.subspan(0).size() == 0);
+ EXPECT_DEATH(av.subspan(1).size(), expected);
+ }
- {
- span<int, 5> av = arr;
- EXPECT_TRUE(av.subspan(0).size() == 5);
- EXPECT_TRUE(av.subspan(1).size() == 4);
- EXPECT_TRUE(av.subspan(4).size() == 1);
- EXPECT_TRUE(av.subspan(5).size() == 0);
- EXPECT_DEATH(av.subspan(6).size(), deathstring);
- const auto av2 = av.subspan(1);
- for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast<int>(i) + 2);
- }
- }
-
- TEST(span_test, iterator_default_init)
- {
- span<int>::iterator it1;
- span<int>::iterator it2;
- EXPECT_TRUE(it1 == it2);
- }
-
- TEST(span_test, iterator_comparisons)
- {
- int a[] = {1, 2, 3, 4};
- {
- span<int> s = a;
- span<int>::iterator it = s.begin();
- auto it2 = it + 1;
-
- EXPECT_TRUE(it == it);
- EXPECT_TRUE(it == s.begin());
- EXPECT_TRUE(s.begin() == it);
-
- EXPECT_TRUE(it != it2);
- EXPECT_TRUE(it2 != it);
- EXPECT_TRUE(it != s.end());
- EXPECT_TRUE(it2 != s.end());
- EXPECT_TRUE(s.end() != it);
-
- EXPECT_TRUE(it < it2);
- EXPECT_TRUE(it <= it2);
- EXPECT_TRUE(it2 <= s.end());
- EXPECT_TRUE(it < s.end());
-
- EXPECT_TRUE(it2 > it);
- EXPECT_TRUE(it2 >= it);
- EXPECT_TRUE(s.end() > it2);
- EXPECT_TRUE(s.end() >= it2);
- }
- }
+ {
+ span<int> av = arr;
+ EXPECT_TRUE(av.subspan(0).size() == 5);
+ EXPECT_TRUE(av.subspan(1).size() == 4);
+ EXPECT_TRUE(av.subspan(4).size() == 1);
+ EXPECT_TRUE(av.subspan(5).size() == 0);
+ EXPECT_DEATH(av.subspan(6).size(), expected);
+ const auto av2 = av.subspan(1);
+ for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast<int>(i) + 2);
+ }
- TEST(span_test, incomparable_iterators)
- {
- std::set_terminate([] {
- std::cerr << "Expected Death. incomparable_iterators";
- std::abort();
- });
+ {
+ span<int, 5> av = arr;
+ EXPECT_TRUE(av.subspan(0).size() == 5);
+ EXPECT_TRUE(av.subspan(1).size() == 4);
+ EXPECT_TRUE(av.subspan(4).size() == 1);
+ EXPECT_TRUE(av.subspan(5).size() == 0);
+ EXPECT_DEATH(av.subspan(6).size(), expected);
+ const auto av2 = av.subspan(1);
+ for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast<int>(i) + 2);
+ }
+}
- int a[] = {1, 2, 3, 4};
- int b[] = {1, 2, 3, 4};
- {
- span<int> s = a;
- span<int> s2 = b;
+TEST(span_test, iterator_default_init)
+{
+ span<int>::iterator it1;
+ span<int>::iterator it2;
+ EXPECT_TRUE(it1 == it2);
+}
+
+TEST(span_test, iterator_comparisons)
+{
+ int a[] = {1, 2, 3, 4};
+ {
+ span<int> s = a;
+ span<int>::iterator it = s.begin();
+ auto it2 = it + 1;
+
+ EXPECT_TRUE(it == it);
+ EXPECT_TRUE(it == s.begin());
+ EXPECT_TRUE(s.begin() == it);
+
+ EXPECT_TRUE(it != it2);
+ EXPECT_TRUE(it2 != it);
+ EXPECT_TRUE(it != s.end());
+ EXPECT_TRUE(it2 != s.end());
+ EXPECT_TRUE(s.end() != it);
+
+ EXPECT_TRUE(it < it2);
+ EXPECT_TRUE(it <= it2);
+ EXPECT_TRUE(it2 <= s.end());
+ EXPECT_TRUE(it < s.end());
+
+ EXPECT_TRUE(it2 > it);
+ EXPECT_TRUE(it2 >= it);
+ EXPECT_TRUE(s.end() > it2);
+ EXPECT_TRUE(s.end() >= it2);
+ }
+}
+
+TEST(span_test, incomparable_iterators)
+{
+ const auto terminateHandler = std::set_terminate([] {
+ std::cerr << "Expected Death. incomparable_iterators";
+ std::abort();
+ });
+ const auto expected = GetExpectedDeathString(terminateHandler);
+
+ int a[] = {1, 2, 3, 4};
+ int b[] = {1, 2, 3, 4};
+ {
+ span<int> s = a;
+ span<int> s2 = b;
#if (__cplusplus > 201402L)
- EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() == s2.begin()), deathstring);
- EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() <= s2.begin()), deathstring);
+ EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() == s2.begin()), expected);
+ EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() <= s2.begin()), expected);
#else
- EXPECT_DEATH(bool _ = (s.begin() == s2.begin()), deathstring);
- EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), deathstring);
+ EXPECT_DEATH(bool _ = (s.begin() == s2.begin()), expected);
+ EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), expected);
#endif
- }
- }
+ }
+}
- TEST(span_test, begin_end)
- {
- std::set_terminate([] {
+TEST(span_test, begin_end)
+{
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. begin_end";
std::abort();
});
- {
- int a[] = {1, 2, 3, 4};
- span<int> s = a;
+ const auto expected = GetExpectedDeathString(terminateHandler);
- span<int>::iterator it = s.begin();
- span<int>::iterator it2 = std::begin(s);
- EXPECT_TRUE(it == it2);
+ {
+ int a[] = {1, 2, 3, 4};
+ span<int> s = a;
- it = s.end();
- it2 = std::end(s);
- EXPECT_TRUE(it == it2);
- }
+ span<int>::iterator it = s.begin();
+ span<int>::iterator it2 = std::begin(s);
+ EXPECT_TRUE(it == it2);
- {
- int a[] = {1, 2, 3, 4};
- span<int> s = a;
-
- auto it = s.begin();
- auto first = it;
- EXPECT_TRUE(it == first);
- EXPECT_TRUE(*it == 1);
-
- auto beyond = s.end();
- EXPECT_TRUE(it != beyond);
- EXPECT_DEATH(*beyond, deathstring);
-
- EXPECT_TRUE(beyond - first == 4);
- EXPECT_TRUE(first - first == 0);
- EXPECT_TRUE(beyond - beyond == 0);
-
- ++it;
- EXPECT_TRUE(it - first == 1);
- EXPECT_TRUE(*it == 2);
- *it = 22;
- EXPECT_TRUE(*it == 22);
- EXPECT_TRUE(beyond - it == 3);
-
- it = first;
- EXPECT_TRUE(it == first);
- while (it != s.end())
- {
- *it = 5;
- ++it;
- }
-
- EXPECT_TRUE(it == beyond);
- EXPECT_TRUE(it - beyond == 0);
-
- for (const auto& n : s) { EXPECT_TRUE(n == 5); }
- }
- }
+ it = s.end();
+ it2 = std::end(s);
+ EXPECT_TRUE(it == it2);
+ }
+
+ {
+ int a[] = {1, 2, 3, 4};
+ span<int> s = a;
+
+ auto it = s.begin();
+ auto first = it;
+ EXPECT_TRUE(it == first);
+ EXPECT_TRUE(*it == 1);
+
+ auto beyond = s.end();
+ EXPECT_TRUE(it != beyond);
+ EXPECT_DEATH(*beyond, expected);
+
+ EXPECT_TRUE(beyond - first == 4);
+ EXPECT_TRUE(first - first == 0);
+ EXPECT_TRUE(beyond - beyond == 0);
+
+ ++it;
+ EXPECT_TRUE(it - first == 1);
+ EXPECT_TRUE(*it == 2);
+ *it = 22;
+ EXPECT_TRUE(*it == 22);
+ EXPECT_TRUE(beyond - it == 3);
+
+ it = first;
+ EXPECT_TRUE(it == first);
+ while (it != s.end())
+ {
+ *it = 5;
+ ++it;
+ }
+
+ EXPECT_TRUE(it == beyond);
+ EXPECT_TRUE(it - beyond == 0);
- TEST(span_test, rbegin_rend)
- {
- std::set_terminate([] {
+ for (const auto& n : s) { EXPECT_TRUE(n == 5); }
+ }
+}
+
+TEST(span_test, rbegin_rend)
+{
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. rbegin_rend";
std::abort();
});
- {
- int a[] = {1, 2, 3, 4};
- span<int> s = a;
+ const auto expected = GetExpectedDeathString(terminateHandler);
+
+ {
+ int a[] = {1, 2, 3, 4};
+ span<int> s = a;
- auto it = s.rbegin();
- auto first = it;
- EXPECT_TRUE(it == first);
- EXPECT_TRUE(*it == 4);
+ auto it = s.rbegin();
+ auto first = it;
+ EXPECT_TRUE(it == first);
+ EXPECT_TRUE(*it == 4);
- auto beyond = s.rend();
- EXPECT_TRUE(it != beyond);
+ auto beyond = s.rend();
+ EXPECT_TRUE(it != beyond);
#if (__cplusplus > 201402L)
- EXPECT_DEATH([[maybe_unused]] auto _ = *beyond , deathstring);
+ EXPECT_DEATH([[maybe_unused]] auto _ = *beyond, expected);
#else
- EXPECT_DEATH(auto _ = *beyond , deathstring);
+ EXPECT_DEATH(auto _ = *beyond, expected);
#endif
- EXPECT_TRUE(beyond - first == 4);
- EXPECT_TRUE(first - first == 0);
- EXPECT_TRUE(beyond - beyond == 0);
-
- ++it;
- EXPECT_TRUE(it - s.rbegin() == 1);
- EXPECT_TRUE(*it == 3);
- *it = 22;
- EXPECT_TRUE(*it == 22);
- EXPECT_TRUE(beyond - it == 3);
-
- it = first;
- EXPECT_TRUE(it == first);
- while (it != s.rend())
- {
- *it = 5;
- ++it;
- }
-
- EXPECT_TRUE(it == beyond);
- EXPECT_TRUE(it - beyond == 0);
-
- for (const auto& n : s) { EXPECT_TRUE(n == 5); }
- }
- }
+ EXPECT_TRUE(beyond - first == 4);
+ EXPECT_TRUE(first - first == 0);
+ EXPECT_TRUE(beyond - beyond == 0);
- TEST(span_test, as_bytes)
- {
- std::set_terminate([] {
- std::cerr << "Expected Death. as_bytes";
- std::abort();
- });
+ ++it;
+ EXPECT_TRUE(it - s.rbegin() == 1);
+ EXPECT_TRUE(*it == 3);
+ *it = 22;
+ EXPECT_TRUE(*it == 22);
+ EXPECT_TRUE(beyond - it == 3);
- int a[] = {1, 2, 3, 4};
- {
- const span<const int> s = a;
- EXPECT_TRUE(s.size() == 4);
- const span<const byte> bs = as_bytes(s);
- EXPECT_TRUE(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
- EXPECT_TRUE(bs.size() == s.size_bytes());
- }
+ it = first;
+ EXPECT_TRUE(it == first);
+ while (it != s.rend())
+ {
+ *it = 5;
+ ++it;
+ }
- {
- span<int> s;
- const auto bs = as_bytes(s);
- EXPECT_TRUE(bs.size() == s.size());
- EXPECT_TRUE(bs.size() == 0);
- EXPECT_TRUE(bs.size_bytes() == 0);
- EXPECT_TRUE(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
- EXPECT_TRUE(bs.data() == nullptr);
- }
+ EXPECT_TRUE(it == beyond);
+ EXPECT_TRUE(it - beyond == 0);
- {
- span<int> s = a;
- const auto bs = as_bytes(s);
- EXPECT_TRUE(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
- EXPECT_TRUE(bs.size() == s.size_bytes());
- }
+ for (const auto& n : s) { EXPECT_TRUE(n == 5); }
+ }
+}
- int b[5] = {1, 2, 3, 4, 5};
- {
- span<int> sp(begin(b), static_cast<size_t>(-2));
- EXPECT_DEATH((void) sp.size_bytes(), deathstring);
- }
- }
+TEST(span_test, as_bytes)
+{
+ const auto terminateHandler = std::set_terminate([] {
+ std::cerr << "Expected Death. as_bytes";
+ std::abort();
+ });
+ const auto expected = GetExpectedDeathString(terminateHandler);
- TEST(span_test, as_writable_bytes)
- {
- int a[] = {1, 2, 3, 4};
+ int a[] = {1, 2, 3, 4};
+ {
+ const span<const int> s = a;
+ EXPECT_TRUE(s.size() == 4);
+ const span<const byte> bs = as_bytes(s);
+ EXPECT_TRUE(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
+ EXPECT_TRUE(bs.size() == s.size_bytes());
+ }
- {
- #ifdef CONFIRM_COMPILATION_ERRORS
- // you should not be able to get writeable bytes for const objects
- span<const int> s = a;
- EXPECT_TRUE(s.size() == 4);
- span<const byte> bs = as_writable_bytes(s);
- EXPECT_TRUE(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
- EXPECT_TRUE(bs.size() == s.size_bytes());
- #endif
- }
+ {
+ span<int> s;
+ const auto bs = as_bytes(s);
+ EXPECT_TRUE(bs.size() == s.size());
+ EXPECT_TRUE(bs.size() == 0);
+ EXPECT_TRUE(bs.size_bytes() == 0);
+ EXPECT_TRUE(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
+ EXPECT_TRUE(bs.data() == nullptr);
+ }
- {
- span<int> s;
- const auto bs = as_writable_bytes(s);
- EXPECT_TRUE(bs.size() == s.size());
- EXPECT_TRUE(bs.size() == 0);
- EXPECT_TRUE(bs.size_bytes() == 0);
- EXPECT_TRUE(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
- EXPECT_TRUE(bs.data() == nullptr);
- }
+ {
+ span<int> s = a;
+ const auto bs = as_bytes(s);
+ EXPECT_TRUE(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
+ EXPECT_TRUE(bs.size() == s.size_bytes());
+ }
- {
- span<int> s = a;
- const auto bs = as_writable_bytes(s);
- EXPECT_TRUE(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
- EXPECT_TRUE(bs.size() == s.size_bytes());
- }
- }
+ int b[5] = {1, 2, 3, 4, 5};
+ {
+ span<int> sp(std::begin(b), static_cast<size_t>(-2));
+ EXPECT_DEATH((void) sp.size_bytes(), expected);
+ }
+}
+
+TEST(span_test, as_writable_bytes)
+{
+ int a[] = {1, 2, 3, 4};
+
+ {
+#ifdef CONFIRM_COMPILATION_ERRORS
+ // you should not be able to get writeable bytes for const objects
+ span<const int> s = a;
+ EXPECT_TRUE(s.size() == 4);
+ span<const byte> bs = as_writable_bytes(s);
+ EXPECT_TRUE(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
+ EXPECT_TRUE(bs.size() == s.size_bytes());
+#endif
+ }
+
+ {
+ span<int> s;
+ const auto bs = as_writable_bytes(s);
+ EXPECT_TRUE(bs.size() == s.size());
+ EXPECT_TRUE(bs.size() == 0);
+ EXPECT_TRUE(bs.size_bytes() == 0);
+ EXPECT_TRUE(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
+ EXPECT_TRUE(bs.data() == nullptr);
+ }
+
+ {
+ span<int> s = a;
+ const auto bs = as_writable_bytes(s);
+ EXPECT_TRUE(static_cast<void*>(bs.data()) == static_cast<void*>(s.data()));
+ EXPECT_TRUE(bs.size() == s.size_bytes());
+ }
+}
- TEST(span_test, fixed_size_conversions)
- {
- std::set_terminate([] {
+TEST(span_test, fixed_size_conversions)
+{
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. fixed_size_conversions";
std::abort();
});
- int arr[] = {1, 2, 3, 4};
+ const auto expected = GetExpectedDeathString(terminateHandler);
- // converting to an span from an equal size array is ok
- span<int, 4> s4 = arr;
- EXPECT_TRUE(s4.size() == 4);
+ int arr[] = {1, 2, 3, 4};
- // converting to dynamic_range is always ok
- {
- span<int> s = s4;
- EXPECT_TRUE(s.size() == s4.size());
- static_cast<void>(s);
- }
+ // converting to an span from an equal size array is ok
+ span<int, 4> s4 = arr;
+ EXPECT_TRUE(s4.size() == 4);
- // initialization or assignment to static span that REDUCES size is NOT ok
- #ifdef CONFIRM_COMPILATION_ERRORS
- {
- span<int, 2> s = arr;
- }
- {
- span<int, 2> s2 = s4;
- static_cast<void>(s2);
- }
- #endif
+ // converting to dynamic_range is always ok
+ {
+ span<int> s = s4;
+ EXPECT_TRUE(s.size() == s4.size());
+ static_cast<void>(s);
+ }
- // even when done dynamically
- {
- /*
- // this now results in a compile-time error, rather than runtime.
- // There is no suitable conversion from dynamic span to fixed span.
- span<int> s = arr;
- auto f = [&]() {
- const span<int, 2> s2 = s;
- static_cast<void>(s2);
- };
- EXPECT_DEATH(f(), deathstring);
- */
- }
+// initialization or assignment to static span that REDUCES size is NOT ok
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ span<int, 2> s = arr;
+ }
+ {
+ span<int, 2> s2 = s4;
+ static_cast<void>(s2);
+ }
+#endif
- // but doing so explicitly is ok
+ // even when done dynamically
+ {
+ /*
+ // this now results in a compile-time error, rather than runtime.
+ // There is no suitable conversion from dynamic span to fixed span.
+ span<int> s = arr;
+ auto f = [&]() {
+ const span<int, 2> s2 = s;
+ static_cast<void>(s2);
+ };
+ EXPECT_DEATH(f(), expected);
+ */
+ }
- // you can convert statically
- {
- const span<int, 2> s2{&arr[0], 2};
- static_cast<void>(s2);
- }
- {
- const span<int, 1> s1 = s4.first<1>();
- static_cast<void>(s1);
- }
+ // but doing so explicitly is ok
+
+ // you can convert statically
+ {
+ const span<int, 2> s2{&arr[0], 2};
+ static_cast<void>(s2);
+ }
+ {
+ const span<int, 1> s1 = s4.first<1>();
+ static_cast<void>(s1);
+ }
/*
// this is not a legal operation in std::span, so we are no longer supporting it
@@ -1176,73 +1197,74 @@ TEST(span_test, from_array_constructor)
}
*/
- // initialization or assignment to static span that requires size INCREASE is not ok.
- int arr2[2] = {1, 2};
+ // initialization or assignment to static span that requires size INCREASE is not ok.
+ int arr2[2] = {1, 2};
- #ifdef CONFIRM_COMPILATION_ERRORS
- {
- span<int, 4> s3 = arr2;
- }
- {
- span<int, 2> s2 = arr2;
- span<int, 4> s4a = s2;
- }
- #endif
- {
- auto f = [&]() {
- const span<int, 4> _s4{arr2, 2};
- static_cast<void>(_s4);
- };
- EXPECT_DEATH(f(), deathstring);
- }
+#ifdef CONFIRM_COMPILATION_ERRORS
+ {
+ span<int, 4> s3 = arr2;
+ }
+ {
+ span<int, 2> s2 = arr2;
+ span<int, 4> s4a = s2;
+ }
+#endif
+ {
+ auto f = [&]() {
+ const span<int, 4> _s4{arr2, 2};
+ static_cast<void>(_s4);
+ };
+ EXPECT_DEATH(f(), expected);
+ }
/*
- // This no longer compiles. There is no suitable conversion from dynamic span to a fixed size span.
+ // This no longer compiles. There is no suitable conversion from dynamic span to a fixed size
+ span.
// this should fail - we are trying to assign a small dynamic span to a fixed_size larger one
span<int> av = arr2; auto f = [&]() {
const span<int, 4> _s4 = av;
static_cast<void>(_s4);
};
- EXPECT_DEATH(f(), deathstring);
+ EXPECT_DEATH(f(), expected);
*/
- }
-
- TEST(span_test, interop_with_std_regex)
- {
- char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'};
- span<char> s = lat;
- const auto f_it = s.begin() + 7;
-
- std::match_results<span<char>::iterator> match;
-
- std::regex_match(s.begin(), s.end(), match, std::regex(".*"));
- EXPECT_TRUE(match.ready());
- EXPECT_FALSE(match.empty());
- EXPECT_TRUE(match[0].matched);
- EXPECT_TRUE(match[0].first == s.begin());
- EXPECT_TRUE(match[0].second == s.end());
-
- std::regex_search(s.begin(), s.end(), match, std::regex("F"));
- EXPECT_TRUE(match.ready());
- EXPECT_FALSE(match.empty());
- EXPECT_TRUE(match[0].matched);
- EXPECT_TRUE(match[0].first == f_it);
- EXPECT_TRUE(match[0].second == (f_it + 1));
- }
-
- TEST(span_test, default_constructible)
- {
- EXPECT_TRUE((std::is_default_constructible<span<int>>::value));
- EXPECT_TRUE((std::is_default_constructible<span<int, 0>>::value));
- EXPECT_FALSE((std::is_default_constructible<span<int, 42>>::value));
- }
-
- TEST(span_test, std_container_ctad)
- {
+}
+
+TEST(span_test, interop_with_std_regex)
+{
+ char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'};
+ span<char> s = lat;
+ const auto f_it = s.begin() + 7;
+
+ std::match_results<span<char>::iterator> match;
+
+ std::regex_match(s.begin(), s.end(), match, std::regex(".*"));
+ EXPECT_TRUE(match.ready());
+ EXPECT_FALSE(match.empty());
+ EXPECT_TRUE(match[0].matched);
+ EXPECT_TRUE(match[0].first == s.begin());
+ EXPECT_TRUE(match[0].second == s.end());
+
+ std::regex_search(s.begin(), s.end(), match, std::regex("F"));
+ EXPECT_TRUE(match.ready());
+ EXPECT_FALSE(match.empty());
+ EXPECT_TRUE(match[0].matched);
+ EXPECT_TRUE(match[0].first == f_it);
+ EXPECT_TRUE(match[0].second == (f_it + 1));
+}
+
+TEST(span_test, default_constructible)
+{
+ EXPECT_TRUE((std::is_default_constructible<span<int>>::value));
+ EXPECT_TRUE((std::is_default_constructible<span<int, 0>>::value));
+ EXPECT_FALSE((std::is_default_constructible<span<int, 42>>::value));
+}
+
+TEST(span_test, std_container_ctad)
+{
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
// this test is just to verify that these compile
{
- std::vector<int> v{1,2,3,4};
+ std::vector<int> v{1, 2, 3, 4};
gsl::span sp{v};
static_assert(std::is_same<decltype(sp), gsl::span<int>>::value);
}
@@ -1259,20 +1281,39 @@ TEST(span_test, from_array_constructor)
}
#endif
#endif
- }
+}
- TEST(span_test, front_back)
- {
- int arr[5] = {1,2,3,4,5};
+TEST(span_test, front_back)
+{
+ int arr[5] = {1, 2, 3, 4, 5};
span<int> s{arr};
EXPECT_TRUE(s.front() == 1);
EXPECT_TRUE(s.back() == 5);
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. front_back";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
+
span<int> s2;
- EXPECT_DEATH(s2.front(), deathstring);
- EXPECT_DEATH(s2.back(), deathstring);
- }
+ EXPECT_DEATH(s2.front(), expected);
+ EXPECT_DEATH(s2.back(), expected);
+}
+
+#if defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
+TEST(span_test, std_span)
+{
+ // make sure std::span can be constructed from gsl::span
+ int arr[5] = {1, 2, 3, 4, 5};
+ gsl::span<int> gsl_span{arr};
+#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts))
+ EXPECT_TRUE(std::to_address(gsl_span.begin()) == gsl_span.data());
+ EXPECT_TRUE(std::to_address(gsl_span.end()) == gsl_span.data() + gsl_span.size());
+#endif // __cpp_lib_ranges
+
+ std::span<int> std_span = gsl_span;
+ EXPECT_TRUE(std_span.data() == gsl_span.data());
+ EXPECT_TRUE(std_span.size() == gsl_span.size());
+}
+#endif // defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
diff --git a/tests/strict_notnull_tests.cpp b/tests/strict_notnull_tests.cpp
index 3cf6911..7edef43 100644
--- a/tests/strict_notnull_tests.cpp
+++ b/tests/strict_notnull_tests.cpp
@@ -14,30 +14,40 @@
//
///////////////////////////////////////////////////////////////////////////////
+#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
#include <gtest/gtest.h>
-#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
-namespace gsl
-{
-struct fail_fast;
-} // namespace gsl
+#include "deathTestCommon.h"
using namespace gsl;
-GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+namespace
+{
+// clang-format off
+GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+// clang-format on
bool helper(not_null<int*> p) { return *p == 12; }
+// clang-format off
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+// clang-format on
bool helper_const(not_null<const int*> p) { return *p == 12; }
+// clang-format off
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+// clang-format on
bool strict_helper(strict_not_null<int*> p) { return *p == 12; }
+// clang-format off
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
+// clang-format on
bool strict_helper_const(strict_not_null<const int*> p) { return *p == 12; }
+#ifdef CONFIRM_COMPILATION_ERRORS
int* return_pointer() { return nullptr; }
const int* return_pointer_const() { return nullptr; }
+#endif
+} // namespace
TEST(strict_notnull_tests, TestStrictNotNull)
{
@@ -123,17 +133,14 @@ TEST(strict_notnull_tests, TestStrictNotNull)
}
#if defined(__cplusplus) && (__cplusplus >= 201703L)
-namespace
-{
-static constexpr char deathstring[] = "Expected Death";
-}
TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestStrictNotNullConstructorTypeDeduction";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
{
int i = 42;
@@ -161,7 +168,7 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction)
int* p1 = nullptr;
const strict_not_null x{p1};
};
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
{
@@ -169,14 +176,14 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction)
const int* p1 = nullptr;
const strict_not_null x{p1};
};
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
{
int* p = nullptr;
- EXPECT_DEATH(helper(strict_not_null{p}), deathstring);
- EXPECT_DEATH(helper_const(strict_not_null{p}), deathstring);
+ EXPECT_DEATH(helper(strict_not_null{p}), expected);
+ EXPECT_DEATH(helper_const(strict_not_null{p}), expected);
}
#ifdef CONFIRM_COMPILATION_ERRORS
diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp
index 3c919d0..45a67d9 100644
--- a/tests/string_span_tests.cpp
+++ b/tests/string_span_tests.cpp
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
-#include <gsl/assert> // for Expects, fail_fast (ptr only)
+#include <gsl/assert> // for Expects, fail_fast (ptr only)
#include <gsl/pointers> // for owner
#include <gsl/span> // for span, dynamic_extent
#include <gsl/string_span> // for basic_string_span, operator==, ensure_z
@@ -28,13 +28,10 @@
#include <type_traits> // for remove_reference<>::type
#include <vector> // for vector, allocator
-using namespace std;
+#include "deathTestCommon.h"
+
using namespace gsl;
-namespace
-{
-static constexpr char deathstring[] = "Expected Death";
-}
// Generic string functions
namespace generic
@@ -76,8 +73,7 @@ T create()
template <class T>
void use(basic_string_span<T, gsl::dynamic_extent>)
-{
-}
+{}
#endif
czstring_span<> CreateTempName(string_span<> span)
@@ -85,7 +81,8 @@ czstring_span<> CreateTempName(string_span<> span)
Expects(span.size() > 1);
std::size_t last = 0;
- if (span.size() > 4) {
+ if (span.size() > 4)
+ {
span[0] = 't';
span[1] = 'm';
span[2] = 'p';
@@ -102,7 +99,8 @@ cwzstring_span<> CreateTempNameW(wstring_span<> span)
Expects(span.size() > 1);
std::size_t last = 0;
- if (span.size() > 4) {
+ if (span.size() > 4)
+ {
span[0] = L't';
span[1] = L'm';
span[2] = L'p';
@@ -119,7 +117,8 @@ cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
Expects(span.size() > 1);
std::size_t last = 0;
- if (span.size() > 4) {
+ if (span.size() > 4)
+ {
span[0] = u't';
span[1] = u'm';
span[2] = u'p';
@@ -136,7 +135,8 @@ cu32zstring_span<> CreateTempNameU32(u32string_span<> span)
Expects(span.size() > 1);
std::size_t last = 0;
- if (span.size() > 4) {
+ if (span.size() > 4)
+ {
span[0] = U't';
span[1] = U'm';
span[2] = U'p';
@@ -950,10 +950,11 @@ TEST(string_span_tests, Conversion)
TEST(string_span_tests, zstring)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. zstring";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
// create zspan from zero terminated string
{
@@ -973,7 +974,7 @@ TEST(string_span_tests, zstring)
buf[0] = 'a';
auto workaround_macro = [&]() { const zstring_span<> zspan({buf, 1}); };
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
// usage scenario: create zero-terminated temp file name and pass to a legacy API
@@ -981,8 +982,9 @@ TEST(string_span_tests, zstring)
char buf[10];
auto name = CreateTempName({buf, 10});
- if (!name.empty()) {
- czstring<> str = name.assume_z();
+ if (!name.empty())
+ {
+ czstring str = name.assume_z();
EXPECT_TRUE(generic::strlen(str) == 3);
EXPECT_TRUE(*(str + 3) == '\0');
}
@@ -991,10 +993,11 @@ TEST(string_span_tests, zstring)
TEST(string_span_tests, wzstring)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. wzstring";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
// create zspan from zero terminated string
{
@@ -1014,7 +1017,7 @@ TEST(string_span_tests, wzstring)
buf[0] = L'a';
const auto workaround_macro = [&]() { const wzstring_span<> zspan({buf, 1}); };
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
// usage scenario: create zero-terminated temp file name and pass to a legacy API
@@ -1022,8 +1025,9 @@ TEST(string_span_tests, wzstring)
wchar_t buf[10];
const auto name = CreateTempNameW({buf, 10});
- if (!name.empty()) {
- cwzstring<> str = name.assume_z();
+ if (!name.empty())
+ {
+ cwzstring str = name.assume_z();
EXPECT_TRUE(generic::strnlen(str, 10) == 3);
EXPECT_TRUE(*(str + 3) == L'\0');
}
@@ -1032,10 +1036,11 @@ TEST(string_span_tests, wzstring)
TEST(string_span_tests, u16zstring)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. u16zstring";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
// create zspan from zero terminated string
{
@@ -1055,7 +1060,7 @@ TEST(string_span_tests, u16zstring)
buf[0] = u'a';
const auto workaround_macro = [&]() { const u16zstring_span<> zspan({buf, 1}); };
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
// usage scenario: create zero-terminated temp file name and pass to a legacy API
@@ -1063,8 +1068,9 @@ TEST(string_span_tests, u16zstring)
char16_t buf[10];
const auto name = CreateTempNameU16({buf, 10});
- if (!name.empty()) {
- cu16zstring<> str = name.assume_z();
+ if (!name.empty())
+ {
+ cu16zstring str = name.assume_z();
EXPECT_TRUE(generic::strnlen(str, 10) == 3);
EXPECT_TRUE(*(str + 3) == L'\0');
}
@@ -1073,10 +1079,11 @@ TEST(string_span_tests, u16zstring)
TEST(string_span_tests, u32zstring)
{
- std::set_terminate([] {
+ const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. u31zstring";
std::abort();
});
+ const auto expected = GetExpectedDeathString(terminateHandler);
// create zspan from zero terminated string
{
@@ -1096,7 +1103,7 @@ TEST(string_span_tests, u32zstring)
buf[0] = u'a';
const auto workaround_macro = [&]() { const u32zstring_span<> zspan({buf, 1}); };
- EXPECT_DEATH(workaround_macro(), deathstring);
+ EXPECT_DEATH(workaround_macro(), expected);
}
// usage scenario: create zero-terminated temp file name and pass to a legacy API
@@ -1104,8 +1111,9 @@ TEST(string_span_tests, u32zstring)
char32_t buf[10];
const auto name = CreateTempNameU32({buf, 10});
- if (!name.empty()) {
- cu32zstring<> str = name.assume_z();
+ if (!name.empty())
+ {
+ cu32zstring str = name.assume_z();
EXPECT_TRUE(generic::strnlen(str, 10) == 3);
EXPECT_TRUE(*(str + 3) == L'\0');
}
diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp
index 74dc990..715073f 100644
--- a/tests/utils_tests.cpp
+++ b/tests/utils_tests.cpp
@@ -16,14 +16,15 @@
#include <gtest/gtest.h>
-#include <gsl/util> // finally, narrow_cast
-#include <gsl/narrow> // for narrow, narrowing_error
#include <algorithm> // for move
+#include <complex>
+#include <cstddef> // for std::ptrdiff_t
#include <functional> // for reference_wrapper, _Bind_helper<>::type
+#include <gsl/narrow> // for narrow, narrowing_error
+#include <gsl/util> // finally, narrow_cast
#include <limits> // for numeric_limits
#include <stdint.h> // for uint32_t, int32_t
#include <type_traits> // for is_same
-#include <cstddef> // for std::ptrdiff_t
using namespace gsl;
@@ -32,8 +33,7 @@ namespace
void f(int& i) { i += 1; }
static int j = 0;
void g() { j += 1; }
-}
-
+} // namespace
TEST(utils_tests, sanity_check_for_gsl_index_typedef)
{
@@ -123,6 +123,7 @@ TEST(utils_tests, narrow_cast)
EXPECT_TRUE(uc == 44);
}
+#ifndef GSL_KERNEL_MODE
TEST(utils_tests, narrow)
{
int n = 120;
@@ -144,4 +145,11 @@ TEST(utils_tests, narrow)
n = -42;
EXPECT_THROW(narrow<unsigned>(n), narrowing_error);
+
+ EXPECT_TRUE(
+ narrow<std::complex<float>>(std::complex<double>(4, 2)) == std::complex<float>(4, 2));
+ EXPECT_THROW(narrow<std::complex<float>>(std::complex<double>(4.2)), narrowing_error);
+
+ EXPECT_TRUE(narrow<int>(float(1)) == 1);
}
+#endif // GSL_KERNEL_MODE