mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Merge remote-tracking branch 'origin/main' into final_action-revision
This commit is contained in:
commit
8840d87199
2
.github/workflows/android.yml
vendored
2
.github/workflows/android.yml
vendored
@ -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
|
||||
|
6
.github/workflows/ios.yml
vendored
6
.github/workflows/ios.yml
vendored
@ -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
|
||||
|
337
.travis.yml
337
.travis.yml
@ -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}
|
@ -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
|
||||
)
|
||||
|
||||
|
40
README.md
40
README.md
@ -30,14 +30,14 @@ not_null | ☑ | restricts a pointer / smart po
|
||||
span | ☑ | a view over a contiguous sequence of memory. Based on the standardized verison of `std::span`, however `gsl::span` enforces bounds checking. See the [wiki](https://github.com/microsoft/GSL/wiki/gsl::span-and-std::span) for additional information.
|
||||
span_p | ☐ | spans a range starting from a pointer to the first place for which the predicate is true
|
||||
basic_zstring | ☑ | A pointer to a C-string (zero-terminated array) with a templated char type
|
||||
zstring | ☑ | An alias to `basic_zstring` with a char type of char
|
||||
czstring | ☑ | An alias to `basic_zstring` with a char type of const char
|
||||
wzstring | ☑ | An alias to `basic_zstring` with a char type of wchar_t
|
||||
cwzstring | ☑ | An alias to `basic_zstring` with a char type of const wchar_t
|
||||
u16zstring | ☑ | An alias to `basic_zstring` with a char type of char16_t
|
||||
cu16zstring | ☑ | An alias to `basic_zstring` with a char type of const char16_t
|
||||
u32zstring | ☑ | An alias to `basic_zstring` with a char type of char32_t
|
||||
cu32zstring | ☑ | An alias to `basic_zstring` with a char type of const char32_t
|
||||
zstring | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of char
|
||||
czstring | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of const char
|
||||
wzstring | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of wchar_t
|
||||
cwzstring | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of const wchar_t
|
||||
u16zstring | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of char16_t
|
||||
cu16zstring | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of const char16_t
|
||||
u32zstring | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of char32_t
|
||||
cu32zstring | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of const char32_t
|
||||
[**2. Owners**][cg-owners] | |
|
||||
unique_ptr | ☑ | an alias to `std::unique_ptr`
|
||||
shared_ptr | ☑ | an alias to `std::shared_ptr`
|
||||
@ -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!
|
||||
|
41
SECURITY.md
Normal file
41
SECURITY.md
Normal file
@ -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 -->
|
@ -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
|
||||
- template: ./pipelines/jobs.yml
|
||||
parameters:
|
||||
jobName: 'Validate Clang Previous'
|
||||
imageName: ubuntu-18.04
|
||||
compiler: clang
|
||||
image: ubuntu-20.04
|
||||
compilerVersions: [ 12, 11 ]
|
||||
setupfile: 'setup_clang.yml'
|
||||
|
||||
# MSVC
|
||||
- stage: MSVC
|
||||
- stage: Xcode
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./pipelines/jobs.yml
|
||||
parameters:
|
||||
jobName: 'Validate MSVC latest'
|
||||
imageName: windows-latest
|
||||
- template: ./pipelines/jobs.yml
|
||||
parameters:
|
||||
jobName: 'Validate MSVC Previous'
|
||||
imageName: vs2017-win2016
|
||||
compiler: 'Xcode'
|
||||
image: macOS-11
|
||||
compilerVersions: [ '12.5.1', '13.2.1' ]
|
||||
setupfile: 'setup_apple.yml'
|
||||
|
||||
# Apple-Clang
|
||||
- stage: Apple_Clang
|
||||
- stage: VS_MSVC
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./pipelines/jobs.yml
|
||||
parameters:
|
||||
jobName: 'Validate Apple-Clang latest'
|
||||
imageName: macos-10.15
|
||||
compiler: 'VS2019 (MSVC)'
|
||||
compilerVersions: [ 'default' ]
|
||||
image: windows-2019
|
||||
- template: ./pipelines/jobs.yml
|
||||
parameters:
|
||||
jobName: 'Validate Apple-Clang Previous'
|
||||
imageName: macos-10.14
|
||||
compiler: 'VS2022 (MSVC)'
|
||||
compilerVersions: [ 'default' ]
|
||||
image: windows-2022
|
||||
|
||||
- stage: VS_LLVM
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./pipelines/jobs.yml
|
||||
parameters:
|
||||
compiler: 'VS2019 (LLVM)'
|
||||
compilerVersions: [ 'default' ]
|
||||
image: windows-2019
|
||||
extraCmakeArgs: '-T ClangCL'
|
||||
- template: ./pipelines/jobs.yml
|
||||
parameters:
|
||||
compiler: 'VS2022 (LLVM)'
|
||||
compilerVersions: [ 'default' ]
|
||||
image: windows-2022
|
||||
extraCmakeArgs: '-T ClangCL'
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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,19 +27,52 @@ 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);
|
||||
|
||||
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 || (is_different_signedness && ((t < T{}) != (u < U{}))))
|
||||
if (static_cast<U>(t) != u)
|
||||
{
|
||||
throw narrowing_error{};
|
||||
}
|
||||
|
@ -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,11 +34,18 @@ 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 {};
|
||||
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
|
||||
|
||||
//
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 <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
|
||||
//
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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__)
|
||||
|
@ -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 }}
|
||||
- ${{ 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.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'
|
||||
vmImage: ${{ parameters.image }}
|
||||
continueOnError: false
|
||||
|
||||
steps:
|
||||
- template: ./steps.yml
|
||||
- ${{ 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
|
||||
|
9
pipelines/setup_apple.yml
Normal file
9
pipelines/setup_apple.yml
Normal file
@ -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
|
13
pipelines/setup_clang.yml
Normal file
13
pipelines/setup_clang.yml
Normal file
@ -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 }}
|
14
pipelines/setup_gcc.yml
Normal file
14
pipelines/setup_gcc.yml
Normal file
@ -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 }}
|
@ -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
|
@ -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")
|
||||
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
|
||||
)
|
||||
|
||||
function(add_gsl_test name)
|
||||
add_executable(${name} ${name}.cpp)
|
||||
target_link_libraries(${name}
|
||||
target_link_libraries(gsl_tests
|
||||
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_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}
|
||||
add_executable(gsl_noexcept_tests no_exception_ensure_tests.cpp)
|
||||
target_link_libraries(gsl_noexcept_tests
|
||||
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_test(gsl_noexcept_tests gsl_noexcept_tests)
|
||||
|
@ -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 ""
|
||||
|
@ -14,23 +14,19 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gsl/algorithm> // for copy
|
||||
#include <gsl/span> // for span
|
||||
#include <array> // for array
|
||||
#include <cstddef> // for size_t
|
||||
#include <gsl/algorithm> // for copy
|
||||
#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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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,42 +79,74 @@ 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), 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(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(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:
|
||||
|
@ -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);
|
||||
|
11
tests/deathTestCommon.h
Normal file
11
tests/deathTestCommon.h
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
#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
|
||||
@ -26,17 +26,16 @@
|
||||
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,7 +87,7 @@ 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};
|
||||
@ -110,10 +109,10 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
EXPECT_TRUE(s.size() == 1);
|
||||
EXPECT_TRUE(s.data() == std::addressof(arr3d[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_ext_test, make_span_from_dynamic_array_constructor)
|
||||
{
|
||||
TEST(span_ext_test, make_span_from_dynamic_array_constructor)
|
||||
{
|
||||
double(*arr)[3][4] = new double[100][3][4];
|
||||
|
||||
{
|
||||
@ -123,10 +122,10 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
}
|
||||
|
||||
delete[] arr;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_ext_test, make_span_from_std_array_constructor)
|
||||
{
|
||||
TEST(span_ext_test, make_span_from_std_array_constructor)
|
||||
{
|
||||
std::array<int, 4> arr = {1, 2, 3, 4};
|
||||
|
||||
{
|
||||
@ -137,25 +136,25 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
|
||||
// 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);
|
||||
gsl::span<int> s1 = make_span(arr);
|
||||
|
||||
static span<int> s2;
|
||||
static gsl::span<int> s2;
|
||||
s2 = s1;
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \
|
||||
#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
|
||||
#else
|
||||
EXPECT_TRUE(s1.size() == s2.size());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_ext_test, make_span_from_const_std_array_constructor)
|
||||
{
|
||||
TEST(span_ext_test, make_span_from_const_std_array_constructor)
|
||||
{
|
||||
const std::array<int, 4> arr = {1, 2, 3, 4};
|
||||
|
||||
{
|
||||
@ -163,10 +162,10 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
EXPECT_TRUE(s.size() == arr.size());
|
||||
EXPECT_TRUE(s.data() == arr.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_ext_test, make_span_from_std_array_const_constructor)
|
||||
{
|
||||
TEST(span_ext_test, make_span_from_std_array_const_constructor)
|
||||
{
|
||||
std::array<const int, 4> arr = {1, 2, 3, 4};
|
||||
|
||||
{
|
||||
@ -174,10 +173,10 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
EXPECT_TRUE(s.size() == arr.size());
|
||||
EXPECT_TRUE(s.data() == arr.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_ext_test, make_span_from_container_constructor)
|
||||
{
|
||||
TEST(span_ext_test, make_span_from_container_constructor)
|
||||
{
|
||||
std::vector<int> v = {1, 2, 3};
|
||||
const std::vector<int> cv = v;
|
||||
|
||||
@ -190,20 +189,20 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
EXPECT_TRUE(cs.size() == cv.size());
|
||||
EXPECT_TRUE(cs.data() == cv.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, interop_with_gsl_at)
|
||||
{
|
||||
TEST(span_test, interop_with_gsl_at)
|
||||
{
|
||||
int arr[5] = {1, 2, 3, 4, 5};
|
||||
span<int> s{arr};
|
||||
gsl::span<int> s{arr};
|
||||
EXPECT_TRUE(at(s, 0) == 1);
|
||||
EXPECT_TRUE(at(s, 1) == 2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_ext_test, iterator_free_functions)
|
||||
{
|
||||
TEST(span_ext_test, iterator_free_functions)
|
||||
{
|
||||
int a[] = {1, 2, 3, 4};
|
||||
span<int> s{a};
|
||||
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));
|
||||
@ -228,22 +227,23 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
|
||||
EXPECT_TRUE(s.rbegin() == crbegin(s));
|
||||
EXPECT_TRUE(s.rend() == crend(s));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_ext_test, ssize_free_function)
|
||||
{
|
||||
TEST(span_ext_test, ssize_free_function)
|
||||
{
|
||||
int a[] = {1, 2, 3, 4};
|
||||
span<int> s{a};
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_ext_test, comparison_operators)
|
||||
#ifndef GSL_KERNEL_MODE
|
||||
TEST(span_ext_test, comparison_operators)
|
||||
{
|
||||
{
|
||||
{
|
||||
span<int> s1;
|
||||
span<int> s2;
|
||||
gsl::span<int> s1;
|
||||
gsl::span<int> s2;
|
||||
EXPECT_TRUE(s1 == s2);
|
||||
EXPECT_FALSE(s1 != s2);
|
||||
EXPECT_FALSE(s1 < s2);
|
||||
@ -260,8 +260,8 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
|
||||
{
|
||||
int arr[] = {2, 1};
|
||||
span<int> s1 = arr;
|
||||
span<int> s2 = arr;
|
||||
gsl::span<int> s1 = arr;
|
||||
gsl::span<int> s2 = arr;
|
||||
|
||||
EXPECT_TRUE(s1 == s2);
|
||||
EXPECT_FALSE(s1 != s2);
|
||||
@ -280,8 +280,8 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
{
|
||||
int arr[] = {2, 1}; // bigger
|
||||
|
||||
span<int> s1;
|
||||
span<int> s2 = arr;
|
||||
gsl::span<int> s1;
|
||||
gsl::span<int> s2 = arr;
|
||||
|
||||
EXPECT_TRUE(s1 != s2);
|
||||
EXPECT_TRUE(s2 != s1);
|
||||
@ -300,8 +300,8 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
{
|
||||
int arr1[] = {1, 2};
|
||||
int arr2[] = {1, 2};
|
||||
span<int> s1 = arr1;
|
||||
span<int> s2 = arr2;
|
||||
gsl::span<int> s1 = arr1;
|
||||
gsl::span<int> s2 = arr2;
|
||||
|
||||
EXPECT_TRUE(s1 == s2);
|
||||
EXPECT_FALSE(s1 != s2);
|
||||
@ -320,8 +320,8 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
{
|
||||
int arr[] = {1, 2, 3};
|
||||
|
||||
span<int> s1 = {&arr[0], 2}; // shorter
|
||||
span<int> s2 = arr; // longer
|
||||
gsl::span<int> s1 = {&arr[0], 2}; // shorter
|
||||
gsl::span<int> s2 = arr; // longer
|
||||
|
||||
EXPECT_TRUE(s1 != s2);
|
||||
EXPECT_TRUE(s2 != s1);
|
||||
@ -341,8 +341,8 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
int arr1[] = {1, 2}; // smaller
|
||||
int arr2[] = {2, 1}; // bigger
|
||||
|
||||
span<int> s1 = arr1;
|
||||
span<int> s2 = arr2;
|
||||
gsl::span<int> s1 = arr1;
|
||||
gsl::span<int> s2 = arr2;
|
||||
|
||||
EXPECT_TRUE(s1 != s2);
|
||||
EXPECT_TRUE(s2 != s1);
|
||||
@ -357,4 +357,5 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
||||
EXPECT_TRUE(s2 >= s1);
|
||||
EXPECT_FALSE(s1 >= s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // GSL_KERNEL_MODE
|
||||
|
@ -17,19 +17,19 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <gsl/byte> // for byte
|
||||
#include <gsl/util> // for narrow_cast, at
|
||||
#include <gsl/span> // for span, span_iterator, operator==, operator!=
|
||||
#include <gsl/util> // for narrow_cast, at
|
||||
|
||||
#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,12 +276,12 @@ 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};
|
||||
|
||||
{
|
||||
@ -292,7 +298,7 @@ TEST(span_test, from_array_constructor)
|
||||
|
||||
int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
span<int, 6> s{arr};
|
||||
}
|
||||
@ -320,7 +326,7 @@ TEST(span_test, from_array_constructor)
|
||||
{
|
||||
span<int, 6> s{arr2d};
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
const span<int[3]> s{std::addressof(arr2d[0]), 1};
|
||||
EXPECT_TRUE(s.size() == 1);
|
||||
@ -329,7 +335,7 @@ TEST(span_test, from_array_constructor)
|
||||
|
||||
int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
span<int> s{arr3d};
|
||||
EXPECT_TRUE(s.size() == 12);
|
||||
@ -355,7 +361,7 @@ TEST(span_test, from_array_constructor)
|
||||
EXPECT_TRUE(s[0] == 1);
|
||||
EXPECT_TRUE(s[5] == 6);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
const span<int[3][2]> s{std::addressof(arr3d[0]), 1};
|
||||
EXPECT_TRUE(s.size() == 1);
|
||||
@ -368,10 +374,10 @@ TEST(span_test, from_array_constructor)
|
||||
EXPECT_TRUE(s.size() == 5);
|
||||
EXPECT_TRUE(s.data() == std::addressof(ao_arr[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, from_dynamic_array_constructor)
|
||||
{
|
||||
TEST(span_test, from_dynamic_array_constructor)
|
||||
{
|
||||
double(*arr)[3][4] = new double[100][3][4];
|
||||
|
||||
{
|
||||
@ -381,10 +387,10 @@ TEST(span_test, from_array_constructor)
|
||||
}
|
||||
|
||||
delete[] arr;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, from_std_array_constructor)
|
||||
{
|
||||
TEST(span_test, from_std_array_constructor)
|
||||
{
|
||||
std::array<int, 4> arr = {1, 2, 3, 4};
|
||||
|
||||
{
|
||||
@ -422,7 +428,7 @@ TEST(span_test, from_array_constructor)
|
||||
EXPECT_TRUE(ao_arr.data() == fs.data());
|
||||
}
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
span<int, 2> s{arr};
|
||||
EXPECT_TRUE(s.size() == 2);
|
||||
@ -453,7 +459,7 @@ TEST(span_test, from_array_constructor)
|
||||
// try to take a temporary std::array
|
||||
take_a_span(get_an_array());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
{
|
||||
auto get_an_array = []() -> std::array<int, 4> { return {1, 2, 3, 4}; };
|
||||
@ -461,10 +467,10 @@ TEST(span_test, from_array_constructor)
|
||||
// try to take a temporary std::array
|
||||
take_a_span(get_an_array());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, from_const_std_array_constructor)
|
||||
{
|
||||
TEST(span_test, from_const_std_array_constructor)
|
||||
{
|
||||
const std::array<int, 4> arr = {1, 2, 3, 4};
|
||||
|
||||
{
|
||||
@ -487,7 +493,7 @@ TEST(span_test, from_array_constructor)
|
||||
EXPECT_TRUE(s.data() == ao_arr.data());
|
||||
}
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
span<const int, 2> s{arr};
|
||||
EXPECT_TRUE(s.size() == 2);
|
||||
@ -503,7 +509,7 @@ TEST(span_test, from_array_constructor)
|
||||
{
|
||||
span<const int, 5> s{arr};
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
{
|
||||
auto get_an_array = []() -> const std::array<int, 4> { return {1, 2, 3, 4}; };
|
||||
@ -511,10 +517,10 @@ TEST(span_test, from_array_constructor)
|
||||
// try to take a temporary std::array
|
||||
take_a_span(get_an_array());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, from_std_array_const_constructor)
|
||||
{
|
||||
TEST(span_test, from_std_array_const_constructor)
|
||||
{
|
||||
std::array<const int, 4> arr = {1, 2, 3, 4};
|
||||
|
||||
{
|
||||
@ -529,7 +535,7 @@ TEST(span_test, from_array_constructor)
|
||||
EXPECT_TRUE(s.data() == arr.data());
|
||||
}
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
span<const int, 2> s{arr};
|
||||
EXPECT_TRUE(s.size() == 2);
|
||||
@ -549,11 +555,11 @@ TEST(span_test, from_array_constructor)
|
||||
{
|
||||
span<int, 4> s{arr};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(span_test, from_container_constructor)
|
||||
{
|
||||
TEST(span_test, from_container_constructor)
|
||||
{
|
||||
std::vector<int> v = {1, 2, 3};
|
||||
const std::vector<int> cv = v;
|
||||
|
||||
@ -571,31 +577,31 @@ TEST(span_test, from_array_constructor)
|
||||
const std::string cstr = "hello";
|
||||
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#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
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
span<char> s{cstr};
|
||||
#endif
|
||||
#endif
|
||||
span<const char> cs{cstr};
|
||||
EXPECT_TRUE(cs.size() == cstr.size());
|
||||
EXPECT_TRUE(cs.data() == cstr.data());
|
||||
}
|
||||
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#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
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
@ -605,11 +611,11 @@ TEST(span_test, from_array_constructor)
|
||||
}
|
||||
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#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
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
@ -619,11 +625,11 @@ TEST(span_test, from_array_constructor)
|
||||
}
|
||||
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#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
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
@ -633,49 +639,49 @@ TEST(span_test, from_array_constructor)
|
||||
}
|
||||
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
std::map<int, int> m;
|
||||
span<int> s{m};
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, from_convertible_span_constructor){{span<DerivedClass> avd;
|
||||
span<const DerivedClass> avcd = avd;
|
||||
static_cast<void>(avcd);
|
||||
}
|
||||
TEST(span_test, from_convertible_span_constructor){{span<DerivedClass> avd;
|
||||
span<const DerivedClass> avcd = avd;
|
||||
static_cast<void>(avcd);
|
||||
}
|
||||
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
span<DerivedClass> avd;
|
||||
span<BaseClass> avb = avd;
|
||||
static_cast<void>(avb);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
#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
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(span_test, copy_move_and_assignment)
|
||||
{
|
||||
TEST(span_test, copy_move_and_assignment)
|
||||
{
|
||||
span<int> s1;
|
||||
EXPECT_TRUE(s1.empty());
|
||||
|
||||
@ -692,19 +698,22 @@ TEST(span_test, from_array_constructor)
|
||||
auto use_span = [&](span<const int> s) {
|
||||
EXPECT_TRUE(s.size() == 2);
|
||||
EXPECT_TRUE(s.data() == &arr[1]);
|
||||
}; use_span(get_temp_span());
|
||||
};
|
||||
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([] {
|
||||
TEST(span_test, first)
|
||||
{
|
||||
const auto terminateHandler = std::set_terminate([] {
|
||||
std::cerr << "Expected Death. first";
|
||||
std::abort();
|
||||
});
|
||||
const auto expected = GetExpectedDeathString(terminateHandler);
|
||||
|
||||
int arr[5] = {1, 2, 3, 4, 5};
|
||||
|
||||
{
|
||||
@ -727,11 +736,11 @@ TEST(span_test, from_array_constructor)
|
||||
|
||||
{
|
||||
span<int, 5> av = arr;
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#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);
|
||||
#endif
|
||||
EXPECT_DEATH(av.first(6).size(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
@ -739,14 +748,16 @@ TEST(span_test, from_array_constructor)
|
||||
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();
|
||||
});
|
||||
const auto expected = GetExpectedDeathString(terminateHandler);
|
||||
|
||||
int arr[5] = {1, 2, 3, 4, 5};
|
||||
|
||||
{
|
||||
@ -769,10 +780,10 @@ TEST(span_test, from_array_constructor)
|
||||
|
||||
{
|
||||
span<int, 5> av = arr;
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
EXPECT_TRUE(av.last<6>().size() == 6);
|
||||
#endif
|
||||
EXPECT_DEATH(av.last(6).size(), deathstring);
|
||||
#endif
|
||||
EXPECT_DEATH(av.last(6).size(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
@ -780,14 +791,16 @@ TEST(span_test, from_array_constructor)
|
||||
EXPECT_TRUE(av.last<0>().size() == 0);
|
||||
EXPECT_TRUE(av.last(0).size() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, subspan)
|
||||
{
|
||||
std::set_terminate([] {
|
||||
TEST(span_test, subspan)
|
||||
{
|
||||
const auto terminateHandler = std::set_terminate([] {
|
||||
std::cerr << "Expected Death. subspan";
|
||||
std::abort();
|
||||
});
|
||||
const auto expected = GetExpectedDeathString(terminateHandler);
|
||||
|
||||
int arr[5] = {1, 2, 3, 4, 5};
|
||||
|
||||
{
|
||||
@ -811,8 +824,8 @@ TEST(span_test, from_array_constructor)
|
||||
EXPECT_TRUE(decltype(av.subspan<0, 5>())::extent == 5);
|
||||
EXPECT_TRUE(av.subspan(0, 5).size() == 5);
|
||||
|
||||
EXPECT_DEATH(av.subspan(0, 6).size(), deathstring);
|
||||
EXPECT_DEATH(av.subspan(1, 5).size(), deathstring);
|
||||
EXPECT_DEATH(av.subspan(0, 6).size(), expected);
|
||||
EXPECT_DEATH(av.subspan(1, 5).size(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
@ -821,7 +834,7 @@ TEST(span_test, from_array_constructor)
|
||||
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(6, 0).size(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
@ -835,13 +848,13 @@ TEST(span_test, from_array_constructor)
|
||||
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);
|
||||
EXPECT_DEATH((av.subspan<1, 0>().size()), expected);
|
||||
}
|
||||
|
||||
{
|
||||
span<int> av;
|
||||
EXPECT_TRUE(av.subspan(0).size() == 0);
|
||||
EXPECT_DEATH(av.subspan(1).size(), deathstring);
|
||||
EXPECT_DEATH(av.subspan(1).size(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
@ -850,7 +863,7 @@ TEST(span_test, from_array_constructor)
|
||||
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);
|
||||
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);
|
||||
}
|
||||
@ -861,21 +874,21 @@ TEST(span_test, from_array_constructor)
|
||||
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);
|
||||
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, iterator_default_init)
|
||||
{
|
||||
TEST(span_test, iterator_default_init)
|
||||
{
|
||||
span<int>::iterator it1;
|
||||
span<int>::iterator it2;
|
||||
EXPECT_TRUE(it1 == it2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, iterator_comparisons)
|
||||
{
|
||||
TEST(span_test, iterator_comparisons)
|
||||
{
|
||||
int a[] = {1, 2, 3, 4};
|
||||
{
|
||||
span<int> s = a;
|
||||
@ -902,14 +915,15 @@ TEST(span_test, from_array_constructor)
|
||||
EXPECT_TRUE(s.end() > it2);
|
||||
EXPECT_TRUE(s.end() >= it2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, incomparable_iterators)
|
||||
{
|
||||
std::set_terminate([] {
|
||||
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};
|
||||
@ -917,21 +931,23 @@ TEST(span_test, from_array_constructor)
|
||||
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();
|
||||
});
|
||||
const auto expected = GetExpectedDeathString(terminateHandler);
|
||||
|
||||
{
|
||||
int a[] = {1, 2, 3, 4};
|
||||
span<int> s = a;
|
||||
@ -956,7 +972,7 @@ TEST(span_test, from_array_constructor)
|
||||
|
||||
auto beyond = s.end();
|
||||
EXPECT_TRUE(it != beyond);
|
||||
EXPECT_DEATH(*beyond, deathstring);
|
||||
EXPECT_DEATH(*beyond, expected);
|
||||
|
||||
EXPECT_TRUE(beyond - first == 4);
|
||||
EXPECT_TRUE(first - first == 0);
|
||||
@ -982,14 +998,16 @@ TEST(span_test, from_array_constructor)
|
||||
|
||||
for (const auto& n : s) { EXPECT_TRUE(n == 5); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, rbegin_rend)
|
||||
{
|
||||
std::set_terminate([] {
|
||||
TEST(span_test, rbegin_rend)
|
||||
{
|
||||
const auto terminateHandler = std::set_terminate([] {
|
||||
std::cerr << "Expected Death. rbegin_rend";
|
||||
std::abort();
|
||||
});
|
||||
const auto expected = GetExpectedDeathString(terminateHandler);
|
||||
|
||||
{
|
||||
int a[] = {1, 2, 3, 4};
|
||||
span<int> s = a;
|
||||
@ -1002,9 +1020,9 @@ TEST(span_test, from_array_constructor)
|
||||
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);
|
||||
@ -1031,14 +1049,15 @@ TEST(span_test, from_array_constructor)
|
||||
|
||||
for (const auto& n : s) { EXPECT_TRUE(n == 5); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, as_bytes)
|
||||
{
|
||||
std::set_terminate([] {
|
||||
TEST(span_test, as_bytes)
|
||||
{
|
||||
const auto terminateHandler = std::set_terminate([] {
|
||||
std::cerr << "Expected Death. as_bytes";
|
||||
std::abort();
|
||||
});
|
||||
const auto expected = GetExpectedDeathString(terminateHandler);
|
||||
|
||||
int a[] = {1, 2, 3, 4};
|
||||
{
|
||||
@ -1068,24 +1087,24 @@ TEST(span_test, from_array_constructor)
|
||||
|
||||
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);
|
||||
}
|
||||
span<int> sp(std::begin(b), static_cast<size_t>(-2));
|
||||
EXPECT_DEATH((void) sp.size_bytes(), expected);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(span_test, as_writable_bytes)
|
||||
{
|
||||
TEST(span_test, as_writable_bytes)
|
||||
{
|
||||
int a[] = {1, 2, 3, 4};
|
||||
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#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
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
@ -1104,14 +1123,16 @@ TEST(span_test, from_array_constructor)
|
||||
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();
|
||||
});
|
||||
const auto expected = GetExpectedDeathString(terminateHandler);
|
||||
|
||||
int arr[] = {1, 2, 3, 4};
|
||||
|
||||
// converting to an span from an equal size array is ok
|
||||
@ -1125,8 +1146,8 @@ TEST(span_test, from_array_constructor)
|
||||
static_cast<void>(s);
|
||||
}
|
||||
|
||||
// initialization or assignment to static span that REDUCES size is NOT ok
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
// initialization or assignment to static span that REDUCES size is NOT ok
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
span<int, 2> s = arr;
|
||||
}
|
||||
@ -1134,7 +1155,7 @@ TEST(span_test, from_array_constructor)
|
||||
span<int, 2> s2 = s4;
|
||||
static_cast<void>(s2);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// even when done dynamically
|
||||
{
|
||||
@ -1146,7 +1167,7 @@ TEST(span_test, from_array_constructor)
|
||||
const span<int, 2> s2 = s;
|
||||
static_cast<void>(s2);
|
||||
};
|
||||
EXPECT_DEATH(f(), deathstring);
|
||||
EXPECT_DEATH(f(), expected);
|
||||
*/
|
||||
}
|
||||
|
||||
@ -1179,7 +1200,7 @@ TEST(span_test, from_array_constructor)
|
||||
// initialization or assignment to static span that requires size INCREASE is not ok.
|
||||
int arr2[2] = {1, 2};
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
span<int, 4> s3 = arr2;
|
||||
}
|
||||
@ -1187,28 +1208,29 @@ TEST(span_test, from_array_constructor)
|
||||
span<int, 2> s2 = arr2;
|
||||
span<int, 4> s4a = s2;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
auto f = [&]() {
|
||||
const span<int, 4> _s4{arr2, 2};
|
||||
static_cast<void>(_s4);
|
||||
};
|
||||
EXPECT_DEATH(f(), deathstring);
|
||||
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)
|
||||
{
|
||||
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;
|
||||
@ -1228,21 +1250,21 @@ TEST(span_test, from_array_constructor)
|
||||
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)
|
||||
{
|
||||
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, 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
|
||||
|
@ -14,30 +14,40 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
struct fail_fast;
|
||||
} // namespace gsl
|
||||
#include "deathTestCommon.h"
|
||||
|
||||
using namespace gsl;
|
||||
|
||||
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
|
||||
|
@ -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');
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user