pax_global_header00006660000000000000000000000064141750753230014521gustar00rootroot0000000000000052 comment=a3534567187d2edc428efd3f13466ff75fe5805c GSL-4.0.0/000077500000000000000000000000001417507532300121475ustar00rootroot00000000000000GSL-4.0.0/.clang-format000066400000000000000000000014101417507532300145160ustar00rootroot00000000000000ColumnLimit: 100 UseTab: Never IndentWidth: 4 AccessModifierOffset: -4 NamespaceIndentation: Inner BreakBeforeBraces: Custom BraceWrapping: AfterNamespace: true AfterEnum: true AfterStruct: true AfterClass: true SplitEmptyFunction: false AfterControlStatement: true AfterFunction: true AfterUnion: true BeforeElse: true AlwaysBreakTemplateDeclarations: true BreakConstructorInitializersBeforeComma: true ConstructorInitializerAllOnOneLineOrOnePerLine: true AllowShortBlocksOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: true PointerAlignment: Left AlignConsecutiveAssignments: false AlignTrailingComments: true SpaceAfterCStyleCast: true CommentPragmas: '^ NO-FORMAT:' GSL-4.0.0/.github/000077500000000000000000000000001417507532300135075ustar00rootroot00000000000000GSL-4.0.0/.github/workflows/000077500000000000000000000000001417507532300155445ustar00rootroot00000000000000GSL-4.0.0/.github/workflows/android.yml000066400000000000000000000034551417507532300177160ustar00rootroot00000000000000name: CI_Android on: push: branches: [ main ] pull_request: branches: [ main ] jobs: Android: runs-on: macos-latest defaults: run: working-directory: build steps: - uses: actions/checkout@v2 - name: Create build directory run: mkdir -p build working-directory: . - name: Start emulator run: | echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-24;default;x86_64' echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n xamarin_android_emulator -k 'system-images;android-24;default;x86_64' --force $ANDROID_HOME/emulator/emulator -list-avds echo "Starting emulator" # Start emulator in background nohup $ANDROID_HOME/emulator/emulator -avd xamarin_android_emulator -no-snapshot > /dev/null 2>&1 & 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 .. - name: Build run: cmake --build . --parallel - name: Wait for emulator ready run: | $ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 10; done; input keyevent 82' $ANDROID_HOME/platform-tools/adb devices $ANDROID_HOME/platform-tools/adb shell getprop ro.product.cpu.abi echo "Emulator started" - name: Deploy tests run: | adb push tests /data/local/tmp adb shell find /data/local/tmp/tests -maxdepth 1 -exec chmod +x {} \\\; - name: Test run: adb shell find /data/local/tmp/tests -name "*_tests" -maxdepth 1 -exec {} \\\; GSL-4.0.0/.github/workflows/ios.yml000066400000000000000000000032021417507532300170560ustar00rootroot00000000000000name: CI_iOS on: push: branches: [ main ] pull_request: branches: [ main ] jobs: iOS: runs-on: macos-latest defaults: run: working-directory: build steps: - uses: actions/checkout@v2 - name: Create build directory run: mkdir -p build working-directory: . - name: Configure run: | cmake \ -Werror=dev \ -GXcode \ -DCMAKE_SYSTEM_NAME=iOS \ "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \ -DCMAKE_OSX_DEPLOYMENT_TARGET=9 \ -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \ "-DMACOSX_BUNDLE_GUI_IDENTIFIER=GSL.\$(EXECUTABLE_NAME)" \ -DMACOSX_BUNDLE_BUNDLE_VERSION=3.1.0 \ -DMACOSX_BUNDLE_SHORT_VERSION_STRING=3.1.0 \ .. - name: Build run: cmake --build . --parallel `sysctl -n hw.ncpu` --config Release -- -sdk iphonesimulator - name: Start simulator run: | RUNTIME=`xcrun simctl list runtimes iOS -j|jq '.runtimes|last.identifier'` UDID=`xcrun simctl list devices iPhone available -j|jq -r ".devices[$RUNTIME]|last.udid"` xcrun simctl bootstatus $UDID -b - name: Test run: | for TEST in `find tests/Release-iphonesimulator -depth 1 -name "*.app"` do xcrun simctl install booted $TEST TEST_ID=`plutil -convert json -o - $TEST/Info.plist|jq -r ".CFBundleIdentifier"` xcrun simctl launch --console booted $TEST_ID xcrun simctl uninstall booted $TEST_ID done GSL-4.0.0/.gitignore000066400000000000000000000002611417507532300141360ustar00rootroot00000000000000CMakeFiles build tests/CMakeFiles tests/Debug *.opensdf *.sdf tests/*tests.dir *.vcxproj *.vcxproj.filters *.sln *.tlog Testing/Temporary/*.* CMakeCache.txt *.suo .vs/ .vscode/ GSL-4.0.0/CMakeLists.txt000066400000000000000000000033101417507532300147040ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.1.3...3.16) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") include(guidelineSupportLibrary) project(GSL VERSION 4.0.0 LANGUAGES CXX ) # Must include after the project call due to GNUInstallDirs requiring a language be enabled (IE. CXX) include(GNUInstallDirs) # Creates a library GSL which is an interface (header files only) add_library(GSL INTERFACE) # NOTE: If you want to use GSL prefer to link against GSL using this alias target # EX: # target_link_libraries(foobar PRIVATE Microsoft.GSL::GSL) # # Add Microsoft.GSL::GSL alias for GSL so that dependents can be agnostic about # whether GSL was added via `add_subdirectory` or `find_package` add_library(Microsoft.GSL::GSL ALIAS GSL) # Determine whether this is a standalone project or included by other projects set(GSL_STANDALONE_PROJECT OFF) if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(GSL_STANDALONE_PROJECT ON) endif() ### Project options option(GSL_INSTALL "Generate and install GSL target" ${GSL_STANDALONE_PROJECT}) option(GSL_TEST "Build and perform GSL tests" ${GSL_STANDALONE_PROJECT}) # This GSL implementation generally assumes a platform that implements C++14 support. set(gsl_min_cxx_standard "14") if (GSL_STANDALONE_PROJECT) gsl_set_default_cxx_standard(${gsl_min_cxx_standard}) else() gsl_client_set_cxx_standard(${gsl_min_cxx_standard}) endif() # Setup include directory add_subdirectory(include) # Add natvis file gsl_add_native_visualizer_support() # Add packaging support gsl_create_packaging_file() if (GSL_INSTALL) # Setup install/export logic gsl_install_logic() endif() if (GSL_TEST) enable_testing() add_subdirectory(tests) endif() GSL-4.0.0/CMakeSettings.json000066400000000000000000000010411417507532300155370ustar00rootroot00000000000000{ "configurations": [ { "name": "x64-Debug", "generator": "Ninja", "configurationType": "Debug", "inheritEnvironments": [ "msvc_x64_x64" ], "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", "cmakeCommandArgs": "-DGSL_CXX_STANDARD=17", "buildCommandArgs": "-v", "ctestCommandArgs": "", "codeAnalysisRuleset": "CppCoreCheckRules.ruleset" } ] }GSL-4.0.0/CONTRIBUTING.md000066400000000000000000000037221417507532300144040ustar00rootroot00000000000000## Contributing to the Guidelines Support Library The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines). GSL design changes are made only as a result of modifications to the Guidelines. GSL is accepting contributions that improve or refine any of the types in this library as well as ports to other platforms. Changes should have an issue tracking the suggestion that has been approved by the maintainers. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR, please post a comment in the associated issue to avoid duplication of effort. ## Legal You will need to complete a Contributor License Agreement (CLA). Briefly, this agreement testifies that you are granting us and the community permission to use the submitted change according to the terms of the project's license, and that the work being submitted is under appropriate copyright. Please submit a Contributor License Agreement (CLA) before submitting a pull request. You may visit https://cla.microsoft.com to sign digitally. ## Housekeeping Your pull request should: * Include a description of what your change intends to do * Be a child commit of a reasonably recent commit in the **main** branch * Requests need not be a single commit, but should be a linear sequence of commits (i.e. no merge commits in your PR) * It is desirable, but not necessary, for the tests to pass at each commit. Please see [README.md](./README.md) for instructions to build the test suite. * Have clear commit messages * e.g. "Fix issue", "Add tests for type", etc. * Include appropriate tests * Tests should include reasonable permutations of the target fix/change * Include baseline changes with your change * All changed code must have 100% code coverage * To avoid line ending issues, set `autocrlf = input` and `whitespace = cr-at-eol` in your git configuration GSL-4.0.0/GSL.natvis000066400000000000000000000042141417507532300140230ustar00rootroot00000000000000 {_Data._What,nasb} {{ invoke = {invoke_}, action = {f_} }} invoke_ f_ {{ extent = {storage_.size_} }} storage_.size_ storage_.data_ {span_.storage_.data_,[span_.storage_.size_]na} span_.storage_.size_ span_.storage_.size_ span_.storage_.data_ {span_.storage_.data_,[span_.storage_.size_]na} span_.storage_.size_ span_.storage_.size_ span_.storage_.data_ value = {*ptr_} GSL-4.0.0/LICENSE000066400000000000000000000022051417507532300131530ustar00rootroot00000000000000Copyright (c) 2015 Microsoft Corporation. All rights reserved. This code is licensed under the MIT License (MIT). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. GSL-4.0.0/README.md000066400000000000000000000331101417507532300134240ustar00rootroot00000000000000# GSL: Guidelines Support Library [![Build Status](https://dev.azure.com/cppstat/GSL/_apis/build/status/microsoft.GSL?branchName=main)](https://dev.azure.com/cppstat/GSL/_build/latest?definitionId=1&branchName=main) The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org). This repo contains Microsoft's implementation of GSL. The entire implementation is provided inline in the headers under the [gsl](./include/gsl) directory. The implementation generally assumes a platform that implements C++14 support. While some types have been broken out into their own headers (e.g. [gsl/span](./include/gsl/span)), it is simplest to just include [gsl/gsl](./include/gsl/gsl) and gain access to the entire library. > NOTE: We encourage contributions that improve or refine any of the types in this library as well as ports to other platforms. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for more information about contributing. # Project Code of Conduct This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. # Usage of Third Party Libraries This project makes use of the [Google Test](https://github.com/google/googletest) testing library. Please see the [ThirdPartyNotices.txt](./ThirdPartyNotices.txt) file for details regarding the licensing of Google Test. # Supported features ## Microsoft GSL implements the following from the C++ Core Guidelines: Feature | Supported? | Description -----------------------------------|:----------:|------------- [**1. Views**][cg-views] | | owner | ☑ | an alias for a raw pointer not_null | ☑ | restricts a pointer / smart pointer to hold non-null values span | ☑ | a view over a contiguous sequence of memory. Based on the standardized verison of `std::span`, however `gsl::span` enforces bounds checking. See the [wiki](https://github.com/microsoft/GSL/wiki/gsl::span-and-std::span) for additional information. span_p | ☐ | spans a range starting from a pointer to the first place for which the predicate is true basic_zstring | ☑ | A pointer to a C-string (zero-terminated array) with a templated char type zstring | ☑ | An alias to `basic_zstring` with 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` stack_array | ☐ | a stack-allocated array dyn_array | ☐ | a heap-allocated array [**3. Assertions**][cg-assertions] | | Expects | ☑ | a precondition assertion; on failure it terminates Ensures | ☑ | a postcondition assertion; on failure it terminates [**4. Utilities**][cg-utilities] | | move_owner | ☐ | a helper function that moves one `owner` to the other byte | ☑ | either an alias to std::byte or a byte type final_action | ☑ | a RAII style class that invokes a functor on its destruction finally | ☑ | a helper function instantiating `final_action` GSL_SUPPRESS | ☑ | a macro that takes an argument and turns it into `[[gsl::suppress(x)]]` or `[[gsl::suppress("x")]]` [[implicit]] | ☐ | a "marker" to put on single-argument constructors to explicitly make them non-explicit index | ☑ | a type to use for all container and array indexing (currently an alias for std::ptrdiff_t) joining_thread | ☐ | a RAII style version of `std::thread` that joins narrow | ☑ | a checked version of narrow_cast; it can throw `narrowing_error` narrow_cast | ☑ | a narrowing cast for values and a synonym for static_cast narrowing_error | ☑ | a custom exception type thrown by `narrow()` [**5. Concepts**][cg-concepts] | ☐ | ## The following features do not exist in or have been removed from the C++ Core Guidelines: Feature | Supported? | Description -----------------------------------|:----------:|------------- strict_not_null | ☑ | A stricter version of `not_null` with explicit constructors multi_span | ☐ | Deprecated. Multi-dimensional span. strided_span | ☐ | Deprecated. Support for this type has been discontinued. basic_string_span | ☐ | Deprecated. Like `span` but for strings with a templated char type string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of char cstring_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of const char wstring_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of wchar_t cwstring_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of const wchar_t u16string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of char16_t cu16string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of const char16_t u32string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of char32_t cu32string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of const char32_t This is based on [CppCoreGuidelines semi-specification](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gsl-guidelines-support-library). [cg-views]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslview-views [cg-owners]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslowner-ownership-pointers [cg-assertions]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslassert-assertions [cg-utilities]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslutil-utilities [cg-concepts]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslconcept-concepts # Quick Start ## 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 | 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! - Submit an issue specifying the platform and target. - Consider contributing your changes by filing a pull request with any necessary changes. - If at all possible, add a CI/CD step and add the button to the table below! Target | CI/CD Status :------- | -----------: iOS | ![CI_iOS](https://github.com/microsoft/GSL/workflows/CI_iOS/badge.svg) Android | ![CI_Android](https://github.com/microsoft/GSL/workflows/CI_Android/badge.svg) Note: These CI/CD steps are run with each pull request, however failures in them are non-blocking. ## Building the tests To build the tests, you will require the following: * [CMake](http://cmake.org), version 3.1.3 (3.2.3 for AppleClang) or later to be installed and in your PATH. These steps assume the source code of this repository has been cloned into a directory named `c:\GSL`. 1. Create a directory to contain the build outputs for a particular architecture (we name it c:\GSL\build-x86 in this example). cd GSL md build-x86 cd build-x86 2. Configure CMake to use the compiler of your choice (you can see a list by running `cmake --help`). cmake -G "Visual Studio 15 2017" c:\GSL 3. Build the test suite (in this case, in the Debug configuration, Release is another good choice). cmake --build . --config Debug 4. Run the test suite. ctest -C Debug All tests should pass - indicating your platform is fully supported and you are ready to use the GSL types! ## Building GSL - Using vcpkg You can download and install GSL using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install vcpkg install ms-gsl The GSL port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. ## Using the libraries As the types are entirely implemented inline in headers, there are no linking requirements. You can copy the [gsl](./include/gsl) directory into your source tree so it is available to your compiler, then include the appropriate headers in your program. Alternatively set your compiler's *include path* flag to point to the GSL development folder (`c:\GSL\include` in the example above) or installation folder (after running the install). Eg. MSVC++ /I c:\GSL\include GCC/clang -I$HOME/dev/GSL/include Include the library using: #include ## Usage in CMake The library provides a Config file for CMake, once installed it can be found via find_package(Microsoft.GSL CONFIG) Which, when successful, will add library target called `Microsoft.GSL::GSL` which you can use via the usual `target_link_libraries` mechanism. ### FetchContent If you are using cmake version 3.11+ you can use the offical FetchContent module. This allows you to easily incorporate GSL into your project. ```cmake # NOTE: This example uses cmake version 3.14 (FetchContent_MakeAvailable). # Since it streamlines the FetchContent process cmake_minimum_required(VERSION 3.14) include(FetchContent) # In this example we are picking a specific tag. # You can also pick a specific commit, if you need to. FetchContent_Declare(GSL GIT_REPOSITORY "https://github.com/microsoft/GSL" GIT_TAG "v3.1.0" ) FetchContent_MakeAvailable(GSL) # Now you can link against the GSL interface library add_executable(foobar) # Link against the interface library (IE header only library) target_link_libraries(foobar PRIVATE GSL) ``` ## Debugging visualization support For Visual Studio users, the file [GSL.natvis](./GSL.natvis) in the root directory of the repository can be added to your project if you would like more helpful visualization of GSL types in the Visual Studio debugger than would be offered by default. If you are using cmake this will be done automatically for you. See 'GSL_VS_ADD_NATIVE_VISUALIZERS' GSL-4.0.0/ThirdPartyNotices.txt000066400000000000000000000037461417507532300163410ustar00rootroot00000000000000 THIRD-PARTY SOFTWARE NOTICES AND INFORMATION Do Not Translate or Localize GSL: Guidelines Support Library incorporates third party material from the projects listed below. ------------------------------------------------------------------------------- Software: Google Test Owner: Google Inc. Source URL: github.com/google/googletest License: BSD 3 - Clause Text: Copyright 2008, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- GSL-4.0.0/azure-pipelines.yml000066400000000000000000000026171417507532300160140ustar00rootroot00000000000000trigger: - main pr: autoCancel: true stages: - stage: GCC dependsOn: [] jobs: - template: ./pipelines/jobs.yml parameters: compiler: gcc image: ubuntu-20.04 compilerVersions: [ 11, 10 ] setupfile: 'setup_gcc.yml' - stage: Clang dependsOn: [] jobs: - template: ./pipelines/jobs.yml parameters: compiler: clang image: ubuntu-20.04 compilerVersions: [ 12, 11 ] setupfile: 'setup_clang.yml' - stage: Xcode dependsOn: [] jobs: - template: ./pipelines/jobs.yml parameters: compiler: 'Xcode' image: macOS-11 compilerVersions: [ '12.5.1', '13.2.1' ] setupfile: 'setup_apple.yml' - stage: VS_MSVC dependsOn: [] jobs: - template: ./pipelines/jobs.yml parameters: compiler: 'VS2019 (MSVC)' compilerVersions: [ 'default' ] image: windows-2019 - template: ./pipelines/jobs.yml parameters: 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' GSL-4.0.0/cmake/000077500000000000000000000000001417507532300132275ustar00rootroot00000000000000GSL-4.0.0/cmake/guidelineSupportLibrary.cmake000066400000000000000000000112401417507532300211160ustar00rootroot00000000000000# This cmake module is meant to hold helper functions/macros # that make maintaining the cmake build system much easier. # This is especially helpful since gsl needs to provide coverage # for multiple versions of cmake. # # Any functions/macros should have a gsl_* prefix to avoid problems if (CMAKE_VERSION VERSION_GREATER 3.10 OR CMAKE_VERSION VERSION_EQUAL 3.10) include_guard() else() if (DEFINED guideline_support_library_include_guard) return() endif() set(guideline_support_library_include_guard ON) endif() # Necessary for 'write_basic_package_version_file' include(CMakePackageConfigHelpers) function(gsl_set_default_cxx_standard min_cxx_standard) set(GSL_CXX_STANDARD "${min_cxx_standard}" CACHE STRING "Use c++ standard") set(GSL_CXX_STD "cxx_std_${GSL_CXX_STANDARD}") if (MSVC) set(GSL_CXX_STD_OPT "-std:c++${GSL_CXX_STANDARD}") else() set(GSL_CXX_STD_OPT "-std=c++${GSL_CXX_STANDARD}") endif() # when minimum version required is 3.8.0 remove if below # both branches do exactly the same thing if (CMAKE_VERSION VERSION_LESS 3.7.9) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("${GSL_CXX_STD_OPT}" COMPILER_SUPPORTS_CXX_STANDARD) if(COMPILER_SUPPORTS_CXX_STANDARD) target_compile_options(GSL INTERFACE "${GSL_CXX_STD_OPT}") else() message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no c++${GSL_CXX_STANDARD} support. Please use a different C++ compiler.") endif() else() target_compile_features(GSL INTERFACE "${GSL_CXX_STD}") # on *nix systems force the use of -std=c++XX instead of -std=gnu++XX (default) set(CMAKE_CXX_EXTENSIONS OFF) endif() endfunction() # The best way for a project to specify the GSL's C++ standard is by the client specifying # the CMAKE_CXX_STANDARD. However, this isn't always ideal. Since the CMAKE_CXX_STANDARD is # tied to the cmake version. And many projects have low cmake minimums. # # So provide an alternative approach in case that doesn't work. function(gsl_client_set_cxx_standard min_cxx_standard) if (DEFINED CMAKE_CXX_STANDARD) if (${CMAKE_CXX_STANDARD} VERSION_LESS ${min_cxx_standard}) message(FATAL_ERROR "GSL: Requires at least CXX standard ${min_cxx_standard}, user provided ${CMAKE_CXX_STANDARD}") endif() # Set the GSL standard to what the client desires set(GSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}" PARENT_SCOPE) # Exit out early to avoid extra unneccessary work return() endif() # Otherwise pick a reasonable default gsl_set_default_cxx_standard(${min_cxx_standard}) endfunction() # Adding the GSL.natvis files improves the debugging experience for users of this library. function(gsl_add_native_visualizer_support) if (CMAKE_VERSION VERSION_GREATER 3.7.8) if (MSVC_IDE) option(GSL_VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE) else() set(GSL_VS_ADD_NATIVE_VISUALIZERS FALSE CACHE INTERNAL "Native visualizers are Visual Studio extension" FORCE) endif() # add natvis file to the library so it will automatically be loaded into Visual Studio if(GSL_VS_ADD_NATIVE_VISUALIZERS) target_sources(GSL INTERFACE $) endif() endif() endfunction() function(gsl_install_logic) install(TARGETS GSL EXPORT Microsoft.GSLConfig) install( DIRECTORY include/gsl DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) # Make library importable by other projects install(EXPORT Microsoft.GSLConfig NAMESPACE Microsoft.GSL:: DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL) export(TARGETS GSL NAMESPACE Microsoft.GSL:: FILE Microsoft.GSLConfig.cmake) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL) endfunction() # Add find_package() versioning support. The version for # generated Microsoft.GSLConfigVersion.cmake will be used from # last project() command. The version's compatibility is set between all # minor versions (as it was in prev. GSL releases). function(gsl_create_packaging_file) if(${CMAKE_VERSION} VERSION_LESS "3.14.0") write_basic_package_version_file( ${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake COMPATIBILITY SameMajorVersion ) else() write_basic_package_version_file( ${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT ) endif() endfunction() GSL-4.0.0/include/000077500000000000000000000000001417507532300135725ustar00rootroot00000000000000GSL-4.0.0/include/CMakeLists.txt000066400000000000000000000011631417507532300163330ustar00rootroot00000000000000 # Add include folders to the library and targets that consume it # the SYSTEM keyword suppresses warnings for users of the library # # By adding this directory as an include directory the user gets a # namespace effect. # # IE: # #include if(GSL_STANDALONE_PROJECT) target_include_directories(GSL INTERFACE $ $ ) else() target_include_directories(GSL SYSTEM INTERFACE $ $ ) endif() GSL-4.0.0/include/gsl/000077500000000000000000000000001417507532300143575ustar00rootroot00000000000000GSL-4.0.0/include/gsl/algorithm000066400000000000000000000044531417507532300162760ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_ALGORITHM_H #define GSL_ALGORITHM_H #include // for Expects #include // for dynamic_extent, span #include // for copy_n #include // for ptrdiff_t #include // for is_assignable #ifdef _MSC_VER #pragma warning(push) // turn off some warnings that are noisy about our Expects statements #pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4996) // unsafe use of std::copy_n #endif // _MSC_VER namespace gsl { // Note: this will generate faster code than std::copy using span iterator in older msvc+stl // not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915) template void copy(span src, span dest) { static_assert(std::is_assignable::value, "Elements of source span can not be assigned to elements of destination span"); static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent || (SrcExtent <= DestExtent), "Source range is longer than target range"); Expects(dest.size() >= src.size()); // clang-format off GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute // clang-format on std::copy_n(src.data(), src.size(), dest.data()); } } // namespace gsl #ifdef _MSC_VER #pragma warning(pop) #endif // _MSC_VER #endif // GSL_ALGORITHM_H GSL-4.0.0/include/gsl/assert000066400000000000000000000077351417507532300156170ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_CONTRACTS_H #define GSL_CONTRACTS_H // // Temporary until MSVC STL supports no-exceptions mode. // Currently terminate is a no-op in this mode, so we add termination behavior back // #if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) #define GSL_KERNEL_MODE #define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND #include #define RANGE_CHECKS_FAILURE 0 #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winvalid-noreturn" #endif // defined(__clang__) #else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && // !_HAS_EXCEPTIONS)) #include #endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && // !_HAS_EXCEPTIONS)) // // make suppress attributes parse for some compilers // Hopefully temporary until suppression standardization occurs // #if defined(__clang__) #define GSL_SUPPRESS(x) [[gsl::suppress("x")]] #else #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #define GSL_SUPPRESS(x) [[gsl::suppress(x)]] #else #define GSL_SUPPRESS(x) #endif // _MSC_VER #endif // __clang__ #define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) #if defined(__clang__) || defined(__GNUC__) #define GSL_LIKELY(x) __builtin_expect(!!(x), 1) #define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0) #else #define GSL_LIKELY(x) (!!(x)) #define GSL_UNLIKELY(x) (!!(x)) #endif // defined(__clang__) || defined(__GNUC__) // // GSL_ASSUME(cond) // // Tell the optimizer that the predicate cond must hold. It is unspecified // whether or not cond is actually evaluated. // #ifdef _MSC_VER #define GSL_ASSUME(cond) __assume(cond) #elif defined(__GNUC__) #define GSL_ASSUME(cond) ((cond) ? static_cast(0) : __builtin_unreachable()) #else #define GSL_ASSUME(cond) static_cast((cond) ? 0 : 0) #endif // // GSL.assert: assertions // namespace gsl { namespace details { #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) typedef void(__cdecl* terminate_handler)(); // clang-format off GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // clang-format on [[noreturn]] inline void __cdecl default_terminate_handler() { __fastfail(RANGE_CHECKS_FAILURE); } inline gsl::details::terminate_handler& get_terminate_handler() noexcept { static terminate_handler handler = &default_terminate_handler; return handler; } #endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) [[noreturn]] inline void terminate() noexcept { #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) (*gsl::details::get_terminate_handler())(); #else std::terminate(); #endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) } } // namespace details } // namespace gsl #define GSL_CONTRACT_CHECK(type, cond) \ (GSL_LIKELY(cond) ? static_cast(0) : gsl::details::terminate()) #define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond) #define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__) #pragma clang diagnostic pop #endif #endif // GSL_CONTRACTS_H GSL-4.0.0/include/gsl/byte000066400000000000000000000153471417507532300152570ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_BYTE_H #define GSL_BYTE_H // // make suppress attributes work for some compilers // Hopefully temporary until suppression standardization occurs // #if defined(__clang__) #define GSL_SUPPRESS(x) [[gsl::suppress("x")]] #else #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #define GSL_SUPPRESS(x) [[gsl::suppress(x)]] #else #define GSL_SUPPRESS(x) #endif // _MSC_VER #endif // __clang__ #include // VS2017 15.8 added support for the __cpp_lib_byte definition // To do: drop _HAS_STD_BYTE when support for pre 15.8 expires #ifdef _MSC_VER #pragma warning(push) // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. #pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates // does not always work #ifndef GSL_USE_STD_BYTE // this tests if we are under MSVC and the standard lib has std::byte and it is enabled #if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || \ (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) #define GSL_USE_STD_BYTE 1 #else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= // 201603) #define GSL_USE_STD_BYTE 0 #endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= // 201603) #endif // GSL_USE_STD_BYTE #else // _MSC_VER #ifndef GSL_USE_STD_BYTE #include /* __cpp_lib_byte */ // this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte // also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte #if defined(__cplusplus) && (__cplusplus >= 201703L) && \ (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \ defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) #define GSL_USE_STD_BYTE 1 #else // defined(__cplusplus) && (__cplusplus >= 201703L) && // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) #define GSL_USE_STD_BYTE 0 #endif // defined(__cplusplus) && (__cplusplus >= 201703L) && // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) #endif // GSL_USE_STD_BYTE #endif // _MSC_VER // Use __may_alias__ attribute on gcc and clang #if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5) #define byte_may_alias __attribute__((__may_alias__)) #else // defined __clang__ || defined __GNUC__ #define byte_may_alias #endif // defined __clang__ || defined __GNUC__ #if GSL_USE_STD_BYTE #include #endif namespace gsl { #if GSL_USE_STD_BYTE using std::byte; using std::to_integer; #else // GSL_USE_STD_BYTE // This is a simple definition for now that allows // use of byte within span<> to be standards-compliant enum class byte_may_alias byte : unsigned char { }; template ::value>> constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept { return b = byte(static_cast(b) << shift); } template ::value>> constexpr byte operator<<(byte b, IntegerType shift) noexcept { return byte(static_cast(b) << shift); } template ::value>> constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept { return b = byte(static_cast(b) >> shift); } template ::value>> constexpr byte operator>>(byte b, IntegerType shift) noexcept { return byte(static_cast(b) >> shift); } constexpr byte& operator|=(byte& l, byte r) noexcept { return l = byte(static_cast(l) | static_cast(r)); } constexpr byte operator|(byte l, byte r) noexcept { return byte(static_cast(l) | static_cast(r)); } constexpr byte& operator&=(byte& l, byte r) noexcept { return l = byte(static_cast(l) & static_cast(r)); } constexpr byte operator&(byte l, byte r) noexcept { return byte(static_cast(l) & static_cast(r)); } constexpr byte& operator^=(byte& l, byte r) noexcept { return l = byte(static_cast(l) ^ static_cast(r)); } constexpr byte operator^(byte l, byte r) noexcept { return byte(static_cast(l) ^ static_cast(r)); } constexpr byte operator~(byte b) noexcept { return byte(~static_cast(b)); } template ::value>> constexpr IntegerType to_integer(byte b) noexcept { return static_cast(b); } #endif // GSL_USE_STD_BYTE template constexpr byte to_byte_impl(T t) noexcept { static_assert( E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " "If you are calling to_byte with an integer contant use: gsl::to_byte() version."); return static_cast(t); } template <> // NOTE: need suppression since c++14 does not allow "return {t}" // GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work constexpr byte to_byte_impl(unsigned char t) noexcept { return byte(t); } template constexpr byte to_byte(T t) noexcept { return to_byte_impl::value, T>(t); } template constexpr byte to_byte() noexcept { static_assert(I >= 0 && I <= 255, "gsl::byte only has 8 bits of storage, values must be in range 0-255"); return static_cast(I); } } // namespace gsl #ifdef _MSC_VER #pragma warning(pop) #endif // _MSC_VER #endif // GSL_BYTE_H GSL-4.0.0/include/gsl/gsl000066400000000000000000000023101417507532300150630ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_GSL_H #define GSL_GSL_H #include // copy #include // Ensures/Expects #include // byte #include // owner, not_null #include // span #include // zstring, string_span, zstring_builder... #include // finally()/narrow_cast()... #ifdef __cpp_exceptions #include // narrow() #endif #endif // GSL_GSL_H GSL-4.0.0/include/gsl/gsl_algorithm000066400000000000000000000003531417507532300171360ustar00rootroot00000000000000#pragma once #pragma message( \ "This header will soon be removed. Use instead of ") #include GSL-4.0.0/include/gsl/gsl_assert000066400000000000000000000002101417507532300164410ustar00rootroot00000000000000#pragma once #pragma message("This header will soon be removed. Use instead of ") #include GSL-4.0.0/include/gsl/gsl_byte000066400000000000000000000002021417507532300161040ustar00rootroot00000000000000#pragma once #pragma message("This header will soon be removed. Use instead of ") #include GSL-4.0.0/include/gsl/gsl_narrow000066400000000000000000000002101417507532300164500ustar00rootroot00000000000000#pragma once #pragma message("This header will soon be removed. Use instead of ") #include GSL-4.0.0/include/gsl/gsl_util000066400000000000000000000002021417507532300161160ustar00rootroot00000000000000#pragma once #pragma message("This header will soon be removed. Use instead of ") #include GSL-4.0.0/include/gsl/narrow000066400000000000000000000055371417507532300156240ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_NARROW_H #define GSL_NARROW_H #include // for Expects #include // for narrow_cast namespace gsl { struct narrowing_error : public std::exception { const char* what() const noexcept override { return "narrowing_error"; } }; // narrow() : a checked version of narrow_cast() that throws if the cast changed the value template ::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) { constexpr const bool is_different_signedness = (std::is_signed::value != std::is_signed::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(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 (static_cast(t) != u || (is_different_signedness && ((t < T{}) != (u < U{})))) { throw narrowing_error{}; } return t; } template ::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(u); if (static_cast(t) != u) { throw narrowing_error{}; } return t; } } // namespace gsl #endif // GSL_NARROW_H GSL-4.0.0/include/gsl/pointers000066400000000000000000000234311417507532300161500ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_POINTERS_H #define GSL_POINTERS_H #include // for Ensures, Expects #include // for forward #include // for ptrdiff_t, nullptr_t, size_t #include // for shared_ptr, unique_ptr #include // for hash #include // for enable_if_t, is_convertible, is_assignable #if !defined(GSL_NO_IOSTREAMS) #include // for ostream #endif // !defined(GSL_NO_IOSTREAMS) namespace gsl { namespace details { template struct is_comparable_to_nullptr : std::false_type { }; template struct is_comparable_to_nullptr< T, std::enable_if_t() != nullptr), bool>::value>> : std::true_type { }; } // namespace details // // GSL.owner: ownership pointers // using std::shared_ptr; using std::unique_ptr; // // owner // // owner is designed as a bridge for code that must deal directly with owning pointers for some // reason // // T must be a pointer type // - disallow construction from any type other than pointer type // template ::value>> using owner = T; // // not_null // // Restricts a pointer or smart pointer to only hold non-null values. // // Has zero size overhead over T. // // If T is a pointer (i.e. T == U*) then // - allow construction from U* // - disallow construction from nullptr_t // - disallow default construction // - ensure construction from null U* fails // - allow implicit conversion to U* // template class not_null { public: static_assert(details::is_comparable_to_nullptr::value, "T cannot be compared to nullptr."); template ::value>> constexpr not_null(U&& u) : ptr_(std::forward(u)) { Expects(ptr_ != nullptr); } template ::value>> constexpr not_null(T u) : ptr_(std::move(u)) { Expects(ptr_ != nullptr); } template ::value>> constexpr not_null(const not_null& other) : not_null(other.get()) {} not_null(const not_null& other) = default; not_null& operator=(const not_null& other) = default; constexpr std::conditional_t::value, T, const T&> get() const { Ensures(ptr_ != nullptr); return ptr_; } constexpr operator T() const { return get(); } constexpr decltype(auto) operator->() const { return get(); } constexpr decltype(auto) operator*() const { return *get(); } // prevents compilation when someone attempts to assign a null pointer constant not_null(std::nullptr_t) = delete; not_null& operator=(std::nullptr_t) = delete; // unwanted operators...pointers only point to single objects! not_null& operator++() = delete; not_null& operator--() = delete; not_null operator++(int) = delete; not_null operator--(int) = delete; not_null& operator+=(std::ptrdiff_t) = delete; not_null& operator-=(std::ptrdiff_t) = delete; void operator[](std::ptrdiff_t) const = delete; private: T ptr_; }; template auto make_not_null(T&& t) noexcept { return not_null>>{std::forward(t)}; } #if !defined(GSL_NO_IOSTREAMS) template std::ostream& operator<<(std::ostream& os, const not_null& val) { os << val.get(); return os; } #endif // !defined(GSL_NO_IOSTREAMS) template auto operator==(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() == rhs.get())) -> decltype(lhs.get() == rhs.get()) { return lhs.get() == rhs.get(); } template auto operator!=(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() != rhs.get())) -> decltype(lhs.get() != rhs.get()) { return lhs.get() != rhs.get(); } template auto operator<(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() < rhs.get())) -> decltype(lhs.get() < rhs.get()) { return lhs.get() < rhs.get(); } template auto operator<=(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() <= rhs.get())) -> decltype(lhs.get() <= rhs.get()) { return lhs.get() <= rhs.get(); } template auto operator>(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() > rhs.get())) -> decltype(lhs.get() > rhs.get()) { return lhs.get() > rhs.get(); } template auto operator>=(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() >= rhs.get())) -> decltype(lhs.get() >= rhs.get()) { return lhs.get() >= rhs.get(); } // more unwanted operators template std::ptrdiff_t operator-(const not_null&, const not_null&) = delete; template not_null operator-(const not_null&, std::ptrdiff_t) = delete; template not_null operator+(const not_null&, std::ptrdiff_t) = delete; template not_null operator+(std::ptrdiff_t, const not_null&) = delete; } // namespace gsl namespace std { template struct hash> { std::size_t operator()(const gsl::not_null& value) const { return hash{}(value.get()); } }; } // namespace std namespace gsl { // // strict_not_null // // Restricts a pointer or smart pointer to only hold non-null values, // // - provides a strict (i.e. explicit constructor from T) wrapper of not_null // - to be used for new code that wishes the design to be cleaner and make not_null // checks intentional, or in old code that would like to make the transition. // // To make the transition from not_null, incrementally replace not_null // by strict_not_null and fix compilation errors // // Expect to // - remove all unneeded conversions from raw pointer to not_null and back // - make API clear by specifying not_null in parameters where needed // - remove unnecessary asserts // template class strict_not_null : public not_null { public: template ::value>> constexpr explicit strict_not_null(U&& u) : not_null(std::forward(u)) {} template ::value>> constexpr explicit strict_not_null(T u) : not_null(u) {} template ::value>> constexpr strict_not_null(const not_null& other) : not_null(other) {} template ::value>> constexpr strict_not_null(const strict_not_null& other) : not_null(other) {} strict_not_null(strict_not_null&& other) = default; strict_not_null(const strict_not_null& other) = default; strict_not_null& operator=(const strict_not_null& other) = default; strict_not_null& operator=(const not_null& other) { not_null::operator=(other); return *this; } // prevents compilation when someone attempts to assign a null pointer constant strict_not_null(std::nullptr_t) = delete; strict_not_null& operator=(std::nullptr_t) = delete; // unwanted operators...pointers only point to single objects! strict_not_null& operator++() = delete; strict_not_null& operator--() = delete; strict_not_null operator++(int) = delete; strict_not_null operator--(int) = delete; strict_not_null& operator+=(std::ptrdiff_t) = delete; strict_not_null& operator-=(std::ptrdiff_t) = delete; void operator[](std::ptrdiff_t) const = delete; }; // more unwanted operators template std::ptrdiff_t operator-(const strict_not_null&, const strict_not_null&) = delete; template strict_not_null operator-(const strict_not_null&, std::ptrdiff_t) = delete; template strict_not_null operator+(const strict_not_null&, std::ptrdiff_t) = delete; template strict_not_null operator+(std::ptrdiff_t, const strict_not_null&) = delete; template auto make_strict_not_null(T&& t) noexcept { return strict_not_null>>{std::forward(t)}; } #if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) // deduction guides to prevent the ctad-maybe-unsupported warning template not_null(T) -> not_null; template strict_not_null(T) -> strict_not_null; #endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) } // namespace gsl namespace std { template struct hash> { std::size_t operator()(const gsl::strict_not_null& value) const { return hash{}(value.get()); } }; } // namespace std #endif // GSL_POINTERS_H GSL-4.0.0/include/gsl/span000066400000000000000000000724571417507532300152620ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_SPAN_H #define GSL_SPAN_H #include // for Expects #include // for byte #include // for narrow_cast #include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for span specialization of gsl::at and other span-related extensions #include // for reverse_iterator, distance, random_access_... #include // for enable_if_t, declval, is_convertible, inte... #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) // turn off some warnings that are noisy about our Expects statements #pragma warning(disable : 4127) // conditional expression is constant #pragma warning( \ disable : 4146) // unary minus operator applied to unsigned type, result still unsigned #pragma warning(disable : 4702) // unreachable code // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. #pragma warning(disable : 26495) // uninitalized member when constructor calls constructor #pragma warning(disable : 26446) // parser bug does not allow attributes on some templates #endif // _MSC_VER // See if we have enough C++17 power to use a static constexpr data member // without needing an out-of-line definition #if !(defined(__cplusplus) && (__cplusplus >= 201703L)) #define GSL_USE_STATIC_CONSTEXPR_WORKAROUND #endif // !(defined(__cplusplus) && (__cplusplus >= 201703L)) // GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t) // While there is a conversion from signed to unsigned, it happens at // compiletime, so the compiler wouldn't have to warn indiscriminately, but // could check if the source value actually doesn't fit into the target type // and only warn in those cases. #if defined(__GNUC__) && __GNUC__ > 6 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-conversion" #endif namespace gsl { // implementation details namespace details { template struct is_span_oracle : std::false_type { }; template struct is_span_oracle> : std::true_type { }; template struct is_span : public is_span_oracle> { }; template struct is_std_array_oracle : std::false_type { }; template struct is_std_array_oracle> : std::true_type { }; template struct is_std_array : is_std_array_oracle> { }; template struct is_allowed_extent_conversion : std::integral_constant { }; template struct is_allowed_element_type_conversion : std::integral_constant::value> { }; template class span_iterator { public: using iterator_category = std::random_access_iterator_tag; using value_type = std::remove_cv_t; using difference_type = std::ptrdiff_t; using pointer = Type*; using reference = Type&; #ifdef _MSC_VER using _Unchecked_type = pointer; #endif // _MSC_VER constexpr span_iterator() = default; constexpr span_iterator(pointer begin, pointer end, pointer current) : begin_(begin), end_(end), current_(current) {} constexpr operator span_iterator() const noexcept { return {begin_, end_, current_}; } constexpr reference operator*() const noexcept { Expects(begin_ && end_); Expects(begin_ <= current_ && current_ < end_); return *current_; } constexpr pointer operator->() const noexcept { Expects(begin_ && end_); Expects(begin_ <= current_ && current_ < end_); return current_; } constexpr span_iterator& operator++() noexcept { Expects(begin_ && current_ && end_); Expects(current_ < end_); // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on ++current_; return *this; } constexpr span_iterator operator++(int) noexcept { span_iterator ret = *this; ++*this; return ret; } constexpr span_iterator& operator--() noexcept { Expects(begin_ && end_); Expects(begin_ < current_); --current_; return *this; } constexpr span_iterator operator--(int) noexcept { span_iterator ret = *this; --*this; return ret; } constexpr span_iterator& operator+=(const difference_type n) noexcept { if (n != 0) Expects(begin_ && current_ && end_); if (n > 0) Expects(end_ - current_ >= n); if (n < 0) Expects(current_ - begin_ >= -n); // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on current_ += n; return *this; } constexpr span_iterator operator+(const difference_type n) const noexcept { span_iterator ret = *this; ret += n; return ret; } friend constexpr span_iterator operator+(const difference_type n, const span_iterator& rhs) noexcept { return rhs + n; } constexpr span_iterator& operator-=(const difference_type n) noexcept { if (n != 0) Expects(begin_ && current_ && end_); if (n > 0) Expects(current_ - begin_ >= n); if (n < 0) Expects(end_ - current_ >= -n); current_ -= n; return *this; } constexpr span_iterator operator-(const difference_type n) const noexcept { span_iterator ret = *this; ret -= n; return ret; } template < class Type2, std::enable_if_t, value_type>::value, int> = 0> constexpr difference_type operator-(const span_iterator& rhs) const noexcept { Expects(begin_ == rhs.begin_ && end_ == rhs.end_); return current_ - rhs.current_; } constexpr reference operator[](const difference_type n) const noexcept { return *(*this + n); } template < class Type2, std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator==(const span_iterator& rhs) const noexcept { Expects(begin_ == rhs.begin_ && end_ == rhs.end_); return current_ == rhs.current_; } template < class Type2, std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator!=(const span_iterator& rhs) const noexcept { return !(*this == rhs); } template < class Type2, std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator<(const span_iterator& rhs) const noexcept { Expects(begin_ == rhs.begin_ && end_ == rhs.end_); return current_ < rhs.current_; } template < class Type2, std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator>(const span_iterator& rhs) const noexcept { return rhs < *this; } template < class Type2, std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator<=(const span_iterator& rhs) const noexcept { return !(rhs < *this); } template < class Type2, std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator>=(const span_iterator& rhs) const noexcept { return !(*this < rhs); } #ifdef _MSC_VER // MSVC++ iterator debugging support; allows STL algorithms in 15.8+ // to unwrap span_iterator to a pointer type after a range check in STL // algorithm calls friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept { // test that [lhs, rhs) forms a valid range inside an STL algorithm Expects(lhs.begin_ == rhs.begin_ // range spans have to match && lhs.end_ == rhs.end_ && lhs.current_ <= rhs.current_); // range must not be transposed } constexpr void _Verify_offset(const difference_type n) const noexcept { // test that *this + n is within the range of this call if (n != 0) Expects(begin_ && current_ && end_); if (n > 0) Expects(end_ - current_ >= n); if (n < 0) Expects(current_ - begin_ >= -n); } // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw // pointer return current_; } // Tell the STL that span_iterator should not be unwrapped if it can't // validate in advance, even in release / optimized builds: #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) static constexpr const bool _Unwrap_when_unverified = false; #else static constexpr bool _Unwrap_when_unverified = false; #endif // clang-format off GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive // clang-format on constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped current_ = p; } #endif pointer begin_ = nullptr; pointer end_ = nullptr; pointer current_ = nullptr; }; template class extent_type { public: using size_type = std::size_t; constexpr extent_type() noexcept = default; constexpr explicit extent_type(extent_type); constexpr explicit extent_type(size_type size) { Expects(size == Ext); } constexpr size_type size() const noexcept { return Ext; } private: #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) static constexpr const size_type size_ = Ext; // static size equal to Ext #else static constexpr size_type size_ = Ext; // static size equal to Ext #endif }; template <> class extent_type { public: using size_type = std::size_t; template constexpr explicit extent_type(extent_type ext) : size_(ext.size()) {} constexpr explicit extent_type(size_type size) : size_(size) { Expects(size != dynamic_extent); } constexpr size_type size() const noexcept { return size_; } private: size_type size_; }; template constexpr extent_type::extent_type(extent_type ext) { Expects(ext.size() == Ext); } template struct calculate_subspan_type { using type = span; }; } // namespace details // [span], class template span template class span { public: // constants and types using element_type = ElementType; using value_type = std::remove_cv_t; using size_type = std::size_t; using pointer = element_type*; using const_pointer = const element_type*; using reference = element_type&; using const_reference = const element_type&; using difference_type = std::ptrdiff_t; using iterator = details::span_iterator; using reverse_iterator = std::reverse_iterator; #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) static constexpr const size_type extent{Extent}; #else static constexpr size_type extent{Extent}; #endif // [span.cons], span constructors, copy, assignment, and destructor template " SFINAE, since "std::enable_if_t" is ill-formed when Extent is greater than 0. class = std::enable_if_t<(Dependent || details::is_allowed_extent_conversion<0, Extent>::value)>> constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) {} template = 0> constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count) { Expects(count == Extent); } template = 0> constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count) {} template = 0> constexpr explicit span(pointer firstElem, pointer lastElem) noexcept : storage_(firstElem, narrow_cast(lastElem - firstElem)) { Expects(lastElem - firstElem == static_cast(Extent)); } template = 0> constexpr span(pointer firstElem, pointer lastElem) noexcept : storage_(firstElem, narrow_cast(lastElem - firstElem)) {} template ::value, int> = 0> constexpr span(element_type (&arr)[N]) noexcept : storage_(KnownNotNull{arr}, details::extent_type()) {} template < class T, std::size_t N, std::enable_if_t<(details::is_allowed_extent_conversion::value && details::is_allowed_element_type_conversion::value), int> = 0> constexpr span(std::array& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type()) {} template ::value && details::is_allowed_element_type_conversion::value), int> = 0> constexpr span(const std::array& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type()) {} // NB: the SFINAE on these constructors uses .data() as an incomplete/imperfect proxy for the // requirement on Container to be a contiguous sequence container. template ::value && !details::is_std_array::value && std::is_pointer().data())>::value && std::is_convertible< std::remove_pointer_t().data())> (*)[], element_type (*)[]>::value, int> = 0> constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size()) {} template ::value && !details::is_std_array::value && std::is_pointer().data())>::value && std::is_convertible< std::remove_pointer_t().data())> (*)[], element_type (*)[]>::value, int> = 0> constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) {} template < std::size_t MyExtent = Extent, class Container, std::enable_if_t< MyExtent != dynamic_extent && std::is_const::value && !details::is_span::value && !details::is_std_array::value && std::is_pointer().data())>::value && std::is_convertible< std::remove_pointer_t().data())> (*)[], element_type (*)[]>::value, int> = 0> constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size()) {} template < std::size_t MyExtent = Extent, class Container, std::enable_if_t< MyExtent == dynamic_extent && std::is_const::value && !details::is_span::value && !details::is_std_array::value && std::is_pointer().data())>::value && std::is_convertible< std::remove_pointer_t().data())> (*)[], element_type (*)[]>::value, int> = 0> constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size()) {} constexpr span(const span& other) noexcept = default; template ::value, int> = 0> constexpr span(const span& other) noexcept : storage_(other.data(), details::extent_type(other.size())) {} template ::value, int> = 0> constexpr explicit span(const span& other) noexcept : storage_(other.data(), details::extent_type(other.size())) {} ~span() noexcept = default; constexpr span& operator=(const span& other) noexcept = default; // [span.sub], span subviews template constexpr span first() const noexcept { Expects(Count <= size()); return span{data(), Count}; } template // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on constexpr span last() const noexcept { Expects(Count <= size()); return span{data() + (size() - Count), Count}; } template // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on constexpr auto subspan() const noexcept -> typename details::calculate_subspan_type::type { Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset))); using type = typename details::calculate_subspan_type::type; return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; } constexpr span first(size_type count) const noexcept { Expects(count <= size()); return {data(), count}; } constexpr span last(size_type count) const noexcept { Expects(count <= size()); return make_subspan(size() - count, dynamic_extent, subspan_selector{}); } constexpr span subspan(size_type offset, size_type count = dynamic_extent) const noexcept { return make_subspan(offset, count, subspan_selector{}); } // [span.obs], span observers constexpr size_type size() const noexcept { return storage_.size(); } constexpr size_type size_bytes() const noexcept { Expects(size() < dynamic_extent / sizeof(element_type)); return size() * sizeof(element_type); } constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on constexpr reference operator[](size_type idx) const noexcept { Expects(idx < size()); return data()[idx]; } constexpr reference front() const noexcept { Expects(size() > 0); return data()[0]; } constexpr reference back() const noexcept { Expects(size() > 0); return data()[size() - 1]; } constexpr pointer data() const noexcept { return storage_.data(); } // [span.iter], span iterator support constexpr iterator begin() const noexcept { const auto data = storage_.data(); // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on return {data, data + size(), data}; } constexpr iterator end() const noexcept { const auto data = storage_.data(); // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on const auto endData = data + storage_.size(); return {data, endData, endData}; } constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } #ifdef _MSC_VER // Tell MSVC how to unwrap spans in range-based-for constexpr pointer _Unchecked_begin() const noexcept { return data(); } constexpr pointer _Unchecked_end() const noexcept { // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on return data() + size(); } #endif // _MSC_VER private: // Needed to remove unnecessary null check in subspans struct KnownNotNull { pointer p; }; // this implementation detail class lets us take advantage of the // empty base class optimization to pay for only storage of a single // pointer in the case of fixed-size spans template class storage_type : public ExtentType { public: // KnownNotNull parameter is needed to remove unnecessary null check // in subspans and constructors from arrays template constexpr storage_type(KnownNotNull data, OtherExtentType ext) : ExtentType(ext), data_(data.p) { Expects(ExtentType::size() != dynamic_extent); } template constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) { Expects(ExtentType::size() != dynamic_extent); Expects(data || ExtentType::size() == 0); } constexpr pointer data() const noexcept { return data_; } private: pointer data_; }; storage_type> storage_; // The rest is needed to remove unnecessary null check // in subspans and constructors from arrays constexpr span(KnownNotNull ptr, size_type count) noexcept : storage_(ptr, count) {} template class subspan_selector { }; template constexpr span make_subspan(size_type offset, size_type count, subspan_selector) const noexcept { const span tmp(*this); return tmp.subspan(offset, count); } // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on constexpr span make_subspan(size_type offset, size_type count, subspan_selector) const noexcept { Expects(size() >= offset); if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; } Expects(size() - offset >= count); return {KnownNotNull{data() + offset}, count}; } }; #if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) // Deduction Guides template span(Type (&)[Extent]) -> span; template span(std::array&) -> span; template span(const std::array&) -> span; template ().data())>> span(Container&) -> span; template ().data())>> span(const Container&) -> span; #endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) template constexpr const typename span::size_type span::extent; #endif namespace details { // if we only supported compilers with good constexpr support then // this pair of classes could collapse down to a constexpr function // we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as // constexpr // and so will fail compilation of the template template struct calculate_byte_size : std::integral_constant { static_assert(Extent < dynamic_extent / sizeof(ElementType), "Size is too big."); }; template struct calculate_byte_size : std::integral_constant { }; } // namespace details // [span.objectrep], views of object representation template span::value> as_bytes(span s) noexcept { using type = span::value>; // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on return type{reinterpret_cast(s.data()), s.size_bytes()}; } template ::value, int> = 0> span::value> as_writable_bytes(span s) noexcept { using type = span::value>; // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on return type{reinterpret_cast(s.data()), s.size_bytes()}; } } // namespace gsl #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(pop) #endif // _MSC_VER #if defined(__GNUC__) && __GNUC__ > 6 #pragma GCC diagnostic pop #endif // __GNUC__ > 6 #endif // GSL_SPAN_H GSL-4.0.0/include/gsl/span_ext000066400000000000000000000147271417507532300161360ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_SPAN_EXT_H #define GSL_SPAN_EXT_H /////////////////////////////////////////////////////////////////////////////// // // File: span_ext // Purpose: continue offering features that have been cut from the official // implementation of span. // While modernizing gsl::span a number of features needed to be removed to // be compliant with the design of std::span // /////////////////////////////////////////////////////////////////////////////// #include // GSL_KERNEL_MODE #include // for narrow_cast, narrow #include // for ptrdiff_t, size_t #include #ifndef GSL_KERNEL_MODE #include // for lexicographical_compare #endif // GSL_KERNEL_MODE namespace gsl { // [span.views.constants], constants constexpr const std::size_t dynamic_extent = narrow_cast(-1); template 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 constexpr bool operator==(span l, span r) { return std::equal(l.begin(), l.end(), r.begin(), r.end()); } template constexpr bool operator!=(span l, span r) { return !(l == r); } template constexpr bool operator<(span l, span r) { return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); } template constexpr bool operator<=(span l, span r) { return !(l > r); } template constexpr bool operator>(span l, span r) { return r < l; } template constexpr bool operator>=(span l, span r) { return !(l < r); } #endif // GSL_KERNEL_MODE // // make_span() - Utility functions for creating spans // template constexpr span make_span(ElementType* ptr, typename span::size_type count) { return span(ptr, count); } template constexpr span make_span(ElementType* firstElem, ElementType* lastElem) { return span(firstElem, lastElem); } template constexpr span make_span(ElementType (&arr)[N]) noexcept { return span(arr); } template constexpr span make_span(Container& cont) { return span(cont); } template constexpr span make_span(const Container& cont) { return span(cont); } template constexpr span make_span(Ptr& cont, std::size_t count) { return span(cont, count); } template constexpr span make_span(Ptr& cont) { return span(cont); } // Specialization of gsl::at for span template constexpr ElementType& at(span s, index i) { // No bounds checking here because it is done in span::operator[] called below Ensures(i >= 0); return s[narrow_cast(i)]; } // [span.obs] Free observer functions template constexpr std::ptrdiff_t ssize(const span& s) noexcept { return static_cast(s.size()); } // [span.iter] Free functions for begin/end functions template constexpr typename span::iterator begin(const span& s) noexcept { return s.begin(); } template constexpr typename span::iterator end(const span& s) noexcept { return s.end(); } template constexpr typename span::reverse_iterator rbegin(const span& s) noexcept { return s.rbegin(); } template constexpr typename span::reverse_iterator rend(const span& s) noexcept { return s.rend(); } template constexpr typename span::iterator cbegin(const span& s) noexcept { return s.begin(); } template constexpr typename span::iterator cend(const span& s) noexcept { return s.end(); } template constexpr typename span::reverse_iterator crbegin(const span& s) noexcept { return s.rbegin(); } template constexpr typename span::reverse_iterator crend(const span& s) noexcept { return s.rend(); } } // namespace gsl #endif // GSL_SPAN_EXT_H GSL-4.0.0/include/gsl/string_span000066400000000000000000000757531417507532300166520ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_STRING_SPAN_H #define GSL_STRING_SPAN_H #include // for Ensures, Expects #include // for operator!=, operator==, dynamic_extent #include // for narrow_cast #include // for equal, lexicographical_compare #include // for array #include // for size_t, nullptr_t #include // for PTRDIFF_MAX #include #include // for basic_string, allocator, char_traits #include // for declval, is_convertible, enable_if_t, add_... #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. #pragma warning(disable : 26446) // TODO: bug in parser - attributes and templates #pragma warning(disable : 26481) // TODO: suppress does not work inside templates sometimes #pragma warning(disable : 4996) // use of functions & classes marked [[deprecated]] #endif // _MSC_VER #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif namespace gsl { // // czstring and wzstring // // These are "tag" typedefs for C-style strings (i.e. null-terminated character arrays) // that allow static analysis to help find bugs. // // There are no additional features/semantics that we can find a way to add inside the // type system for these types that will not either incur significant runtime costs or // (sometimes needlessly) break existing programs when introduced. // template using basic_zstring = CharT*; using czstring = basic_zstring; using cwzstring = basic_zstring; using cu16zstring = basic_zstring; using cu32zstring = basic_zstring; using zstring = basic_zstring; using wzstring = basic_zstring; using u16zstring = basic_zstring; using u32zstring = basic_zstring; namespace details { template [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see " "isocpp/CppCoreGuidelines PR#1680")]] constexpr std::size_t string_length(const CharT* str, std::size_t n) { if (str == nullptr || n == dynamic_extent) return 0; const span str_span{str, n}; std::size_t len = 0; while (len < n && str_span[len]) len++; return len; } } // namespace details // // ensure_sentinel() // // Provides a way to obtain an span from a contiguous sequence // that ends with a (non-inclusive) sentinel value. // // Will fail-fast if sentinel cannot be found before max elements are examined. // template [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see " "isocpp/CppCoreGuidelines PR#1680")]] constexpr span ensure_sentinel(T* seq, std::size_t max = static_cast(-1)) { Ensures(seq != nullptr); // clang-format off GSL_SUPPRESS(f.23) // TODO: false positive // TODO: suppress does not work // clang-format on auto cur = seq; Ensures(cur != nullptr); // workaround for removing the warning // clang-format off GSL_SUPPRESS(bounds.1) // TODO: suppress does not work // clang-format on while (static_cast(cur - seq) < max && *cur != Sentinel) ++cur; Ensures(*cur == Sentinel); return {seq, static_cast(cur - seq)}; } // // ensure_z - creates a span for a zero terminated strings. The span will not contain the zero // termination. Will fail fast if a null-terminator cannot be found before the limit of size_type. // template [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see " "isocpp/CppCoreGuidelines PR#1680")]] constexpr span ensure_z(CharT* const& sz, std::size_t max = static_cast(-1)) { return ensure_sentinel(sz, max); } template constexpr span ensure_z(CharT (&sz)[N]) { return ensure_z(&sz[0], N); } template [[deprecated( "string_span was removed from the C++ Core Guidelines. For more information, see " "isocpp/CppCoreGuidelines PR#1680")]] constexpr span::type, dynamic_extent> ensure_z(Cont& cont) { return ensure_z(cont.data(), cont.size()); } template class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, " "see isocpp/CppCoreGuidelines PR#1680")]] basic_string_span; namespace details { template struct [[deprecated( "string_span was removed from the C++ Core Guidelines. For more information, " "see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle : std::false_type{}; template struct [[deprecated( "string_span was removed from the C++ Core Guidelines. For more information, see " "isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle> : std::true_type{}; template struct [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span : is_basic_string_span_oracle>{}; } // namespace details // // string_span and relatives // template class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, " "see isocpp/CppCoreGuidelines PR#1680")]] basic_string_span { public: using element_type = CharT; using value_type = std::remove_cv_t; using pointer = std::add_pointer_t; using reference = std::add_lvalue_reference_t; using const_reference = std::add_lvalue_reference_t>; using impl_type = span; using size_type = typename impl_type::size_type; using iterator = typename impl_type::iterator; using reverse_iterator = typename impl_type::reverse_iterator; // default (empty) constexpr basic_string_span() noexcept = default; // copy constexpr basic_string_span(const basic_string_span& other) noexcept = default; // assign constexpr basic_string_span& operator=(const basic_string_span& other) noexcept = default; constexpr basic_string_span(pointer ptr, size_type length) : span_(ptr, length) {} constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {} // From static arrays - if 0-terminated, remove 0 from the view // All other containers allow 0s within the length, so we do not remove them template constexpr basic_string_span(element_type(&arr)[N]) : span_(remove_z(arr)) {} template > constexpr basic_string_span(std::array & arr) noexcept : span_(arr) {} template > constexpr basic_string_span(const std::array& arr) noexcept : span_(arr) {} // Container signature should work for basic_string after C++17 version exists template // GSL_SUPPRESS(bounds.4) // TODO: parser bug constexpr basic_string_span(std::basic_string & str) : span_(&str[0], str.length()) {} template constexpr basic_string_span(const std::basic_string& str) : span_(&str[0], str.length()) {} // from containers. Containers must have a pointer type and data() function signatures template ::value && std::is_convertible::value && std::is_convertible().data())>::value>> constexpr basic_string_span(Container & cont) : span_(cont) {} template ::value && std::is_convertible::value && std::is_convertible().data())>::value>> constexpr basic_string_span(const Container& cont) : span_(cont) {} // from string_span template < class OtherValueType, std::size_t OtherExtent, class = std::enable_if_t::impl_type, impl_type>::value>> constexpr basic_string_span(basic_string_span other) : span_(other.data(), other.length()) {} template constexpr basic_string_span first() const { return {span_.template first()}; } constexpr basic_string_span first(size_type count) const { return {span_.first(count)}; } template constexpr basic_string_span last() const { return {span_.template last()}; } constexpr basic_string_span last(size_type count) const { return {span_.last(count)}; } template constexpr basic_string_span subspan() const { return {span_.template subspan()}; } constexpr basic_string_span subspan( size_type offset, size_type count = dynamic_extent) const { return {span_.subspan(offset, count)}; } constexpr reference operator[](size_type idx) const { return span_[idx]; } constexpr reference operator()(size_type idx) const { return span_[idx]; } constexpr pointer data() const { return span_.data(); } constexpr size_type length() const noexcept { return span_.size(); } constexpr size_type size() const noexcept { return span_.size(); } constexpr size_type size_bytes() const noexcept { return span_.size_bytes(); } constexpr size_type length_bytes() const noexcept { return span_.length_bytes(); } constexpr bool empty() const noexcept { return size() == 0; } constexpr iterator begin() const noexcept { return span_.begin(); } constexpr iterator end() const noexcept { return span_.end(); } constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); } constexpr reverse_iterator rend() const noexcept { return span_.rend(); } private: static constexpr impl_type remove_z(pointer const& sz, std::size_t max) { return impl_type(sz, details::string_length(sz, max)); } template static constexpr impl_type remove_z(element_type(&sz)[N]) { return remove_z(&sz[0], N); } impl_type span_; }; template using string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_string_span; template using cstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_string_span; template using wstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_string_span; template using cwstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_string_span; template using u16string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_string_span; template using cu16string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_string_span; template using u32string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_string_span; template using cu32string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_string_span; // // to_string() allow (explicit) conversions from string_span to string // template constexpr std::basic_string::type> to_string(basic_string_span view) { return {view.data(), narrow_cast(view.length())}; } template , typename Allocator = std::allocator, typename gCharT, std::size_t Extent> constexpr std::basic_string to_basic_string(basic_string_span view) { return {view.data(), narrow_cast(view.length())}; } template constexpr basic_string_span::value> as_bytes(basic_string_span s) noexcept { // clang-format off GSL_SUPPRESS(type.1) // clang-format on return {reinterpret_cast(s.data()), s.size_bytes()}; } template ::value>> constexpr basic_string_span::value> as_writable_bytes(basic_string_span s) noexcept { // clang-format off GSL_SUPPRESS(type.1) // clang-format on return {reinterpret_cast(s.data()), s.size_bytes()}; } // zero-terminated string span, used to convert // zero-terminated spans to legacy strings template class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, " "see isocpp/CppCoreGuidelines PR#1680")]] basic_zstring_span { public: using value_type = CharT; using const_value_type = std::add_const_t; using pointer = std::add_pointer_t; using const_pointer = std::add_pointer_t; using zstring_type = basic_zstring; using const_zstring_type = basic_zstring; using impl_type = span; using string_span_type = basic_string_span; constexpr basic_zstring_span(impl_type s) : span_(s) { // expects a zero-terminated span Expects(s.size() > 0); Expects(s[s.size() - 1] == value_type{}); } // copy constexpr basic_zstring_span(const basic_zstring_span& other) = default; // move constexpr basic_zstring_span(basic_zstring_span && other) = default; // assign constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default; // move assign constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default; constexpr bool empty() const noexcept { return false; } constexpr string_span_type as_string_span() const noexcept { return {span_.data(), span_.size() - 1}; } constexpr string_span_type ensure_z() const { return gsl::ensure_z(span_); } constexpr const_zstring_type assume_z() const noexcept { return span_.data(); } private: impl_type span_; }; template using zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_zstring_span; template using wzstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_zstring_span; template using u16zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_zstring_span; template using u32zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_zstring_span; template using czstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_zstring_span; template using cwzstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " "information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_zstring_span; template using cu16zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For " "more information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_zstring_span; template using cu32zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For " "more information, see isocpp/CppCoreGuidelines PR#1680")]] = basic_zstring_span; // operator == template ::value || std::is_convertible>>::value>> bool operator==(const gsl::basic_string_span& one, const T& other) { const gsl::basic_string_span> tmp(other); return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); } template ::value && std::is_convertible>>::value>> bool operator==(const T& one, const gsl::basic_string_span& other) { const gsl::basic_string_span> tmp(one); return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end()); } // operator != template , Extent>>::value>> bool operator!=(gsl::basic_string_span one, const T& other) { return !(one == other); } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> bool operator!=(const T& one, gsl::basic_string_span other) { return !(one == other); } // operator< template , Extent>>::value>> bool operator<(gsl::basic_string_span one, const T& other) { const gsl::basic_string_span, Extent> tmp(other); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> bool operator<(const T& one, gsl::basic_string_span other) { gsl::basic_string_span, Extent> tmp(one); return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); } #ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && std::is_convertible::value && std::is_same().size(), *std::declval().data())>, DataType>::value>> bool operator<(gsl::basic_string_span one, const T& other) { gsl::basic_string_span, Extent> tmp(other); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && std::is_convertible::value && std::is_same().size(), *std::declval().data())>, DataType>::value>> bool operator<(const T& one, gsl::basic_string_span other) { gsl::basic_string_span, Extent> tmp(one); return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); } #endif // operator <= template , Extent>>::value>> bool operator<=(gsl::basic_string_span one, const T& other) { return !(other < one); } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> bool operator<=(const T& one, gsl::basic_string_span other) { return !(other < one); } #ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && std::is_convertible::value && std::is_same().size(), *std::declval().data())>, DataType>::value>> bool operator<=(gsl::basic_string_span one, const T& other) { return !(other < one); } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && std::is_convertible::value && std::is_same().size(), *std::declval().data())>, DataType>::value>> bool operator<=(const T& one, gsl::basic_string_span other) { return !(other < one); } #endif // operator> template , Extent>>::value>> bool operator>(gsl::basic_string_span one, const T& other) { return other < one; } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> bool operator>(const T& one, gsl::basic_string_span other) { return other < one; } #ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && std::is_convertible::value && std::is_same().size(), *std::declval().data())>, DataType>::value>> bool operator>(gsl::basic_string_span one, const T& other) { return other < one; } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && std::is_convertible::value && std::is_same().size(), *std::declval().data())>, DataType>::value>> bool operator>(const T& one, gsl::basic_string_span other) { return other < one; } #endif // operator >= template , Extent>>::value>> bool operator>=(gsl::basic_string_span one, const T& other) { return !(one < other); } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> bool operator>=(const T& one, gsl::basic_string_span other) { return !(one < other); } #ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && std::is_convertible::value && std::is_same().size(), *std::declval().data())>, DataType>::value>> bool operator>=(gsl::basic_string_span one, const T& other) { return !(one < other); } template < typename CharT, std::size_t Extent = dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && std::is_convertible::value && std::is_same().size(), *std::declval().data())>, DataType>::value>> bool operator>=(const T& one, gsl::basic_string_span other) { return !(one < other); } #endif } // namespace gsl #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(pop) #endif // _MSC_VER #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif #endif // GSL_STRING_SPAN_H GSL-4.0.0/include/gsl/util000066400000000000000000000113741417507532300152650ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_UTIL_H #define GSL_UTIL_H #include // for Expects #include #include // for ptrdiff_t, size_t #include // for initializer_list #include // for is_signed, integral_constant #include // for exchange, forward #if defined(__has_include) && __has_include() #include #if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L #include #endif // __cpp_lib_span >= 202002L #endif //__has_include() #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) #pragma warning(disable : 4127) // conditional expression is constant #endif // _MSC_VER #if defined(__cplusplus) && (__cplusplus >= 201703L) #define GSL_NODISCARD [[nodiscard]] #else #define GSL_NODISCARD #endif // defined(__cplusplus) && (__cplusplus >= 201703L) namespace gsl { // // GSL.util: utilities // // index type for all container indexes/subscripts/sizes using index = std::ptrdiff_t; // final_action allows you to ensure something gets run at the end of a scope template class final_action { public: static_assert(!std::is_reference::value && !std::is_const::value && !std::is_volatile::value, "Final_action should store its callable by value"); explicit final_action(F f) noexcept : f_(std::move(f)) {} final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) {} final_action(const final_action&) = delete; final_action& operator=(const final_action&) = delete; final_action& operator=(final_action&&) = delete; // clang-format off GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws // clang-format on ~final_action() noexcept { if (invoke_) f_(); } private: F f_; bool invoke_{true}; }; // finally() - convenience function to generate a final_action template GSL_NODISCARD final_action::type>::type> finally(F&& f) noexcept { return final_action::type>::type>( std::forward(f)); } // narrow_cast(): a searchable way to do narrowing casts of values template // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on constexpr T narrow_cast(U&& u) noexcept { return static_cast(std::forward(u)); } // // at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector // template // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // clang-format on constexpr T& at(T (&arr)[N], const index i) { Expects(i >= 0 && i < narrow_cast(N)); return arr[narrow_cast(i)]; } template // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // clang-format on constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) { Expects(i >= 0 && i < narrow_cast(cont.size())); using size_type = decltype(cont.size()); return cont[narrow_cast(i)]; } template // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on constexpr T at(const std::initializer_list cont, const index i) { Expects(i >= 0 && i < narrow_cast(cont.size())); return *(cont.begin() + i); } #if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L template constexpr auto at(std::span sp, const index i) -> decltype(sp[sp.size()]) { Expects(i >= 0 && i < narrow_cast(sp.size())); return sp[gsl::narrow_cast(i)]; } #endif // __cpp_lib_span >= 202002L } // namespace gsl #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(pop) #endif // _MSC_VER #endif // GSL_UTIL_H GSL-4.0.0/pipelines/000077500000000000000000000000001417507532300141375ustar00rootroot00000000000000GSL-4.0.0/pipelines/jobs.yml000066400000000000000000000030761417507532300156250ustar00rootroot00000000000000parameters: 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: - ${{ each compilerVersion in parameters.compilerVersions }}: - ${{ each CXXVersion in parameters.CXXVersions }}: - ${{ each buildType in parameters.buildTypes }}: - job: displayName: ${{ format('{0} {1} C++{2} {3}', parameters.compiler, compilerVersion, CXXVersion, buildType) }} pool: vmImage: ${{ parameters.image }} continueOnError: false steps: - ${{ if not(eq(parameters.setupfile, '')) }}: - template: ${{ parameters.setupfile }} parameters: version: ${{ compilerVersion }} - task: CMake@1 name: Configure inputs: workingDirectory: build cmakeArgs: '-DGSL_CXX_STANDARD=${{ CXXVersion }} -DCMAKE_BUILD_TYPE=${{ buildType }} -DCI_TESTING:BOOL=ON -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -Werror=dev ${{ parameters.extraCmakeArgs }} .. ' - task: CMake@1 name: Build inputs: workingDirectory: build cmakeArgs: '--build . ' - script: ctest . --output-on-failure --no-compress-output name: CTest workingDirectory: build failOnStderr: true GSL-4.0.0/pipelines/setup_apple.yml000066400000000000000000000003741417507532300172070ustar00rootroot00000000000000parameters: 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 GSL-4.0.0/pipelines/setup_clang.yml000066400000000000000000000005001417507532300171610ustar00rootroot00000000000000parameters: 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 }} GSL-4.0.0/pipelines/setup_gcc.yml000066400000000000000000000006141417507532300166370ustar00rootroot00000000000000parameters: 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 }} GSL-4.0.0/pipelines/steps.yml000066400000000000000000000000001417507532300160060ustar00rootroot00000000000000GSL-4.0.0/tests/000077500000000000000000000000001417507532300133115ustar00rootroot00000000000000GSL-4.0.0/tests/CMakeLists.txt000066400000000000000000000224061417507532300160550ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(GSLTests CXX) enable_testing() # again, for support standalone testing include(FindPkgConfig) include(ExternalProject) # will make visual studio generated project group files set_property(GLOBAL PROPERTY USE_FOLDERS ON) if(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 IOS_PROCESS_DELAY_WORKAROUND=1) endif() pkg_search_module(GTestMain gtest_main) if (NOT GTestMain_FOUND) # No pre-installed GTest is available, try to download it using Git. find_package(Git REQUIRED QUIET) configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) execute_process( COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . RESULT_VARIABLE result WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) if(result) message(FATAL_ERROR "CMake step for googletest failed: ${result}") endif() execute_process( COMMAND ${CMAKE_COMMAND} --build . RESULT_VARIABLE result WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) if(result) message(FATAL_ERROR "CMake step for googletest failed: ${result}") endif() set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) set(GTestMain_LIBRARIES gtest_main) add_subdirectory( ${CMAKE_CURRENT_BINARY_DIR}/googletest-src ${CMAKE_CURRENT_BINARY_DIR}/googletest-build EXCLUDE_FROM_ALL ) endif() if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) # CMake has been started independently in this directory with tests. Do # import the globally installed Guidelines Support Library and test it # instead of the current version from the include/ folder. find_package(Microsoft.GSL REQUIRED) endif() if (MSVC AND (GSL_CXX_STANDARD GREATER_EQUAL 17)) set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-) endif() # this interface adds compile options to how the tests are run # please try to keep entries ordered =) add_library(gsl_tests_config INTERFACE) if(MSVC) # MSVC or simulating MSVC target_compile_options(gsl_tests_config INTERFACE ${GSL_CPLUSPLUS_OPT} /EHsc /W4 /WX $<$: /wd4996 # Use of function or classes marked [[deprecated]] /wd26409 # CppCoreCheck - GTest /wd26426 # CppCoreCheck - GTest /wd26440 # CppCoreCheck - GTest /wd26446 # CppCoreCheck - prefer gsl::at() /wd26472 # CppCoreCheck - use gsl::narrow(_cast) /wd26481 # CppCoreCheck - use span instead of pointer arithmetic $<$,1920>: # VS2015 /wd4189 # variable is initialized but not referenced $<$>: # Release, RelWithDebInfo /wd4702 # Unreachable code > > > $<$: -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-covered-switch-default # GTest -Wno-deprecated-declarations # Allow tests for [[deprecated]] elements -Wno-global-constructors # GTest -Wno-language-extension-token # GTest gtest-port.h -Wno-missing-braces -Wno-missing-prototypes -Wno-shift-sign-overflow # GTest gtest-port.h -Wno-undef # GTest -Wno-used-but-marked-unused # GTest EXPECT_DEATH $<$: # no support for [[maybe_unused]] -Wno-unused-member-function -Wno-unused-variable > > ) else() target_compile_options(gsl_tests_config INTERFACE -fno-strict-aliasing -Wall -Wcast-align -Wconversion -Wctor-dtor-privacy -Werror -Wextra -Wpedantic -Wshadow -Wsign-conversion -Wno-deprecated-declarations # Allow tests for [[deprecated]] elements $<$,$>: -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-missing-braces -Wno-covered-switch-default # GTest -Wno-global-constructors # GTest -Wno-missing-prototypes -Wno-padded -Wno-unknown-attributes -Wno-used-but-marked-unused # GTest EXPECT_DEATH -Wno-weak-vtables $<$: # no support for [[maybe_unused]] -Wno-unused-member-function -Wno-unused-variable > > $<$: $<$,4.99>,$,6>>: $<$:-Wno-undefined-func-template> > $<$,$,$>>: -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) > > $<$: $<$,9.1>,$,10>>: $<$:-Wno-undefined-func-template> > > $<$: -Wdouble-promotion # float implicit to double -Wlogical-op # suspicious uses of logical operators $<$,6>>: -Wduplicated-cond # duplicated if-else conditions -Wmisleading-indentation -Wnull-dereference $<$: # no support for [[maybe_unused]] -Wno-unused-variable > > $<$,7>>: -Wduplicated-branches # identical if-else branches > > ) endif(MSVC) # for tests to find the gtest header target_include_directories(gsl_tests_config SYSTEM INTERFACE googletest/googletest/include ) add_executable(gsl_tests algorithm_tests.cpp assertion_tests.cpp at_tests.cpp byte_tests.cpp notnull_tests.cpp owner_tests.cpp span_compatibility_tests.cpp span_ext_tests.cpp span_tests.cpp strict_notnull_tests.cpp string_span_tests.cpp utils_tests.cpp ) target_link_libraries(gsl_tests Microsoft.GSL::GSL gsl_tests_config ${GTestMain_LIBRARIES} ) add_test(gsl_tests gsl_tests) # No exception tests foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) STRING (REGEX REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}") endforeach(flag_var) # this interface adds compile options to how the tests are run # please try to keep entries ordered =) add_library(gsl_tests_config_noexcept INTERFACE) if(MSVC) # MSVC or simulating MSVC target_compile_definitions(gsl_tests_config_noexcept INTERFACE _HAS_EXCEPTIONS=0 # disable exceptions in the Microsoft STL ) target_compile_options(gsl_tests_config_noexcept INTERFACE ${GSL_CPLUSPLUS_OPT} /W4 /WX $<$: /wd4577 /wd4702 /wd26440 # CppCoreCheck - GTest /wd26446 # CppCoreCheck - prefer gsl::at() > $<$: -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-missing-prototypes -Wno-unknown-attributes > ) else() target_compile_options(gsl_tests_config_noexcept INTERFACE -fno-exceptions -fno-strict-aliasing -Wall -Wcast-align -Wconversion -Wctor-dtor-privacy -Werror -Wextra -Wpedantic -Wshadow -Wsign-conversion $<$,$>: -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-missing-prototypes -Wno-unknown-attributes -Wno-weak-vtables > $<$: -Wdouble-promotion # float implicit to double -Wlogical-op # suspicious uses of logical operators -Wuseless-cast # casting to its own type $<$,6>>: -Wduplicated-cond # duplicated if-else conditions -Wmisleading-indentation -Wnull-dereference > $<$,7>>: -Wduplicated-branches # identical if-else branches > $<$,8>>: -Wcast-align=strict # increase alignment (i.e. char* to int*) > > ) endif(MSVC) add_executable(gsl_noexcept_tests no_exception_ensure_tests.cpp) target_link_libraries(gsl_noexcept_tests Microsoft.GSL::GSL gsl_tests_config_noexcept ) add_test(gsl_noexcept_tests gsl_noexcept_tests) GSL-4.0.0/tests/CMakeLists.txt.in000066400000000000000000000007351417507532300164630ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(googletest-download NONE) include(ExternalProject) ExternalProject_Add(googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG 1b18723e874b256c1e39378c6774a90701d70f7a SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) GSL-4.0.0/tests/algorithm_tests.cpp000066400000000000000000000144041417507532300172300ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include // for array #include // for size_t #include // for copy #include // for span #include #include "deathTestCommon.h" namespace gsl { struct fail_fast; } // namespace gsl using namespace gsl; TEST(algorithm_tests, same_type) { // dynamic source and destination span { std::array src{1, 2, 3, 4, 5}; std::array dst{}; const span src_span(src); const span dst_span(dst); copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); for (std::size_t i = 0; i < src.size(); ++i) { EXPECT_TRUE(dst[i] == src[i]); EXPECT_TRUE(dst[i + src.size()] == src[i]); } } // static source and dynamic destination span { std::array src{1, 2, 3, 4, 5}; std::array dst{}; const span src_span(src); const span dst_span(dst); copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); for (std::size_t i = 0; i < src.size(); ++i) { EXPECT_TRUE(dst[i] == src[i]); EXPECT_TRUE(dst[i + src.size()] == src[i]); } } // dynamic source and static destination span { std::array src{1, 2, 3, 4, 5}; std::array dst{}; const gsl::span src_span(src); const gsl::span dst_span(dst); copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); for (std::size_t i = 0; i < src.size(); ++i) { EXPECT_TRUE(dst[i] == src[i]); EXPECT_TRUE(dst[i + src.size()] == src[i]); } } // static source and destination span { std::array src{1, 2, 3, 4, 5}; std::array dst{}; const span src_span(src); const span dst_span(dst); copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); for (std::size_t i = 0; i < src.size(); ++i) { EXPECT_TRUE(dst[i] == src[i]); EXPECT_TRUE(dst[i + src.size()] == src[i]); } } } TEST(algorithm_tests, compatible_type) { // dynamic source and destination span { std::array src{1, 2, 3, 4, 5}; std::array dst{}; const span src_span(src); const span dst_span(dst); copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); for (std::size_t i = 0; i < src.size(); ++i) { EXPECT_TRUE(dst[i] == src[i]); EXPECT_TRUE(dst[i + src.size()] == src[i]); } } // static source and dynamic destination span { std::array src{1, 2, 3, 4, 5}; std::array dst{}; const span src_span(src); const span dst_span(dst); copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); for (std::size_t i = 0; i < src.size(); ++i) { EXPECT_TRUE(dst[i] == src[i]); EXPECT_TRUE(dst[i + src.size()] == src[i]); } } // dynamic source and static destination span { std::array src{1, 2, 3, 4, 5}; std::array dst{}; const span src_span(src); const span dst_span(dst); copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); for (std::size_t i = 0; i < src.size(); ++i) { EXPECT_TRUE(dst[i] == src[i]); EXPECT_TRUE(dst[i + src.size()] == src[i]); } } // static source and destination span { std::array src{1, 2, 3, 4, 5}; std::array dst{}; const span src_span(src); const span dst_span(dst); copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); for (std::size_t i = 0; i < src.size(); ++i) { EXPECT_TRUE(dst[i] == src[i]); EXPECT_TRUE(dst[i + src.size()] == src[i]); } } } #ifdef CONFIRM_COMPILATION_ERRORS TEST(algorithm_tests, incompatible_type) { std::array src{1, 2, 3, 4}; std::array dst{}; span src_span_dyn(src); span src_span_static(src); span dst_span_dyn(dst); span dst_span_static(dst); // every line should produce a compilation error copy(src_span_dyn, dst_span_dyn); copy(src_span_dyn, dst_span_static); copy(src_span_static, dst_span_dyn); copy(src_span_static, dst_span_static); } #endif TEST(algorithm_tests, small_destination_span) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. small_destination_span"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); std::array src{1, 2, 3, 4}; std::array dst{}; const span src_span_dyn(src); const span src_span_static(src); const span dst_span_dyn(dst); const span dst_span_static(dst); 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); #endif } GSL-4.0.0/tests/assertion_tests.cpp000066400000000000000000000031171417507532300172500ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include "deathTestCommon.h" #include // for fail_fast (ptr only), Ensures, Expects #include using namespace gsl; namespace { int f(int i) { Expects(i > 0 && i < 10); return i; } int g(int i) { i++; Ensures(i > 0 && i < 10); return i; } } // namespace TEST(assertion_tests, expects) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. expects"; std::abort(); }); EXPECT_TRUE(f(2) == 2); EXPECT_DEATH(f(10), GetExpectedDeathString(terminateHandler)); } TEST(assertion_tests, ensures) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. ensures"; std::abort(); }); EXPECT_TRUE(g(2) == 3); EXPECT_DEATH(g(9), GetExpectedDeathString(terminateHandler)); } GSL-4.0.0/tests/at_tests.cpp000066400000000000000000000126671417507532300156570ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for at #include // for array #include // for size_t #include // for initializer_list #include // for vector #if defined(__cplusplus) && __cplusplus >= 202002L #include #endif // __cplusplus >= 202002L #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) { EXPECT_TRUE(&gsl::at(a, i) == &a[i]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[i]); } 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), 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) { std::array a = {1, 2, 3, 4}; const std::array& c_a = a; for (int i = 0; i < 4; ++i) { EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); } 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), 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) { std::vector a = {1, 2, 3, 4}; const std::vector& c_a = a; for (int i = 0; i < 4; ++i) { EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); } 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), 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 a = {1, 2, 3, 4}; 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); } const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. InitializerList"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); EXPECT_DEATH(gsl::at(a, -1), expected); EXPECT_DEATH(gsl::at(a, 4), expected); EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), expected); EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), expected); } #if defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L TEST(at_tests, std_span) { std::vector vec{1, 2, 3, 4, 5}; std::span sp{vec}; std::vector cvec{1, 2, 3, 4, 5}; std::span csp{cvec}; for (gsl::index i = 0; i < gsl::narrow_cast(vec.size()); ++i) { EXPECT_TRUE(&gsl::at(sp, i) == &vec[gsl::narrow_cast(i)]); EXPECT_TRUE(&gsl::at(csp, i) == &cvec[gsl::narrow_cast(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(sp.size())), expected); EXPECT_DEATH(gsl::at(csp, -1), expected); EXPECT_DEATH(gsl::at(csp, gsl::narrow_cast(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() { int a1[4] = {1, 2, 3, 4}; const int(&c_a1)[4] = a1; std::array a2 = {1, 2, 3, 4}; const std::array& c_a2 = a2; 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: // if (&gsl::at(a2, i) != &a2[static_cast(i)]) return false; if (&gsl::at(c_a2, i) != &c_a2[static_cast(i)]) return false; if (gsl::at({1, 2, 3, 4}, i) != i + 1) return false; } return true; } static_assert(test_constexpr(), "FAIL"); #endif GSL-4.0.0/tests/byte_tests.cpp000066400000000000000000000066451417507532300162150ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for to_byte, to_integer, byte, operator&, ope... using namespace std; using namespace gsl; namespace { int modify_both(gsl::byte& b, int& i) { i = 10; b = to_byte<5>(); return i; } TEST(byte_tests, construction) { { const byte b = static_cast(4); EXPECT_TRUE(static_cast(b) == 4); } // clang-format off GSL_SUPPRESS(es.49) // clang-format on { const byte b = byte(12); EXPECT_TRUE(static_cast(b) == 12); } { const byte b = to_byte<12>(); EXPECT_TRUE(static_cast(b) == 12); } { const unsigned char uc = 12; const byte b = to_byte(uc); EXPECT_TRUE(static_cast(b) == 12); } #if defined(__cplusplus) && (__cplusplus >= 201703L) { const byte b{14}; EXPECT_TRUE(static_cast(b) == 14); } #endif } TEST(byte_tests, bitwise_operations) { const byte b = to_byte<0xFF>(); byte a = to_byte<0x00>(); EXPECT_TRUE((b | a) == to_byte<0xFF>()); EXPECT_TRUE(a == to_byte<0x00>()); a |= b; EXPECT_TRUE(a == to_byte<0xFF>()); a = to_byte<0x01>(); EXPECT_TRUE((b & a) == to_byte<0x01>()); a &= b; EXPECT_TRUE(a == to_byte<0x01>()); EXPECT_TRUE((b ^ a) == to_byte<0xFE>()); EXPECT_TRUE(a == to_byte<0x01>()); a ^= b; EXPECT_TRUE(a == to_byte<0xFE>()); a = to_byte<0x01>(); EXPECT_TRUE(~a == to_byte<0xFE>()); a = to_byte<0xFF>(); EXPECT_TRUE((a << 4) == to_byte<0xF0>()); EXPECT_TRUE((a >> 4) == to_byte<0x0F>()); a <<= 4; EXPECT_TRUE(a == to_byte<0xF0>()); a >>= 4; EXPECT_TRUE(a == to_byte<0x0F>()); } TEST(byte_tests, to_integer) { const byte b = to_byte<0x12>(); EXPECT_TRUE(0x12 == gsl::to_integer(b)); EXPECT_TRUE(0x12 == gsl::to_integer(b)); EXPECT_TRUE(0x12 == gsl::to_integer(b)); EXPECT_TRUE(0x12 == gsl::to_integer(b)); EXPECT_TRUE(0x12 == gsl::to_integer(b)); EXPECT_TRUE(0x12 == gsl::to_integer(b)); EXPECT_TRUE(0x12 == gsl::to_integer(b)); EXPECT_TRUE(0x12 == gsl::to_integer(b)); // EXPECT_TRUE(0x12 == gsl::to_integer(b)); // expect compile-time error // EXPECT_TRUE(0x12 == gsl::to_integer(b)); // expect compile-time error } TEST(byte_tests, aliasing) { int i{0}; const int res = modify_both(reinterpret_cast(i), i); EXPECT_TRUE(res == i); } } // namespace #ifdef CONFIRM_COMPILATION_ERRORS copy(src_span_static, dst_span_static); #endif GSL-4.0.0/tests/deathTestCommon.h000066400000000000000000000005741417507532300165660ustar00rootroot00000000000000#pragma once #include 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; } GSL-4.0.0/tests/no_exception_ensure_tests.cpp000066400000000000000000000031541417507532300213150ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for std::exit #include // for span #include #include int operator_subscript_no_throw() noexcept { int arr[10]; const gsl::span sp{arr}; return sp[11]; } [[noreturn]] void test_terminate() { std::exit(0); } void setup_termination_handler() noexcept { #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) auto& handler = gsl::details::get_terminate_handler(); handler = &test_terminate; #else std::set_terminate(test_terminate); #endif } 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; } GSL-4.0.0/tests/notnull_tests.cpp000066400000000000000000000404741417507532300167430ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for not_null, operator<, operator<=, operator> #include // for addressof #include // for shared_ptr, make_shared, operator<, opera... #include // for operator<<, ostringstream, basic_ostream:... #include // for uint16_t #include // for basic_string, operator==, string, operator<< #include // for type_info #include "deathTestCommon.h" using namespace gsl; struct MyBase { }; struct MyDerived : public MyBase { }; struct Unrelated { }; // stand-in for a user-defined ref-counted class template struct RefCounted { RefCounted(T* p) : p_(p) {} operator T*() { return p_; } T* p_; }; // user defined smart pointer with comparison operators returning non bool value template struct CustomPtr { CustomPtr(T* p) : p_(p) {} operator T*() { return p_; } bool operator!=(std::nullptr_t) const { return p_ != nullptr; } T* p_ = nullptr; }; template std::string operator==(CustomPtr const& lhs, CustomPtr const& rhs) { // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on return reinterpret_cast(lhs.p_) == reinterpret_cast(rhs.p_) ? "true" : "false"; } template std::string operator!=(CustomPtr const& lhs, CustomPtr const& rhs) { // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on return reinterpret_cast(lhs.p_) != reinterpret_cast(rhs.p_) ? "true" : "false"; } template std::string operator<(CustomPtr const& lhs, CustomPtr const& rhs) { // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on return reinterpret_cast(lhs.p_) < reinterpret_cast(rhs.p_) ? "true" : "false"; } template std::string operator>(CustomPtr const& lhs, CustomPtr const& rhs) { // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on return reinterpret_cast(lhs.p_) > reinterpret_cast(rhs.p_) ? "true" : "false"; } template std::string operator<=(CustomPtr const& lhs, CustomPtr const& rhs) { // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on return reinterpret_cast(lhs.p_) <= reinterpret_cast(rhs.p_) ? "true" : "false"; } template std::string operator>=(CustomPtr const& lhs, CustomPtr const& rhs) { // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // clang-format on return reinterpret_cast(lhs.p_) >= reinterpret_cast(rhs.p_) ? "true" : "false"; } struct NonCopyableNonMovable { NonCopyableNonMovable() = default; NonCopyableNonMovable(const NonCopyableNonMovable&) = delete; NonCopyableNonMovable& operator=(const NonCopyableNonMovable&) = delete; NonCopyableNonMovable(NonCopyableNonMovable&&) = delete; NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete; }; namespace { // clang-format off GSL_SUPPRESS(f .4) // NO-FORMAT: attribute // clang-format on bool helper(not_null p) { return *p == 12; } // clang-format off GSL_SUPPRESS(f .4) // NO-FORMAT: attribute // clang-format on bool helper_const(not_null p) { return *p == 12; } int* return_pointer() { return nullptr; } } // namespace TEST(notnull_tests, TestNotNullConstructors) { { #ifdef CONFIRM_COMPILATION_ERRORS not_null p = nullptr; // yay...does not compile! not_null*> p1 = 0; // yay...does not compile! not_null p2; // yay...does not compile! std::unique_ptr up = std::make_unique(120); not_null p3 = up; // Forbid non-nullptr assignable types not_null> f(std::vector{1}); not_null z(10); not_null> y({1, 2}); #endif } const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. TestNotNullConstructors"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); { // from shared pointer int i = 12; auto rp = RefCounted(&i); not_null p(rp); EXPECT_TRUE(p.get() == &i); not_null> x( std::make_shared(10)); // shared_ptr is nullptr assignable int* pi = nullptr; EXPECT_DEATH((not_null(pi)), expected); } { // from pointer to local int t = 42; not_null x = &t; helper(&t); helper_const(&t); EXPECT_TRUE(*x == 42); } { // from raw pointer // from not_null pointer int t = 42; int* p = &t; not_null x = p; helper(p); helper_const(p); helper(x); helper_const(x); EXPECT_TRUE(*x == 42); } { // from raw const pointer // from not_null const pointer int t = 42; const int* cp = &t; not_null x = cp; helper_const(cp); helper_const(x); EXPECT_TRUE(*x == 42); } { // from not_null const pointer, using auto int t = 42; const int* cp = &t; auto x = not_null{cp}; EXPECT_TRUE(*x == 42); } { // from returned pointer EXPECT_DEATH(helper(return_pointer()), expected); EXPECT_DEATH(helper_const(return_pointer()), expected); } } template void ostream_helper(T v) { not_null p(&v); { std::ostringstream os; std::ostringstream ref; os << static_cast(p); ref << static_cast(&v); EXPECT_TRUE(os.str() == ref.str()); } { std::ostringstream os; std::ostringstream ref; os << *p; ref << v; EXPECT_TRUE(os.str() == ref.str()); } } TEST(notnull_tests, TestNotNullostream) { ostream_helper(17); ostream_helper(21.5f); ostream_helper(3.4566e-7); ostream_helper('c'); ostream_helper(0x0123u); ostream_helper("cstring"); ostream_helper("string"); } TEST(notnull_tests, TestNotNullCasting) { MyBase base; MyDerived derived; Unrelated unrelated; not_null u{&unrelated}; (void) u; not_null p{&derived}; not_null q(&base); q = p; // allowed with heterogeneous copy ctor EXPECT_TRUE(q == p); #ifdef CONFIRM_COMPILATION_ERRORS q = u; // no viable conversion possible between MyBase* and Unrelated* p = q; // not possible to implicitly convert MyBase* to MyDerived* not_null r = p; not_null s = reinterpret_cast(p); #endif not_null t(reinterpret_cast(p.get())); EXPECT_TRUE(reinterpret_cast(p.get()) == reinterpret_cast(t.get())); } TEST(notnull_tests, TestNotNullAssignment) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. TestNotNullAssignmentd"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); int i = 12; not_null p(&i); EXPECT_TRUE(helper(p)); int* q = nullptr; EXPECT_DEATH(p = not_null(q), expected); } TEST(notnull_tests, TestNotNullRawPointerComparison) { int ints[2] = {42, 43}; int* p1 = &ints[0]; const int* p2 = &ints[1]; using NotNull1 = not_null; using NotNull2 = not_null; EXPECT_TRUE((NotNull1(p1) == NotNull1(p1)) == true); EXPECT_TRUE((NotNull1(p1) == NotNull2(p2)) == false); EXPECT_TRUE((NotNull1(p1) != NotNull1(p1)) == false); EXPECT_TRUE((NotNull1(p1) != NotNull2(p2)) == true); EXPECT_TRUE((NotNull1(p1) < NotNull1(p1)) == false); EXPECT_TRUE((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); EXPECT_TRUE((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); EXPECT_TRUE((NotNull1(p1) > NotNull1(p1)) == false); EXPECT_TRUE((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); EXPECT_TRUE((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); EXPECT_TRUE((NotNull1(p1) <= NotNull1(p1)) == true); EXPECT_TRUE((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); EXPECT_TRUE((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); } TEST(notnull_tests, TestNotNullDereferenceOperator) { { auto sp1 = std::make_shared(); using NotNullSp1 = not_null; EXPECT_TRUE(typeid(*sp1) == typeid(*NotNullSp1(sp1))); EXPECT_TRUE(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1)); } { int ints[1] = {42}; CustomPtr p1(&ints[0]); using NotNull1 = not_null; EXPECT_TRUE(typeid(*NotNull1(p1)) == typeid(*p1)); EXPECT_TRUE(*NotNull1(p1) == 42); *NotNull1(p1) = 43; EXPECT_TRUE(ints[0] == 43); } { int v = 42; gsl::not_null p(&v); EXPECT_TRUE(typeid(*p) == typeid(*(&v))); *p = 43; EXPECT_TRUE(v == 43); } } TEST(notnull_tests, TestNotNullSharedPtrComparison) { auto sp1 = std::make_shared(42); auto sp2 = std::make_shared(43); using NotNullSp1 = not_null; using NotNullSp2 = not_null; EXPECT_TRUE((NotNullSp1(sp1) == NotNullSp1(sp1)) == true); EXPECT_TRUE((NotNullSp1(sp1) == NotNullSp2(sp2)) == false); EXPECT_TRUE((NotNullSp1(sp1) != NotNullSp1(sp1)) == false); EXPECT_TRUE((NotNullSp1(sp1) != NotNullSp2(sp2)) == true); EXPECT_TRUE((NotNullSp1(sp1) < NotNullSp1(sp1)) == false); EXPECT_TRUE((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2)); EXPECT_TRUE((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1)); EXPECT_TRUE((NotNullSp1(sp1) > NotNullSp1(sp1)) == false); EXPECT_TRUE((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2)); EXPECT_TRUE((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1)); EXPECT_TRUE((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true); EXPECT_TRUE((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2)); EXPECT_TRUE((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1)); EXPECT_TRUE((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true); EXPECT_TRUE((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2)); EXPECT_TRUE((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1)); } TEST(notnull_tests, TestNotNullCustomPtrComparison) { int ints[2] = {42, 43}; CustomPtr p1(&ints[0]); CustomPtr p2(&ints[1]); using NotNull1 = not_null; using NotNull2 = not_null; EXPECT_TRUE((NotNull1(p1) == NotNull1(p1)) == "true"); EXPECT_TRUE((NotNull1(p1) == NotNull2(p2)) == "false"); EXPECT_TRUE((NotNull1(p1) != NotNull1(p1)) == "false"); EXPECT_TRUE((NotNull1(p1) != NotNull2(p2)) == "true"); EXPECT_TRUE((NotNull1(p1) < NotNull1(p1)) == "false"); EXPECT_TRUE((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); EXPECT_TRUE((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); EXPECT_TRUE((NotNull1(p1) > NotNull1(p1)) == "false"); EXPECT_TRUE((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); EXPECT_TRUE((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); EXPECT_TRUE((NotNull1(p1) <= NotNull1(p1)) == "true"); EXPECT_TRUE((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); EXPECT_TRUE((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); EXPECT_TRUE((NotNull1(p1) >= NotNull1(p1)) == "true"); EXPECT_TRUE((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2)); EXPECT_TRUE((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1)); } #if defined(__cplusplus) && (__cplusplus >= 201703L) TEST(notnull_tests, TestNotNullConstructorTypeDeduction) { { int i = 42; not_null x{&i}; helper(not_null{&i}); helper_const(not_null{&i}); EXPECT_TRUE(*x == 42); } { int i = 42; int* p = &i; not_null x{p}; helper(not_null{p}); helper_const(not_null{p}); EXPECT_TRUE(*x == 42); } 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(), expected); } { auto workaround_macro = []() { const int* p1 = nullptr; const not_null x{p1}; }; EXPECT_DEATH(workaround_macro(), expected); } { int* p = nullptr; EXPECT_DEATH(helper(not_null{p}), expected); EXPECT_DEATH(helper_const(not_null{p}), expected); } #ifdef CONFIRM_COMPILATION_ERRORS { not_null x{nullptr}; helper(not_null{nullptr}); helper_const(not_null{nullptr}); } #endif } #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) TEST(notnull_tests, TestMakeNotNull) { { int i = 42; const auto x = make_not_null(&i); helper(make_not_null(&i)); helper_const(make_not_null(&i)); EXPECT_TRUE(*x == 42); } { int i = 42; int* p = &i; const auto x = make_not_null(p); helper(make_not_null(p)); helper_const(make_not_null(p)); EXPECT_TRUE(*x == 42); } const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. TestMakeNotNull"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); { const auto workaround_macro = []() { int* p1 = nullptr; const auto x = make_not_null(p1); EXPECT_TRUE(*x == 42); }; EXPECT_DEATH(workaround_macro(), expected); } { const auto workaround_macro = []() { const int* p1 = nullptr; const auto x = make_not_null(p1); EXPECT_TRUE(*x == 42); }; EXPECT_DEATH(workaround_macro(), expected); } { int* p = nullptr; 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), expected); EXPECT_DEATH(helper(make_not_null(nullptr)), expected); EXPECT_DEATH(helper_const(make_not_null(nullptr)), expected); } #endif } TEST(notnull_tests, TestStdHash) { int x = 42; int y = 99; not_null nn{&x}; const not_null cnn{&x}; std::hash> hash_nn; std::hash hash_intptr; EXPECT_TRUE(hash_nn(nn) == hash_intptr(&x)); EXPECT_FALSE(hash_nn(nn) == hash_intptr(&y)); EXPECT_FALSE(hash_nn(nn) == hash_intptr(nullptr)); } GSL-4.0.0/tests/owner_tests.cpp000066400000000000000000000024051417507532300163720ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for owner using namespace gsl; GSL_SUPPRESS(f .23) // NO-FORMAT: attribute void f(int* i) { *i += 1; } TEST(owner_tests, basic_test) { owner p = new int(120); EXPECT_TRUE(*p == 120); f(p); EXPECT_TRUE(*p == 121); delete p; } TEST(owner_tests, check_pointer_constraint) { #ifdef CONFIRM_COMPILATION_ERRORS { owner integerTest = 10; owner> sharedPtrTest(new int(10)); } #endif } GSL-4.0.0/tests/span_compatibility_tests.cpp000066400000000000000000001661071417507532300211440ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for byte #include // for span, span_iterator, operator==, operator!= #include // for array #include // for ptrdiff_t #include // for reverse_iterator, operator-, operator== #include // for integral_constant<>::value, is_default_co... #include #include // for vector using namespace std; using namespace gsl; // Below are tests that verify the gsl interface support the same things as the std // Ranges and Concepts support need to be added later. struct Base { }; struct Derived : Base { }; static_assert(std::is_convertible::value, "std::is_convertible"); static_assert(!std::is_convertible::value, "!std::is_convertible"); // int*(*) [], int const* const(*)[] was identified as an issue in CWG330 and the resolution was // provided with N4261. template void ArrayConvertibilityCheck() { #if __cplusplus >= 201703l if constexpr (std::is_convertible::value) { std::array stl_nullptr{{nullptr, nullptr, nullptr}}; gsl::span sp_const_nullptr_1{stl_nullptr}; EXPECT_TRUE(sp_const_nullptr_1.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_1.size() == 3); gsl::span 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>::value, "std::is_same< decltype(span{stl_nullptr}), span>::value"); static_assert( std::is_same>::value, "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span>::value"); } #endif } TEST(span_compatibility_tests, assertion_tests) { int arr[3]{10, 20, 30}; std::array stl{{100, 200, 300}}; ArrayConvertibilityCheck(); { gsl::span sp_dyn; EXPECT_TRUE(sp_dyn.data() == nullptr); EXPECT_TRUE(sp_dyn.size() == 0); EXPECT_TRUE(sp_dyn.empty()); } { gsl::span sp_zero; EXPECT_TRUE(sp_zero.data() == nullptr); EXPECT_TRUE(sp_zero.size() == 0); EXPECT_TRUE(sp_zero.empty()); gsl::span sp_dyn_a(arr, 3); gsl::span sp_dyn_b(begin(arr), 3); EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); EXPECT_TRUE(sp_dyn_b.data() == std::begin(arr)); EXPECT_TRUE(sp_dyn_a.size() == 3); EXPECT_TRUE(sp_dyn_b.size() == 3); gsl::span sp_three_a(arr, 3); gsl::span sp_three_b(begin(arr), 3); EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); EXPECT_TRUE(sp_three_b.data() == std::begin(arr)); EXPECT_TRUE(sp_three_a.size() == 3); EXPECT_TRUE(sp_three_b.size() == 3); gsl::span sp_const_a(arr, 3); gsl::span sp_const_b(begin(arr), 3); EXPECT_TRUE(sp_const_a.data() == std::begin(arr)); EXPECT_TRUE(sp_const_b.data() == std::begin(arr)); EXPECT_TRUE(sp_const_a.size() == 3); EXPECT_TRUE(sp_const_b.size() == 3); #if __cplusplus >= 201703l gsl::span sp_const_c(std::as_const(arr), 3); EXPECT_TRUE(sp_const_c.data() == std::begin(arr)); EXPECT_TRUE(sp_const_c.size() == 3); #endif // __cplusplus >= 201703l gsl::span sp_const_d(cbegin(arr), 3); EXPECT_TRUE(sp_const_d.data() == std::begin(arr)); EXPECT_TRUE(sp_const_d.size() == 3); } { gsl::span sp_dyn_a(begin(arr), std::end(arr)); EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); EXPECT_TRUE(sp_dyn_a.size() == 3); gsl::span sp_three_a(begin(arr), std::end(arr)); EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); EXPECT_TRUE(sp_three_a.size() == 3); gsl::span sp_const_a(begin(arr), std::end(arr)); gsl::span sp_const_b(begin(arr), std::cend(arr)); gsl::span sp_const_c(cbegin(arr), std::end(arr)); gsl::span sp_const_d(cbegin(arr), std::cend(arr)); EXPECT_TRUE(sp_const_a.data() == std::begin(arr)); EXPECT_TRUE(sp_const_b.data() == std::begin(arr)); EXPECT_TRUE(sp_const_c.data() == std::begin(arr)); EXPECT_TRUE(sp_const_d.data() == std::begin(arr)); EXPECT_TRUE(sp_const_a.size() == 3); EXPECT_TRUE(sp_const_b.size() == 3); EXPECT_TRUE(sp_const_c.size() == 3); EXPECT_TRUE(sp_const_d.size() == 3); } { gsl::span sp_dyn_a(arr); gsl::span sp_dyn_b(stl); gsl::span sp_dyn_c{stl}; gsl::span sp_dyn_d{stl}; EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); EXPECT_TRUE(sp_dyn_b.data() == stl.data()); EXPECT_TRUE(sp_dyn_a.size() == 3); EXPECT_TRUE(sp_dyn_b.size() == 3); gsl::span sp_three_a(arr); gsl::span sp_three_b(stl); EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); EXPECT_TRUE(sp_three_b.data() == stl.data()); EXPECT_TRUE(sp_three_a.size() == 3); EXPECT_TRUE(sp_three_b.size() == 3); gsl::span sp_const_w(arr); gsl::span sp_const_y(stl); EXPECT_TRUE(sp_const_w.data() == std::begin(arr)); EXPECT_TRUE(sp_const_y.data() == stl.data()); EXPECT_TRUE(sp_const_w.size() == 3); EXPECT_TRUE(sp_const_y.size() == 3); #if __cplusplus >= 201703l gsl::span sp_const_x(std::as_const(arr)); EXPECT_TRUE(sp_const_x.data() == std::begin(arr)); EXPECT_TRUE(sp_const_x.size() == 3); gsl::span sp_const_z(std::as_const(stl)); EXPECT_TRUE(sp_const_z.data() == stl.data()); EXPECT_TRUE(sp_const_z.size() == 3); #endif // __cplusplus >= 201703l } { const gsl::span orig_dyn(arr); const gsl::span orig_three(arr); const gsl::span orig_const_dyn(arr); const gsl::span orig_const_three(arr); gsl::span sp_a(orig_dyn); gsl::span sp_b(orig_three); gsl::span sp_c(orig_three); gsl::span sp_d(orig_dyn); gsl::span sp_e(orig_three); gsl::span sp_f(orig_const_dyn); gsl::span sp_g(orig_const_three); gsl::span sp_h(orig_three); gsl::span sp_i(orig_const_three); EXPECT_TRUE(sp_a.data() == std::begin(arr)); EXPECT_TRUE(sp_b.data() == std::begin(arr)); EXPECT_TRUE(sp_c.data() == std::begin(arr)); EXPECT_TRUE(sp_d.data() == std::begin(arr)); EXPECT_TRUE(sp_e.data() == std::begin(arr)); EXPECT_TRUE(sp_f.data() == std::begin(arr)); EXPECT_TRUE(sp_g.data() == std::begin(arr)); EXPECT_TRUE(sp_h.data() == std::begin(arr)); EXPECT_TRUE(sp_i.data() == std::begin(arr)); EXPECT_TRUE(sp_a.size() == 3); EXPECT_TRUE(sp_b.size() == 3); EXPECT_TRUE(sp_c.size() == 3); EXPECT_TRUE(sp_d.size() == 3); EXPECT_TRUE(sp_e.size() == 3); EXPECT_TRUE(sp_f.size() == 3); EXPECT_TRUE(sp_g.size() == 3); EXPECT_TRUE(sp_h.size() == 3); EXPECT_TRUE(sp_i.size() == 3); } { gsl::span sp_dyn(arr); gsl::span sp_three(arr); gsl::span sp_const_dyn(arr); gsl::span sp_const_three(arr); EXPECT_TRUE(sp_dyn.data() == std::begin(arr)); EXPECT_TRUE(sp_three.data() == std::begin(arr)); EXPECT_TRUE(sp_const_dyn.data() == std::begin(arr)); EXPECT_TRUE(sp_const_three.data() == std::begin(arr)); EXPECT_TRUE(sp_dyn.size() == 3); EXPECT_TRUE(sp_three.size() == 3); EXPECT_TRUE(sp_const_dyn.size() == 3); EXPECT_TRUE(sp_const_three.size() == 3); int other[4]{12, 34, 56, 78}; sp_dyn = gsl::span{other}; sp_three = gsl::span{stl}; sp_const_dyn = gsl::span{other}; sp_const_three = gsl::span{stl}; EXPECT_TRUE(sp_dyn.data() == std::begin(other)); EXPECT_TRUE(sp_three.data() == stl.data()); EXPECT_TRUE(sp_const_dyn.data() == std::begin(other)); EXPECT_TRUE(sp_const_three.data() == stl.data()); EXPECT_TRUE(sp_dyn.size() == 4); EXPECT_TRUE(sp_three.size() == 3); EXPECT_TRUE(sp_const_dyn.size() == 4); EXPECT_TRUE(sp_const_three.size() == 3); } { gsl::span::iterator it_dyn{}; { gsl::span sp_dyn(arr); it_dyn = sp_dyn.begin(); } EXPECT_TRUE(*it_dyn == arr[0]); EXPECT_TRUE(it_dyn[2] == arr[2]); gsl::span::iterator it_three{}; { gsl::span sp_three(stl); it_three = sp_three.begin(); } EXPECT_TRUE(*it_three == stl[0]); EXPECT_TRUE(it_three[2] == stl[2]); } { int sequence[9]{10, 20, 30, 40, 50, 60, 70, 80, 90}; const gsl::span sp_dyn(sequence); const gsl::span sp_nine(sequence); auto first_3 = sp_dyn.first<3>(); auto first_4 = sp_nine.first<4>(); auto first_5 = sp_dyn.first(5); auto first_6 = sp_nine.first(6); static_assert(noexcept(sp_dyn.first<3>()), "noexcept(sp_dyn.first<3>())"); // strengthened static_assert(noexcept(sp_nine.first<4>()), "noexcept(sp_nine.first<4>())"); // strengthened static_assert(noexcept(sp_dyn.first(5)), "noexcept(sp_dyn.first(5))"); // strengthened static_assert(noexcept(sp_nine.first(6)), "noexcept(sp_nine.first(6))"); // strengthened static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); EXPECT_TRUE(first_3.data() == std::begin(sequence)); EXPECT_TRUE(first_4.data() == std::begin(sequence)); EXPECT_TRUE(first_5.data() == std::begin(sequence)); EXPECT_TRUE(first_6.data() == std::begin(sequence)); EXPECT_TRUE(first_3.size() == 3); EXPECT_TRUE(first_4.size() == 4); EXPECT_TRUE(first_5.size() == 5); EXPECT_TRUE(first_6.size() == 6); auto last_3 = sp_dyn.last<3>(); auto last_4 = sp_nine.last<4>(); auto last_5 = sp_dyn.last(5); auto last_6 = sp_nine.last(6); static_assert(noexcept(sp_dyn.last<3>()), "noexcept(sp_dyn.last<3>())"); // strengthened static_assert(noexcept(sp_nine.last<4>()), "noexcept(sp_nine.last<4>())"); // strengthened static_assert(noexcept(sp_dyn.last(5)), "noexcept(sp_dyn.last(5))"); // strengthened static_assert(noexcept(sp_nine.last(6)), "noexcept(sp_nine.last(6))"); // strengthened static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); EXPECT_TRUE(last_3.data() == std::begin(sequence) + 6); EXPECT_TRUE(last_4.data() == std::begin(sequence) + 5); EXPECT_TRUE(last_5.data() == std::begin(sequence) + 4); EXPECT_TRUE(last_6.data() == std::begin(sequence) + 3); EXPECT_TRUE(last_3.size() == 3); EXPECT_TRUE(last_4.size() == 4); EXPECT_TRUE(last_5.size() == 5); EXPECT_TRUE(last_6.size() == 6); auto offset_3 = sp_dyn.subspan<3>(); auto offset_4 = sp_nine.subspan<4>(); auto offset_5 = sp_dyn.subspan(5); auto offset_6 = sp_nine.subspan(6); static_assert(noexcept(sp_dyn.subspan<3>()), "noexcept(sp_dyn.subspan<3>())"); // strengthened static_assert(noexcept(sp_nine.subspan<4>()), "noexcept(sp_nine.subspan<4>())"); // strengthened static_assert(noexcept(sp_dyn.subspan(5)), "noexcept(sp_dyn.subspan(5))"); // strengthened static_assert(noexcept(sp_nine.subspan(6)), "noexcept(sp_nine.subspan(6))"); // strengthened static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); EXPECT_TRUE(offset_3.data() == std::begin(sequence) + 3); EXPECT_TRUE(offset_4.data() == std::begin(sequence) + 4); EXPECT_TRUE(offset_5.data() == std::begin(sequence) + 5); EXPECT_TRUE(offset_6.data() == std::begin(sequence) + 6); EXPECT_TRUE(offset_3.size() == 6); EXPECT_TRUE(offset_4.size() == 5); EXPECT_TRUE(offset_5.size() == 4); EXPECT_TRUE(offset_6.size() == 3); auto subspan_3 = sp_dyn.subspan<3, 2>(); auto subspan_4 = sp_nine.subspan<4, 2>(); auto subspan_5 = sp_dyn.subspan(5, 2); auto subspan_6 = sp_nine.subspan(6, 2); static_assert(noexcept(sp_dyn.subspan<3, 2>()), "noexcept(sp_dyn.subspan<3, 2>())"); // strengthened static_assert(noexcept(sp_nine.subspan<4, 2>()), "noexcept(sp_nine.subspan<4, 2>())"); // strengthened static_assert(noexcept(sp_dyn.subspan(5, 2)), "noexcept(sp_dyn.subspan(5, 2))"); // strengthened static_assert(noexcept(sp_nine.subspan(6, 2)), "noexcept(sp_nine.subspan(6, 2))"); // strengthened static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); EXPECT_TRUE(subspan_3.data() == std::begin(sequence) + 3); EXPECT_TRUE(subspan_4.data() == std::begin(sequence) + 4); EXPECT_TRUE(subspan_5.data() == std::begin(sequence) + 5); EXPECT_TRUE(subspan_6.data() == std::begin(sequence) + 6); EXPECT_TRUE(subspan_3.size() == 2); EXPECT_TRUE(subspan_4.size() == 2); EXPECT_TRUE(subspan_5.size() == 2); EXPECT_TRUE(subspan_6.size() == 2); static_assert(noexcept(sp_dyn.size()), "noexcept(sp_dyn.size())"); static_assert(noexcept(sp_dyn.size_bytes()), "noexcept(sp_dyn.size_bytes())"); static_assert(noexcept(sp_dyn.empty()), "noexcept(sp_dyn.empty())"); static_assert(noexcept(sp_dyn[0]), "noexcept(sp_dyn[0])"); // strengthened static_assert(noexcept(sp_dyn.front()), "noexcept(sp_dyn.front())"); // strengthened static_assert(noexcept(sp_dyn.back()), "noexcept(sp_dyn.back())"); // strengthened static_assert(noexcept(sp_dyn.data()), "noexcept(sp_dyn.data())"); static_assert(noexcept(sp_dyn.begin()), "noexcept(sp_dyn.begin())"); static_assert(noexcept(sp_dyn.end()), "noexcept(sp_dyn.end())"); static_assert(noexcept(sp_dyn.rbegin()), "noexcept(sp_dyn.rbegin())"); static_assert(noexcept(sp_dyn.rend()), "noexcept(sp_dyn.rend())"); static_assert(noexcept(sp_nine.size()), "noexcept(sp_nine.size())"); static_assert(noexcept(sp_nine.size_bytes()), "noexcept(sp_nine.size_bytes())"); static_assert(noexcept(sp_nine.empty()), "noexcept(sp_nine.empty())"); static_assert(noexcept(sp_nine[0]), "noexcept(sp_nine[0])"); // strengthened static_assert(noexcept(sp_nine.front()), "noexcept(sp_nine.front())"); // strengthened static_assert(noexcept(sp_nine.back()), "noexcept(sp_nine.back())"); // strengthened static_assert(noexcept(sp_nine.data()), "noexcept(sp_nine.data())"); static_assert(noexcept(sp_nine.begin()), "noexcept(sp_nine.begin())"); static_assert(noexcept(sp_nine.end()), "noexcept(sp_nine.end())"); static_assert(noexcept(sp_nine.rbegin()), "noexcept(sp_nine.rbegin())"); static_assert(noexcept(sp_nine.rend()), "noexcept(sp_nine.rend())"); EXPECT_TRUE(sp_dyn.size() == 9); EXPECT_TRUE(sp_nine.size() == 9); EXPECT_TRUE(sp_dyn.size_bytes() == 9 * sizeof(int)); EXPECT_TRUE(sp_nine.size_bytes() == 9 * sizeof(int)); EXPECT_TRUE(!sp_dyn.empty()); EXPECT_TRUE(!sp_nine.empty()); EXPECT_TRUE(sp_dyn[0] == 10); EXPECT_TRUE(sp_nine[0] == 10); EXPECT_TRUE(sp_dyn[8] == 90); EXPECT_TRUE(sp_nine[8] == 90); EXPECT_TRUE(sp_dyn.front() == 10); EXPECT_TRUE(sp_nine.front() == 10); EXPECT_TRUE(sp_dyn.back() == 90); EXPECT_TRUE(sp_nine.back() == 90); EXPECT_TRUE(&sp_dyn.front() == std::begin(sequence)); EXPECT_TRUE(&sp_nine.front() == std::begin(sequence)); EXPECT_TRUE(&sp_dyn[4] == std::begin(sequence) + 4); EXPECT_TRUE(&sp_nine[4] == std::begin(sequence) + 4); EXPECT_TRUE(&sp_dyn.back() == std::begin(sequence) + 8); EXPECT_TRUE(&sp_nine.back() == std::begin(sequence) + 8); EXPECT_TRUE(sp_dyn.data() == std::begin(sequence)); EXPECT_TRUE(sp_nine.data() == std::begin(sequence)); EXPECT_TRUE(*sp_dyn.begin() == 10); EXPECT_TRUE(*sp_nine.begin() == 10); EXPECT_TRUE(sp_dyn.end()[-2] == 80); EXPECT_TRUE(sp_nine.end()[-2] == 80); EXPECT_TRUE(*sp_dyn.rbegin() == 90); EXPECT_TRUE(*sp_nine.rbegin() == 90); EXPECT_TRUE(sp_dyn.rend()[-2] == 20); EXPECT_TRUE(sp_nine.rend()[-2] == 20); static_assert(is_same::iterator>::value, "is_same::iterator>::value"); static_assert(is_same::iterator>::value, "is_same::iterator>::value"); static_assert(is_same::iterator>::value, "is_same::iterator>::value"); static_assert(is_same::iterator>::value, "is_same::iterator>::value"); static_assert( is_same::reverse_iterator>::value, "is_same::reverse_iterator>::value"); static_assert( is_same::reverse_iterator>::value, "is_same::reverse_iterator>::value"); static_assert(is_same::reverse_iterator>::value, "is_same::reverse_iterator>::value"); static_assert( is_same::reverse_iterator>::value, "is_same::reverse_iterator>::value"); } { int sequence[9]{10, 20, 30, 40, 50, 60, 70, 80, 90}; constexpr size_t SizeBytes = sizeof(sequence); const gsl::span sp_dyn(sequence); const gsl::span sp_nine(sequence); const gsl::span sp_const_dyn(sequence); const gsl::span sp_const_nine(sequence); static_assert(noexcept(as_bytes(sp_dyn)), "noexcept(as_bytes(sp_dyn))"); static_assert(noexcept(as_bytes(sp_nine)), "noexcept(as_bytes(sp_nine))"); static_assert(noexcept(as_bytes(sp_const_dyn)), "noexcept(as_bytes(sp_const_dyn))"); static_assert(noexcept(as_bytes(sp_const_nine)), "noexcept(as_bytes(sp_const_nine))"); static_assert(noexcept(as_writable_bytes(sp_dyn)), "noexcept(as_writable_bytes(sp_dyn))"); static_assert(noexcept(as_writable_bytes(sp_nine)), "noexcept(as_writable_bytes(sp_nine))"); auto sp_1 = as_bytes(sp_dyn); auto sp_2 = as_bytes(sp_nine); auto sp_3 = as_bytes(sp_const_dyn); auto sp_4 = as_bytes(sp_const_nine); auto sp_5 = as_writable_bytes(sp_dyn); auto sp_6 = as_writable_bytes(sp_nine); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); static_assert(is_same>::value, "is_same>::value"); EXPECT_TRUE(sp_1.data() == reinterpret_cast(begin(sequence))); EXPECT_TRUE(sp_2.data() == reinterpret_cast(begin(sequence))); EXPECT_TRUE(sp_3.data() == reinterpret_cast(begin(sequence))); EXPECT_TRUE(sp_4.data() == reinterpret_cast(begin(sequence))); EXPECT_TRUE(sp_5.data() == reinterpret_cast(begin(sequence))); EXPECT_TRUE(sp_6.data() == reinterpret_cast(begin(sequence))); EXPECT_TRUE(sp_1.size() == SizeBytes); EXPECT_TRUE(sp_2.size() == SizeBytes); EXPECT_TRUE(sp_3.size() == SizeBytes); EXPECT_TRUE(sp_4.size() == SizeBytes); EXPECT_TRUE(sp_5.size() == SizeBytes); EXPECT_TRUE(sp_6.size() == SizeBytes); } } // assertions for span's definition static_assert(std::is_same::value, "gsl::dynamic_extent must be respresented as std::size_t"); static_assert(gsl::dynamic_extent == static_cast(-1), "gsl::dynamic_extent must be defined as the max value of std::size_t"); static_assert(std::is_same::extent), const std::size_t>::value, "Ensure that the type of gsl::span::extent is std::size_t"); static_assert(gsl::span::extent == gsl::dynamic_extent, "gsl::span::extent should be equivalent to gsl::dynamic_extent"); static_assert(std::is_same::extent), const std::size_t>::value, "Ensure that the type of gsl::span::extent is std::size_t"); static_assert(gsl::span::extent == 3, "Ensure that span::extent is equal to 3"); static_assert(std::is_same::element_type, int>::value, "span::element_type should be int"); static_assert(std::is_same::value_type, int>::value, "span::value_type should be int"); static_assert(std::is_same::size_type, std::size_t>::value, "span::size_type should be std::size_t"); static_assert(std::is_same::difference_type, ptrdiff_t>::value, "span::difference_type should be std::ptrdiff_t"); static_assert(std::is_same::pointer, int*>::value, "span::pointer should be int*"); static_assert(std::is_same::const_pointer, const int*>::value, "span::const_pointer should be const int*"); static_assert(std::is_same::reference, int&>::value, "span::reference should be int&"); static_assert(std::is_same::const_reference, const int&>::value, "span::const_reference should be const int&"); static_assert(std::is_same::element_type, int>::value, "span::element_type should be int"); static_assert(std::is_same::value_type, int>::value, "span::value_type should be int"); static_assert(std::is_same::size_type, std::size_t>::value, "span::size_type should be std::size_t"); static_assert(std::is_same::difference_type, ptrdiff_t>::value, "span::difference_type should be std::ptrdiff_t"); static_assert(std::is_same::pointer, int*>::value, "span::pointer should be int*"); static_assert(std::is_same::const_pointer, const int*>::value, "span::const_pointer should be const int*"); static_assert(std::is_same::reference, int&>::value, "span::reference should be int&"); static_assert(std::is_same::const_reference, const int&>::value, "span::const_reference should be const int&"); static_assert(std::is_same::element_type, const int>::value, "span::element_type should be const int"); static_assert(std::is_same::value_type, int>::value, "span::value_type should be int"); static_assert(std::is_same::size_type, std::size_t>::value, "span::size_type should be size_t"); static_assert(std::is_same::difference_type, ptrdiff_t>::value, "span::difference_type should be ptrdiff_t"); static_assert(std::is_same::pointer, const int*>::value, "span::pointer should be const int*"); static_assert(std::is_same::const_pointer, const int*>::value, "span::const_pointer should be const int*"); static_assert(std::is_same::reference, const int&>::value, "span::reference should be const int&"); static_assert(std::is_same::const_reference, const int&>::value, "span::const_reference should be const int&"); static_assert(std::is_same::element_type, const int>::value, "span::element_type should be const int"); static_assert(std::is_same::value_type, int>::value, "span::value_type should be int"); static_assert(std::is_same::size_type, std::size_t>::value, "span::size_type should be size_t"); static_assert(std::is_same::difference_type, ptrdiff_t>::value, "span::difference_type should be ptrdiff_t"); static_assert(std::is_same::pointer, const int*>::value, "span::pointer should be const int*"); static_assert(std::is_same::const_pointer, const int*>::value, "span::const_pointer should be const int*"); static_assert(std::is_same::reference, const int&>::value, "span::reference should be const int&"); static_assert(std::is_same::const_reference, const int&>::value, "span::const_reference should be const int&"); // assertions for span_iterator static_assert(std::is_same::iterator>::pointer, int*>::value, "span::iterator's pointer should be int*"); static_assert( std::is_same::reverse_iterator, std::reverse_iterator::iterator>>::value, "span::reverse_iterator should equal std::reverse_iterator::iterator>"); static_assert(std::is_same::iterator>::pointer, int*>::value, "span::iterator's pointer should be int*"); static_assert( std::is_same::reverse_iterator, std::reverse_iterator::iterator>>::value, "span::reverse_iterator should equal std::reverse_iterator::iterator>"); static_assert( std::is_same::iterator>::pointer, const int*>::value, "span::iterator's pointer should be int*"); static_assert(std::is_same::reverse_iterator, std::reverse_iterator::iterator>>::value, "span::reverse_iterator should equal std::reverse_iterator::iterator>"); static_assert(std::is_same::iterator>::pointer, const int*>::value, "span::iterator's pointer should be int*"); static_assert(std::is_same::reverse_iterator, std::reverse_iterator::iterator>>::value, "span::reverse_iterator should equal std::reverse_iterator::iterator>"); // copyability assertions static_assert(std::is_trivially_copyable>::value, "span should be trivially copyable"); static_assert(std::is_trivially_copyable::iterator>::value, "span::iterator should be trivially copyable"); static_assert(std::is_trivially_copyable>::value, "span should be trivially copyable"); static_assert(std::is_trivially_copyable::iterator>::value, "span::iterator should be trivially copyable"); static_assert(std::is_trivially_copyable>::value, "span should be trivially copyable"); static_assert(std::is_trivially_copyable::iterator>::value, "span::iterator should be trivially copyable"); static_assert(std::is_trivially_copyable>::value, "span should be trivially copyable"); static_assert(std::is_trivially_copyable::iterator>::value, "span::iterator should be trivially copyable"); // nothrow constructible assertions static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, "std::is_nothrow_constructible, int*, std::size_t>"); static_assert(std::is_nothrow_constructible, int*, std::uint16_t>::value, "std::is_nothrow_constructible, int*, std::uint16_t>"); static_assert(std::is_nothrow_constructible, int*, int*>::value, "std::is_nothrow_constructible, int*, int*>"); static_assert(std::is_nothrow_constructible, int (&)[3]>::value, "std::is_nothrow_constructible, int(&)[3]>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, std::array&>::value, "std::is_nothrow_constructible, std::array&>"); static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, "std::is_nothrow_constructible, int*, std::size_t>"); static_assert(std::is_nothrow_constructible, int*, std::uint16_t>::value, "std::is_nothrow_constructible, int*, std::uint16_t>"); static_assert(std::is_nothrow_constructible, int*, int*>::value, "std::is_nothrow_constructible, int*, int*>"); static_assert(std::is_nothrow_constructible, int (&)[3]>::value, "std::is_nothrow_constructible, int(&)[3]>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, std::array&>::value, "std::is_nothrow_constructible, std::array&>"); static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, "std::is_nothrow_constructible, int*, std::size_t>"); static_assert(std::is_nothrow_constructible, int*, int*>::value, "std::is_nothrow_constructible, int*, int*>"); static_assert(std::is_nothrow_constructible, int*, const int*>::value, "std::is_nothrow_constructible, int*, const int*>"); static_assert(std::is_nothrow_constructible, int (&)[3]>::value, "std::is_nothrow_constructible, int(&)[3]>"); static_assert(std::is_nothrow_constructible, const int*, int*>::value, "std::is_nothrow_constructible, const int*, int*>"); static_assert(std::is_nothrow_constructible, const int*, const int*>::value, "std::is_nothrow_constructible, const int*, const int*>"); static_assert(std::is_nothrow_constructible, const int*, std::size_t>::value, "std::is_nothrow_constructible, const int*, std::size_t>"); static_assert(std::is_nothrow_constructible, const int (&)[3]>::value, "std::is_nothrow_constructible, const int(&)[3]>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, std::array&>::value, "std::is_nothrow_constructible, std::array&>"); static_assert(std::is_nothrow_constructible, const std::array&>::value, "std::is_nothrow_constructible, const std::array&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, "std::is_nothrow_constructible, Base(&)[3]>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, std::array&>::value, "std::is_nothrow_constructible, std::array&>"); static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, "std::is_nothrow_constructible, Base(&)[3]>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, std::array&>::value, "std::is_nothrow_constructible, std::array&>"); static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, "std::is_nothrow_constructible, Base(&)[3]>"); static_assert(std::is_nothrow_constructible, const Base (&)[3]>::value, "std::is_nothrow_constructible, const Base(&)[3]>"); static_assert(std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert(std::is_nothrow_constructible, std::array&>::value, "std::is_nothrow_constructible, std::array&>"); static_assert( std::is_nothrow_constructible, const std::array&>::value, "std::is_nothrow_constructible, const std::array&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); static_assert( std::is_nothrow_constructible, const gsl::span&>::value, "std::is_nothrow_constructible, const gsl::span&>"); // non-constructible assertions static_assert(!std::is_constructible, const int*, int*>::value, "!std::is_constructible, const int*, int*>"); static_assert(!std::is_constructible, const int*, const int*>::value, "!std::is_constructible, const int*, const int*>"); static_assert(!std::is_constructible, const int*, double*>::value, "!std::is_constructible, const int*, double*>"); static_assert(!std::is_constructible, const int*, std::size_t>::value, "!std::is_constructible, const int*, std::size_t>"); static_assert(!std::is_constructible, const int (&)[3]>::value, "!std::is_constructible, const int(&)[3]>"); static_assert(!std::is_constructible, double*, int*>::value, "!std::is_constructible, double*, int*>"); static_assert(!std::is_constructible, double*, const int*>::value, "!std::is_constructible, double*, const int*>"); static_assert(!std::is_constructible, double*, double*>::value, "!std::is_constructible, double*, double*>"); static_assert(!std::is_constructible, double*, std::size_t>::value, "!std::is_constructible, double*, std::size_t>"); static_assert(!std::is_constructible, double (&)[3]>::value, "!std::is_constructible, double(&)[3]>"); static_assert(!std::is_constructible, int*, double*>::value, "!std::is_constructible, int*, double*>"); static_assert(!std::is_constructible, std::size_t, int*>::value, "!std::is_constructible, std::size_t, int*>"); static_assert(!std::is_constructible, std::size_t, std::size_t>::value, "!std::is_constructible, std::size_t, std::size_t>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); static_assert(!std::is_constructible, const std::array&>::value, "!std::is_constructible, const std::array&>"); static_assert(!std::is_constructible, int*, double*>::value, "!std::is_constructible, int*, double*>"); static_assert(!std::is_constructible, int (&)[500]>::value, "!std::is_constructible, int(&)[500]>"); static_assert(!std::is_constructible, const int*, int*>::value, "!std::is_constructible, const int*, int*>"); static_assert(!std::is_constructible, const int*, const int*>::value, "!std::is_constructible, const int*, const int*>"); static_assert(!std::is_constructible, const int*, std::size_t>::value, "!std::is_constructible, const int*, std::size_t>"); static_assert(!std::is_constructible, const int*, double*>::value, "!std::is_constructible, const int*, double*>"); static_assert(!std::is_constructible, const int (&)[3]>::value, "!std::is_constructible, const int(&)[3]>"); static_assert(!std::is_constructible, double*, std::size_t>::value, "!std::is_constructible, double*, std::size_t>"); static_assert(!std::is_constructible, double*, int*>::value, "!std::is_constructible, double*, int*>"); static_assert(!std::is_constructible, double*, const int*>::value, "!std::is_constructible, double*, const int*>"); static_assert(!std::is_constructible, double*, double*>::value, "!std::is_constructible, double*, double*>"); static_assert(!std::is_constructible, double (&)[3]>::value, "!std::is_constructible, double(&)[3]>"); static_assert(!std::is_constructible, std::size_t, int*>::value, "!std::is_constructible, std::size_t, int*>"); static_assert(!std::is_constructible, std::size_t, std::size_t>::value, "!std::is_constructible, std::size_t, std::size_t>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); static_assert(!std::is_constructible, const std::array&>::value, "!std::is_constructible, const std::array&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, double (&)[3]>::value, "!std::is_constructible, double(&)[3]>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert( !std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, Derived (&)[3]>::value, "!std::is_constructible, Derived(&)[3]>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); static_assert(!std::is_constructible, std::vector&>::value, "!std::is_constructible, std::vector&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, Derived (&)[3]>::value, "!std::is_constructible, Derived(&)[3]>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); static_assert(!std::is_constructible, Derived (&)[3]>::value, "!std::is_constructible, Derived(&)[3]>"); static_assert(!std::is_constructible, const Derived (&)[3]>::value, "!std::is_constructible, const Derived(&)[3]>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); static_assert(!std::is_constructible, const std::array&>::value, "!std::is_constructible, const std::array&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert( !std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert( !std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); static_assert(!std::is_constructible, const std::array&>::value, "!std::is_constructible, const std::array&>"); // Explicit construction enabled in P1976R2 static_assert(std::is_constructible, const gsl::span&>::value, "std::is_constructible, const gsl::span&>"); static_assert(std::is_constructible, const gsl::span&>::value, "std::is_constructible, const gsl::span&>"); static_assert(std::is_constructible, const gsl::span&>::value, "std::is_constructible, const gsl::span&>"); // no throw copy constructor static_assert(std::is_nothrow_copy_constructible>::value, "std::is_nothrow_copy_constructible>"); static_assert(std::is_nothrow_copy_constructible>::value, "std::is_nothrow_copy_constructible>"); static_assert(std::is_nothrow_copy_constructible>::value, "std::is_nothrow_copy_constructible>"); static_assert(std::is_nothrow_copy_constructible>::value, "std::is_nothrow_copy_constructible>"); // no throw copy assignment static_assert(std::is_nothrow_copy_assignable>::value, "std::is_nothrow_copy_assignable>"); static_assert(std::is_nothrow_copy_assignable>::value, "std::is_nothrow_copy_assignable>"); static_assert(std::is_nothrow_copy_assignable>::value, "std::is_nothrow_copy_assignable>"); static_assert(std::is_nothrow_copy_assignable>::value, "std::is_nothrow_copy_assignable>"); // no throw destruction static_assert(std::is_nothrow_destructible>::value, "std::is_nothrow_destructible>"); static_assert(std::is_nothrow_destructible>::value, "std::is_nothrow_destructible>"); static_assert(std::is_nothrow_destructible>::value, "std::is_nothrow_destructible>"); // conversions static_assert(std::is_convertible>::value, "std::is_convertible>"); static_assert(std::is_convertible>::value, "std::is_convertible>"); static_assert(std::is_convertible>::value, "std::is_convertible>"); static_assert(std::is_convertible>::value, "std::is_convertible>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); #if __cplusplus >= 201703l template static constexpr bool AsWritableBytesCompilesFor = false; template static constexpr bool AsWritableBytesCompilesFor()))>> = true; static_assert(AsWritableBytesCompilesFor>, "AsWritableBytesCompilesFor>"); static_assert(AsWritableBytesCompilesFor>, "AsWritableBytesCompilesFor>"); static_assert(!AsWritableBytesCompilesFor>, "!AsWritableBytesCompilesFor>"); static_assert(!AsWritableBytesCompilesFor>, "!AsWritableBytesCompilesFor>"); #endif // __cplusplus >= 201703l GSL-4.0.0/tests/span_ext_tests.cpp000066400000000000000000000237421417507532300170700ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for span and span_ext #include // for narrow_cast, at #include // for array #include // for cerr #include // for vector using namespace std; using namespace gsl; #include "deathTestCommon.h" TEST(span_ext_test, make_span_from_pointer_length_constructor) { 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}; { auto s = make_span(&arr[0], 2); EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == &arr[0]); EXPECT_TRUE(s[0] == 1); EXPECT_TRUE(s[1] == 2); } { int* p = nullptr; auto s = make_span(p, narrow_cast::size_type>(0)); EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); } { int* p = nullptr; auto workaround_macro = [=]() { make_span(p, 2); }; EXPECT_DEATH(workaround_macro(), expected); } } TEST(span_ext_test, make_span_from_pointer_pointer_construction) { int arr[4] = {1, 2, 3, 4}; { auto s = make_span(&arr[0], &arr[2]); EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == &arr[0]); EXPECT_TRUE(s[0] == 1); EXPECT_TRUE(s[1] == 2); } { auto s = make_span(&arr[0], &arr[0]); EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == &arr[0]); } { int* p = nullptr; auto s = make_span(p, p); EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); } } TEST(span_ext_test, make_span_from_array_constructor) { int arr[5] = {1, 2, 3, 4, 5}; int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; { const auto s = make_span(arr); EXPECT_TRUE(s.size() == 5); EXPECT_TRUE(s.data() == std::addressof(arr[0])); } { const auto s = make_span(std::addressof(arr2d[0]), 1); EXPECT_TRUE(s.size() == 1); EXPECT_TRUE(s.data() == std::addressof(arr2d[0])); } { const auto s = make_span(std::addressof(arr3d[0]), 1); EXPECT_TRUE(s.size() == 1); EXPECT_TRUE(s.data() == std::addressof(arr3d[0])); } } TEST(span_ext_test, make_span_from_dynamic_array_constructor) { double(*arr)[3][4] = new double[100][3][4]; { auto s = make_span(&arr[0][0][0], 10); EXPECT_TRUE(s.size() == 10); EXPECT_TRUE(s.data() == &arr[0][0][0]); } delete[] arr; } TEST(span_ext_test, make_span_from_std_array_constructor) { std::array arr = {1, 2, 3, 4}; { auto s = make_span(arr); EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590 { gsl::span s1 = make_span(arr); static gsl::span s2; s2 = s1; #if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \ __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__) // Known to be broken in gcc 6.4 and 6.5 with optimizations // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116 EXPECT_TRUE(s1.size() == 4); EXPECT_TRUE(s2.size() == 0); #else EXPECT_TRUE(s1.size() == s2.size()); #endif } } TEST(span_ext_test, make_span_from_const_std_array_constructor) { const std::array arr = {1, 2, 3, 4}; { auto s = make_span(arr); EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } } TEST(span_ext_test, make_span_from_std_array_const_constructor) { std::array arr = {1, 2, 3, 4}; { auto s = make_span(arr); EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } } TEST(span_ext_test, make_span_from_container_constructor) { std::vector v = {1, 2, 3}; const std::vector cv = v; { auto s = make_span(v); EXPECT_TRUE(s.size() == v.size()); EXPECT_TRUE(s.data() == v.data()); auto cs = make_span(cv); EXPECT_TRUE(cs.size() == cv.size()); EXPECT_TRUE(cs.data() == cv.data()); } } TEST(span_test, interop_with_gsl_at) { int arr[5] = {1, 2, 3, 4, 5}; gsl::span s{arr}; EXPECT_TRUE(at(s, 0) == 1); EXPECT_TRUE(at(s, 1) == 2); } TEST(span_ext_test, iterator_free_functions) { int a[] = {1, 2, 3, 4}; gsl::span s{a}; EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE(s.begin() == begin(s)); EXPECT_TRUE(s.end() == end(s)); EXPECT_TRUE(s.rbegin() == rbegin(s)); EXPECT_TRUE(s.rend() == rend(s)); EXPECT_TRUE(s.begin() == cbegin(s)); EXPECT_TRUE(s.end() == cend(s)); EXPECT_TRUE(s.rbegin() == crbegin(s)); EXPECT_TRUE(s.rend() == crend(s)); } TEST(span_ext_test, ssize_free_function) { int a[] = {1, 2, 3, 4}; gsl::span s{a}; EXPECT_FALSE((std::is_same::value)); EXPECT_TRUE(s.size() == static_cast(ssize(s))); } #ifndef GSL_KERNEL_MODE TEST(span_ext_test, comparison_operators) { { gsl::span s1; gsl::span s2; EXPECT_TRUE(s1 == s2); EXPECT_FALSE(s1 != s2); EXPECT_FALSE(s1 < s2); EXPECT_TRUE(s1 <= s2); EXPECT_FALSE(s1 > s2); EXPECT_TRUE(s1 >= s2); EXPECT_TRUE(s2 == s1); EXPECT_FALSE(s2 != s1); EXPECT_FALSE(s2 != s1); EXPECT_TRUE(s2 <= s1); EXPECT_FALSE(s2 > s1); EXPECT_TRUE(s2 >= s1); } { int arr[] = {2, 1}; gsl::span s1 = arr; gsl::span s2 = arr; EXPECT_TRUE(s1 == s2); EXPECT_FALSE(s1 != s2); EXPECT_FALSE(s1 < s2); EXPECT_TRUE(s1 <= s2); EXPECT_FALSE(s1 > s2); EXPECT_TRUE(s1 >= s2); EXPECT_TRUE(s2 == s1); EXPECT_FALSE(s2 != s1); EXPECT_FALSE(s2 < s1); EXPECT_TRUE(s2 <= s1); EXPECT_FALSE(s2 > s1); EXPECT_TRUE(s2 >= s1); } { int arr[] = {2, 1}; // bigger gsl::span s1; gsl::span s2 = arr; EXPECT_TRUE(s1 != s2); EXPECT_TRUE(s2 != s1); EXPECT_FALSE(s1 == s2); EXPECT_FALSE(s2 == s1); EXPECT_TRUE(s1 < s2); EXPECT_FALSE(s2 < s1); EXPECT_TRUE(s1 <= s2); EXPECT_FALSE(s2 <= s1); EXPECT_TRUE(s2 > s1); EXPECT_FALSE(s1 > s2); EXPECT_TRUE(s2 >= s1); EXPECT_FALSE(s1 >= s2); } { int arr1[] = {1, 2}; int arr2[] = {1, 2}; gsl::span s1 = arr1; gsl::span s2 = arr2; EXPECT_TRUE(s1 == s2); EXPECT_FALSE(s1 != s2); EXPECT_FALSE(s1 < s2); EXPECT_TRUE(s1 <= s2); EXPECT_FALSE(s1 > s2); EXPECT_TRUE(s1 >= s2); EXPECT_TRUE(s2 == s1); EXPECT_FALSE(s2 != s1); EXPECT_FALSE(s2 < s1); EXPECT_TRUE(s2 <= s1); EXPECT_FALSE(s2 > s1); EXPECT_TRUE(s2 >= s1); } { int arr[] = {1, 2, 3}; gsl::span s1 = {&arr[0], 2}; // shorter gsl::span s2 = arr; // longer EXPECT_TRUE(s1 != s2); EXPECT_TRUE(s2 != s1); EXPECT_FALSE(s1 == s2); EXPECT_FALSE(s2 == s1); EXPECT_TRUE(s1 < s2); EXPECT_FALSE(s2 < s1); EXPECT_TRUE(s1 <= s2); EXPECT_FALSE(s2 <= s1); EXPECT_TRUE(s2 > s1); EXPECT_FALSE(s1 > s2); EXPECT_TRUE(s2 >= s1); EXPECT_FALSE(s1 >= s2); } { int arr1[] = {1, 2}; // smaller int arr2[] = {2, 1}; // bigger gsl::span s1 = arr1; gsl::span s2 = arr2; EXPECT_TRUE(s1 != s2); EXPECT_TRUE(s2 != s1); EXPECT_FALSE(s1 == s2); EXPECT_FALSE(s2 == s1); EXPECT_TRUE(s1 < s2); EXPECT_FALSE(s2 < s1); EXPECT_TRUE(s1 <= s2); EXPECT_FALSE(s2 <= s1); EXPECT_TRUE(s2 > s1); EXPECT_FALSE(s1 > s2); EXPECT_TRUE(s2 >= s1); EXPECT_FALSE(s1 >= s2); } } #endif // GSL_KERNEL_MODE GSL-4.0.0/tests/span_tests.cpp000066400000000000000000001027431417507532300162070ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for byte #include // for span, span_iterator, operator==, operator!= #include // for narrow_cast, at #include // for array #include // for ptrdiff_t #include // for ptrdiff_t #include // for reverse_iterator, operator-, operator== #include // for unique_ptr, shared_ptr, make_unique, allo... #include // for match_results, sub_match, match_results<>... #include // for string #include // for integral_constant<>::value, is_default_co... #include #include // for vector // the string_view include and macro are used in the deduction guide verification #if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) #ifdef __has_include #if __has_include() #include #define HAS_STRING_VIEW #endif // __has_include() #endif // __has_include #endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) #include "deathTestCommon.h" using namespace gsl; namespace { struct BaseClass { }; struct DerivedClass : BaseClass { }; struct AddressOverloaded { #if (__cplusplus > 201402L) [[maybe_unused]] #endif AddressOverloaded operator&() const { return {}; } }; } // namespace TEST(span_test, constructors) { span s; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); span cs; EXPECT_TRUE(cs.size() == 0); EXPECT_TRUE(cs.data() == nullptr); } TEST(span_test, constructors_with_extent) { span s; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); span cs; EXPECT_TRUE(cs.size() == 0); EXPECT_TRUE(cs.data() == nullptr); } TEST(span_test, constructors_with_bracket_init) { span s{}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); span cs{}; EXPECT_TRUE(cs.size() == 0); EXPECT_TRUE(cs.data() == nullptr); } TEST(span_test, size_optimization) { span s; EXPECT_TRUE(sizeof(s) == sizeof(int*) + sizeof(ptrdiff_t)); span se; EXPECT_TRUE(sizeof(se) == sizeof(int*)); } TEST(span_test, from_nullptr_size_constructor) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. from_nullptr_size_constructor"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); { span s{nullptr, narrow_cast::size_type>(0)}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); span cs{nullptr, narrow_cast::size_type>(0)}; EXPECT_TRUE(cs.size() == 0); EXPECT_TRUE(cs.data() == nullptr); } { auto workaround_macro = []() { const span s{nullptr, narrow_cast::size_type>(0)}; }; EXPECT_DEATH(workaround_macro(), expected); } { auto workaround_macro = []() { const span s{nullptr, 1}; }; EXPECT_DEATH(workaround_macro(), expected); auto const_workaround_macro = []() { const span s{nullptr, 1}; }; EXPECT_DEATH(const_workaround_macro(), expected); } { auto workaround_macro = []() { const span s{nullptr, 1}; }; EXPECT_DEATH(workaround_macro(), expected); auto const_workaround_macro = []() { const span s{nullptr, 1}; }; EXPECT_DEATH(const_workaround_macro(), expected); } { span s{nullptr, narrow_cast::size_type>(0)}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); span cs{nullptr, narrow_cast::size_type>(0)}; EXPECT_TRUE(cs.size() == 0); EXPECT_TRUE(cs.data() == nullptr); } } TEST(span_test, from_pointer_length_constructor) { 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}; { for (int i = 0; i < 4; ++i) { { span s = {&arr[0], narrow_cast(i)}; EXPECT_TRUE(s.size() == narrow_cast(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(j)]); } { span s = {&arr[i], 4 - narrow_cast(i)}; EXPECT_TRUE(s.size() == 4 - narrow_cast(i)); EXPECT_TRUE(s.data() == &arr[i]); EXPECT_TRUE(s.empty() == ((4 - i) == 0)); for (int j = 0; j < 4 - i; ++j) EXPECT_TRUE(arr[j + i] == s[narrow_cast(j)]); } } } { span s{&arr[0], 2}; EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == &arr[0]); EXPECT_TRUE(s[0] == 1); EXPECT_TRUE(s[1] == 2); } { int* p = nullptr; span s{p, narrow_cast::size_type>(0)}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); } { int* p = nullptr; auto workaround_macro = [=]() { const span s{p, 2}; }; EXPECT_DEATH(workaround_macro(), expected); } } TEST(span_test, from_pointer_pointer_construction) { int arr[4] = {1, 2, 3, 4}; { span s{&arr[0], &arr[2]}; EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == &arr[0]); EXPECT_TRUE(s[0] == 1); EXPECT_TRUE(s[1] == 2); } { span s{&arr[0], &arr[2]}; EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == &arr[0]); EXPECT_TRUE(s[0] == 1); EXPECT_TRUE(s[1] == 2); } { span s{&arr[0], &arr[0]}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == &arr[0]); } { span s{&arr[0], &arr[0]}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == &arr[0]); } // this will fail the std::distance() precondition, which asserts on MSVC debug builds //{ // auto workaround_macro = [&]() { span s{&arr[1], &arr[0]}; }; // 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 s{&arr[0], p}; }; // EXPECT_DEATH(workaround_macro(), expected); //} { int* p = nullptr; span s{p, p}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); } { int* p = nullptr; span s{p, p}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); } // this will fail the std::distance() precondition, which asserts on MSVC debug builds //{ // int* p = nullptr; // auto workaround_macro = [&]() { span s{&arr[0], p}; }; // EXPECT_DEATH(workaround_macro(), expected); //} } TEST(span_test, from_array_constructor) { int arr[5] = {1, 2, 3, 4, 5}; { const span s{arr}; EXPECT_TRUE(s.size() == 5); EXPECT_TRUE(s.data() == &arr[0]); } { const span s{arr}; EXPECT_TRUE(s.size() == 5); EXPECT_TRUE(s.data() == &arr[0]); } int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; #ifdef CONFIRM_COMPILATION_ERRORS { span s{arr}; } { span s{arr}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == &arr[0]); } { span s{arr2d}; EXPECT_TRUE(s.size() == 6); EXPECT_TRUE(s.data() == &arr2d[0][0]); EXPECT_TRUE(s[0] == 1); EXPECT_TRUE(s[5] == 6); } { span s{arr2d}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == &arr2d[0][0]); } { span s{arr2d}; } #endif { const span s{std::addressof(arr2d[0]), 1}; EXPECT_TRUE(s.size() == 1); EXPECT_TRUE(s.data() == std::addressof(arr2d[0])); } int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; #ifdef CONFIRM_COMPILATION_ERRORS { span s{arr3d}; EXPECT_TRUE(s.size() == 12); EXPECT_TRUE(s.data() == &arr3d[0][0][0]); EXPECT_TRUE(s[0] == 1); EXPECT_TRUE(s[11] == 12); } { span s{arr3d}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == &arr3d[0][0][0]); } { span s{arr3d}; } { span s{arr3d}; EXPECT_TRUE(s.size() == 12); EXPECT_TRUE(s.data() == &arr3d[0][0][0]); EXPECT_TRUE(s[0] == 1); EXPECT_TRUE(s[5] == 6); } #endif { const span s{std::addressof(arr3d[0]), 1}; EXPECT_TRUE(s.size() == 1); } AddressOverloaded ao_arr[5] = {}; { const span s{ao_arr}; EXPECT_TRUE(s.size() == 5); EXPECT_TRUE(s.data() == std::addressof(ao_arr[0])); } } TEST(span_test, from_dynamic_array_constructor) { double(*arr)[3][4] = new double[100][3][4]; { span s(&arr[0][0][0], 10); EXPECT_TRUE(s.size() == 10); EXPECT_TRUE(s.data() == &arr[0][0][0]); } delete[] arr; } TEST(span_test, from_std_array_constructor) { std::array arr = {1, 2, 3, 4}; { span s{arr}; EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); span cs{arr}; EXPECT_TRUE(cs.size() == arr.size()); EXPECT_TRUE(cs.data() == arr.data()); } { span s{arr}; EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); span cs{arr}; EXPECT_TRUE(cs.size() == arr.size()); EXPECT_TRUE(cs.data() == arr.data()); } { std::array empty_arr{}; span s{empty_arr}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.empty()); } std::array ao_arr{}; { span fs{ao_arr}; EXPECT_TRUE(fs.size() == ao_arr.size()); EXPECT_TRUE(ao_arr.data() == fs.data()); } #ifdef CONFIRM_COMPILATION_ERRORS { span s{arr}; EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == arr.data()); span cs{arr}; EXPECT_TRUE(cs.size() == 2); EXPECT_TRUE(cs.data() == arr.data()); } { span s{arr}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == arr.data()); span cs{arr}; EXPECT_TRUE(cs.size() == 0); EXPECT_TRUE(cs.data() == arr.data()); } { span s{arr}; } { auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; auto take_a_span = [](span s) { static_cast(s); }; // try to take a temporary std::array take_a_span(get_an_array()); } #endif { auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; auto take_a_span = [](span s) { static_cast(s); }; // try to take a temporary std::array take_a_span(get_an_array()); } } TEST(span_test, from_const_std_array_constructor) { const std::array arr = {1, 2, 3, 4}; { span s{arr}; EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } { span s{arr}; EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } const std::array ao_arr{}; { span s{ao_arr}; EXPECT_TRUE(s.size() == ao_arr.size()); EXPECT_TRUE(s.data() == ao_arr.data()); } #ifdef CONFIRM_COMPILATION_ERRORS { span s{arr}; EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == arr.data()); } { span s{arr}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == arr.data()); } { span s{arr}; } #endif { auto get_an_array = []() -> const std::array { return {1, 2, 3, 4}; }; auto take_a_span = [](span s) { static_cast(s); }; // try to take a temporary std::array take_a_span(get_an_array()); } } TEST(span_test, from_std_array_const_constructor) { std::array arr = {1, 2, 3, 4}; { span s{arr}; EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } { span s{arr}; EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } #ifdef CONFIRM_COMPILATION_ERRORS { span s{arr}; EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == arr.data()); } { span s{arr}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == arr.data()); } { span s{arr}; } { span s{arr}; } #endif } TEST(span_test, from_container_constructor) { std::vector v = {1, 2, 3}; const std::vector cv = v; { span s{v}; EXPECT_TRUE(s.size() == v.size()); EXPECT_TRUE(s.data() == v.data()); span cs{v}; EXPECT_TRUE(cs.size() == v.size()); EXPECT_TRUE(cs.data() == v.data()); } std::string str = "hello"; const std::string cstr = "hello"; { #ifdef CONFIRM_COMPILATION_ERRORS span s{str}; EXPECT_TRUE(s.size() == str.size()); EXPECT_TRUE(s.data() == str.data())); #endif span cs{str}; EXPECT_TRUE(cs.size() == str.size()); EXPECT_TRUE(cs.data() == str.data()); } { #ifdef CONFIRM_COMPILATION_ERRORS span s{cstr}; #endif span cs{cstr}; EXPECT_TRUE(cs.size() == cstr.size()); EXPECT_TRUE(cs.data() == cstr.data()); } { #ifdef CONFIRM_COMPILATION_ERRORS auto get_temp_vector = []() -> std::vector { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_vector()); #endif } { auto get_temp_vector = []() -> std::vector { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_vector()); } { #ifdef CONFIRM_COMPILATION_ERRORS auto get_temp_string = []() -> std::string { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_string()); #endif } { auto get_temp_string = []() -> std::string { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_string()); } { #ifdef CONFIRM_COMPILATION_ERRORS auto get_temp_vector = []() -> const std::vector { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_vector()); #endif } { auto get_temp_string = []() -> const std::string { return {}; }; auto use_span = [](span s) { static_cast(s); }; use_span(get_temp_string()); } { #ifdef CONFIRM_COMPILATION_ERRORS std::map m; span s{m}; #endif } } TEST(span_test, from_convertible_span_constructor){{span avd; span avcd = avd; static_cast(avcd); } { #ifdef CONFIRM_COMPILATION_ERRORS span avd; span avb = avd; static_cast(avb); #endif } #ifdef CONFIRM_COMPILATION_ERRORS { span s; span s2 = s; static_cast(s2); } { span s; span s2 = s; static_cast(s2); } { span s; span s2 = s; static_cast(s2); } #endif } TEST(span_test, copy_move_and_assignment) { span s1; EXPECT_TRUE(s1.empty()); int arr[] = {3, 4, 5}; span s2 = arr; EXPECT_TRUE(s2.size() == 3); EXPECT_TRUE(s2.data() == &arr[0]); s2 = s1; EXPECT_TRUE(s2.empty()); auto get_temp_span = [&]() -> span { return {&arr[1], 2}; }; auto use_span = [&](span s) { EXPECT_TRUE(s.size() == 2); EXPECT_TRUE(s.data() == &arr[1]); }; use_span(get_temp_span()); s1 = get_temp_span(); EXPECT_TRUE(s1.size() == 2); EXPECT_TRUE(s1.data() == &arr[1]); } TEST(span_test, first) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. first"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); int arr[5] = {1, 2, 3, 4, 5}; { span av = arr; EXPECT_TRUE(av.first<2>().size() == 2); EXPECT_TRUE(av.first(2).size() == 2); } { span av = arr; EXPECT_TRUE(av.first<0>().size() == 0); EXPECT_TRUE(av.first(0).size() == 0); } { span av = arr; EXPECT_TRUE(av.first<5>().size() == 5); EXPECT_TRUE(av.first(5).size() == 5); } { span av = arr; #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(av.first<6>().size() == 6); EXPECT_TRUE(av.first<-1>().size() == -1); #endif EXPECT_DEATH(av.first(6).size(), expected); } { span av; EXPECT_TRUE(av.first<0>().size() == 0); EXPECT_TRUE(av.first(0).size() == 0); } } 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}; { span av = arr; EXPECT_TRUE(av.last<2>().size() == 2); EXPECT_TRUE(av.last(2).size() == 2); } { span av = arr; EXPECT_TRUE(av.last<0>().size() == 0); EXPECT_TRUE(av.last(0).size() == 0); } { span av = arr; EXPECT_TRUE(av.last<5>().size() == 5); EXPECT_TRUE(av.last(5).size() == 5); } { span av = arr; #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(av.last<6>().size() == 6); #endif EXPECT_DEATH(av.last(6).size(), expected); } { span av; EXPECT_TRUE(av.last<0>().size() == 0); EXPECT_TRUE(av.last(0).size() == 0); } } TEST(span_test, subspan) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. subspan"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); int arr[5] = {1, 2, 3, 4, 5}; { span av = arr; EXPECT_TRUE((av.subspan<2, 2>().size()) == 2); EXPECT_TRUE(decltype(av.subspan<2, 2>())::extent == 2); EXPECT_TRUE(av.subspan(2, 2).size() == 2); EXPECT_TRUE(av.subspan(2, 3).size() == 3); } { span av = arr; EXPECT_TRUE((av.subspan<0, 0>().size()) == 0); EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0); EXPECT_TRUE(av.subspan(0, 0).size() == 0); } { span av = arr; EXPECT_TRUE((av.subspan<0, 5>().size()) == 5); EXPECT_TRUE(decltype(av.subspan<0, 5>())::extent == 5); EXPECT_TRUE(av.subspan(0, 5).size() == 5); EXPECT_DEATH(av.subspan(0, 6).size(), expected); EXPECT_DEATH(av.subspan(1, 5).size(), expected); } { span av = arr; EXPECT_TRUE((av.subspan<4, 0>().size()) == 0); EXPECT_TRUE(decltype(av.subspan<4, 0>())::extent == 0); EXPECT_TRUE(av.subspan(4, 0).size() == 0); EXPECT_TRUE(av.subspan(5, 0).size() == 0); EXPECT_DEATH(av.subspan(6, 0).size(), expected); } { span av = arr; EXPECT_TRUE(av.subspan<1>().size() == 4); EXPECT_TRUE(decltype(av.subspan<1>())::extent == 4); } { span av; EXPECT_TRUE((av.subspan<0, 0>().size()) == 0); EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0); EXPECT_TRUE(av.subspan(0, 0).size() == 0); EXPECT_DEATH((av.subspan<1, 0>().size()), expected); } { span av; EXPECT_TRUE(av.subspan(0).size() == 0); EXPECT_DEATH(av.subspan(1).size(), expected); } { span av = arr; EXPECT_TRUE(av.subspan(0).size() == 5); EXPECT_TRUE(av.subspan(1).size() == 4); EXPECT_TRUE(av.subspan(4).size() == 1); EXPECT_TRUE(av.subspan(5).size() == 0); EXPECT_DEATH(av.subspan(6).size(), expected); const auto av2 = av.subspan(1); for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast(i) + 2); } { span av = arr; EXPECT_TRUE(av.subspan(0).size() == 5); EXPECT_TRUE(av.subspan(1).size() == 4); EXPECT_TRUE(av.subspan(4).size() == 1); EXPECT_TRUE(av.subspan(5).size() == 0); EXPECT_DEATH(av.subspan(6).size(), expected); const auto av2 = av.subspan(1); for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast(i) + 2); } } TEST(span_test, iterator_default_init) { span::iterator it1; span::iterator it2; EXPECT_TRUE(it1 == it2); } TEST(span_test, iterator_comparisons) { int a[] = {1, 2, 3, 4}; { span s = a; span::iterator it = s.begin(); auto it2 = it + 1; EXPECT_TRUE(it == it); EXPECT_TRUE(it == s.begin()); EXPECT_TRUE(s.begin() == it); EXPECT_TRUE(it != it2); EXPECT_TRUE(it2 != it); EXPECT_TRUE(it != s.end()); EXPECT_TRUE(it2 != s.end()); EXPECT_TRUE(s.end() != it); EXPECT_TRUE(it < it2); EXPECT_TRUE(it <= it2); EXPECT_TRUE(it2 <= s.end()); EXPECT_TRUE(it < s.end()); EXPECT_TRUE(it2 > it); EXPECT_TRUE(it2 >= it); EXPECT_TRUE(s.end() > it2); EXPECT_TRUE(s.end() >= it2); } } TEST(span_test, incomparable_iterators) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. incomparable_iterators"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); int a[] = {1, 2, 3, 4}; int b[] = {1, 2, 3, 4}; { span s = a; span s2 = b; #if (__cplusplus > 201402L) 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()), expected); EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), expected); #endif } } 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 s = a; span::iterator it = s.begin(); span::iterator it2 = std::begin(s); EXPECT_TRUE(it == it2); it = s.end(); it2 = std::end(s); EXPECT_TRUE(it == it2); } { int a[] = {1, 2, 3, 4}; span s = a; auto it = s.begin(); auto first = it; EXPECT_TRUE(it == first); EXPECT_TRUE(*it == 1); auto beyond = s.end(); EXPECT_TRUE(it != beyond); EXPECT_DEATH(*beyond, expected); EXPECT_TRUE(beyond - first == 4); EXPECT_TRUE(first - first == 0); EXPECT_TRUE(beyond - beyond == 0); ++it; EXPECT_TRUE(it - first == 1); EXPECT_TRUE(*it == 2); *it = 22; EXPECT_TRUE(*it == 22); EXPECT_TRUE(beyond - it == 3); it = first; EXPECT_TRUE(it == first); while (it != s.end()) { *it = 5; ++it; } EXPECT_TRUE(it == beyond); EXPECT_TRUE(it - beyond == 0); for (const auto& n : s) { EXPECT_TRUE(n == 5); } } } TEST(span_test, rbegin_rend) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. rbegin_rend"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); { int a[] = {1, 2, 3, 4}; span s = a; auto it = s.rbegin(); auto first = it; EXPECT_TRUE(it == first); EXPECT_TRUE(*it == 4); auto beyond = s.rend(); EXPECT_TRUE(it != beyond); #if (__cplusplus > 201402L) EXPECT_DEATH([[maybe_unused]] auto _ = *beyond, expected); #else EXPECT_DEATH(auto _ = *beyond, expected); #endif EXPECT_TRUE(beyond - first == 4); EXPECT_TRUE(first - first == 0); EXPECT_TRUE(beyond - beyond == 0); ++it; EXPECT_TRUE(it - s.rbegin() == 1); EXPECT_TRUE(*it == 3); *it = 22; EXPECT_TRUE(*it == 22); EXPECT_TRUE(beyond - it == 3); it = first; EXPECT_TRUE(it == first); while (it != s.rend()) { *it = 5; ++it; } EXPECT_TRUE(it == beyond); EXPECT_TRUE(it - beyond == 0); for (const auto& n : s) { EXPECT_TRUE(n == 5); } } } 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}; { const span s = a; EXPECT_TRUE(s.size() == 4); const span bs = as_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } { span s; const auto bs = as_bytes(s); EXPECT_TRUE(bs.size() == s.size()); EXPECT_TRUE(bs.size() == 0); EXPECT_TRUE(bs.size_bytes() == 0); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.data() == nullptr); } { span s = a; const auto bs = as_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } int b[5] = {1, 2, 3, 4, 5}; { span sp(std::begin(b), static_cast(-2)); EXPECT_DEATH((void) sp.size_bytes(), expected); } } TEST(span_test, as_writable_bytes) { int a[] = {1, 2, 3, 4}; { #ifdef CONFIRM_COMPILATION_ERRORS // you should not be able to get writeable bytes for const objects span s = a; EXPECT_TRUE(s.size() == 4); span bs = as_writable_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); #endif } { span s; const auto bs = as_writable_bytes(s); EXPECT_TRUE(bs.size() == s.size()); EXPECT_TRUE(bs.size() == 0); EXPECT_TRUE(bs.size_bytes() == 0); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.data() == nullptr); } { span s = a; const auto bs = as_writable_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } } 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 span s4 = arr; EXPECT_TRUE(s4.size() == 4); // converting to dynamic_range is always ok { span s = s4; EXPECT_TRUE(s.size() == s4.size()); static_cast(s); } // initialization or assignment to static span that REDUCES size is NOT ok #ifdef CONFIRM_COMPILATION_ERRORS { span s = arr; } { span s2 = s4; static_cast(s2); } #endif // even when done dynamically { /* // this now results in a compile-time error, rather than runtime. // There is no suitable conversion from dynamic span to fixed span. span s = arr; auto f = [&]() { const span s2 = s; static_cast(s2); }; EXPECT_DEATH(f(), expected); */ } // but doing so explicitly is ok // you can convert statically { const span s2{&arr[0], 2}; static_cast(s2); } { const span s1 = s4.first<1>(); static_cast(s1); } /* // this is not a legal operation in std::span, so we are no longer supporting it // conversion from span to span via call to `first` // then convert from span to span // The dynamic to fixed extents are not supported in the standard // to make this work, span would need to be span. { // NB: implicit conversion to span from span span s1 = s4.first(1); static_cast(s1); } */ // initialization or assignment to static span that requires size INCREASE is not ok. int arr2[2] = {1, 2}; #ifdef CONFIRM_COMPILATION_ERRORS { span s3 = arr2; } { span s2 = arr2; span s4a = s2; } #endif { auto f = [&]() { const span _s4{arr2, 2}; static_cast(_s4); }; EXPECT_DEATH(f(), expected); } /* // 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 av = arr2; auto f = [&]() { const span _s4 = av; static_cast(_s4); }; EXPECT_DEATH(f(), expected); */ } TEST(span_test, interop_with_std_regex) { char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'}; span s = lat; const auto f_it = s.begin() + 7; std::match_results::iterator> match; std::regex_match(s.begin(), s.end(), match, std::regex(".*")); EXPECT_TRUE(match.ready()); EXPECT_FALSE(match.empty()); EXPECT_TRUE(match[0].matched); EXPECT_TRUE(match[0].first == s.begin()); EXPECT_TRUE(match[0].second == s.end()); std::regex_search(s.begin(), s.end(), match, std::regex("F")); EXPECT_TRUE(match.ready()); EXPECT_FALSE(match.empty()); EXPECT_TRUE(match[0].matched); EXPECT_TRUE(match[0].first == f_it); EXPECT_TRUE(match[0].second == (f_it + 1)); } TEST(span_test, default_constructible) { EXPECT_TRUE((std::is_default_constructible>::value)); EXPECT_TRUE((std::is_default_constructible>::value)); EXPECT_FALSE((std::is_default_constructible>::value)); } TEST(span_test, std_container_ctad) { #if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) // this test is just to verify that these compile { std::vector v{1, 2, 3, 4}; gsl::span sp{v}; static_assert(std::is_same>::value); } { std::string str{"foo"}; gsl::span sp{str}; static_assert(std::is_same>::value); } #ifdef HAS_STRING_VIEW { std::string_view sv{"foo"}; gsl::span sp{sv}; static_assert(std::is_same>::value); } #endif #endif } TEST(span_test, front_back) { int arr[5] = {1, 2, 3, 4, 5}; span s{arr}; EXPECT_TRUE(s.front() == 1); EXPECT_TRUE(s.back() == 5); const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. front_back"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); span s2; EXPECT_DEATH(s2.front(), expected); EXPECT_DEATH(s2.back(), expected); } GSL-4.0.0/tests/strict_notnull_tests.cpp000066400000000000000000000116461417507532300203320ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include // for not_null, operator<, operator<=, operator> #include #include "deathTestCommon.h" using namespace gsl; namespace { // clang-format off GSL_SUPPRESS(f.4) // NO-FORMAT: attribute // clang-format on bool helper(not_null p) { return *p == 12; } // clang-format off GSL_SUPPRESS(f.4) // NO-FORMAT: attribute // clang-format on bool helper_const(not_null p) { return *p == 12; } // clang-format off GSL_SUPPRESS(f.4) // NO-FORMAT: attribute // clang-format on bool strict_helper(strict_not_null p) { return *p == 12; } // clang-format off GSL_SUPPRESS(f.4) // NO-FORMAT: attribute // clang-format on bool strict_helper_const(strict_not_null 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) { { // raw ptr <-> strict_not_null int x = 42; #ifdef CONFIRM_COMPILATION_ERRORS strict_not_null snn = &x; strict_helper(&x); strict_helper_const(&x); strict_helper(return_pointer()); strict_helper_const(return_pointer_const()); #endif const strict_not_null snn1{&x}; helper(snn1); helper_const(snn1); EXPECT_TRUE(*snn1 == 42); } { // strict_not_null -> strict_not_null int x = 42; strict_not_null snn1{&x}; const strict_not_null snn2{&x}; strict_helper(snn1); strict_helper_const(snn1); strict_helper_const(snn2); EXPECT_TRUE(snn1 == snn2); } { // strict_not_null -> not_null int x = 42; strict_not_null snn{&x}; const not_null nn1 = snn; const not_null nn2{snn}; helper(snn); helper_const(snn); EXPECT_TRUE(snn == nn1); EXPECT_TRUE(snn == nn2); } { // not_null -> strict_not_null int x = 42; not_null nn{&x}; const strict_not_null snn1{nn}; const strict_not_null snn2{nn}; strict_helper(nn); strict_helper_const(nn); EXPECT_TRUE(snn1 == nn); EXPECT_TRUE(snn2 == nn); std::hash> hash_snn; std::hash> hash_nn; EXPECT_TRUE(hash_nn(snn1) == hash_nn(nn)); EXPECT_TRUE(hash_snn(snn1) == hash_nn(nn)); EXPECT_TRUE(hash_nn(snn1) == hash_nn(snn2)); EXPECT_TRUE(hash_snn(snn1) == hash_snn(nn)); } #ifdef CONFIRM_COMPILATION_ERRORS { strict_not_null p{nullptr}; } #endif } #if defined(__cplusplus) && (__cplusplus >= 201703L) TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. TestStrictNotNullConstructorTypeDeduction"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); { int i = 42; strict_not_null x{&i}; helper(strict_not_null{&i}); helper_const(strict_not_null{&i}); EXPECT_TRUE(*x == 42); } { int i = 42; int* p = &i; strict_not_null x{p}; helper(strict_not_null{p}); helper_const(strict_not_null{p}); EXPECT_TRUE(*x == 42); } { auto workaround_macro = []() { int* p1 = nullptr; const strict_not_null x{p1}; }; EXPECT_DEATH(workaround_macro(), expected); } { auto workaround_macro = []() { const int* p1 = nullptr; const strict_not_null x{p1}; }; EXPECT_DEATH(workaround_macro(), expected); } { int* p = nullptr; EXPECT_DEATH(helper(strict_not_null{p}), expected); EXPECT_DEATH(helper_const(strict_not_null{p}), expected); } #ifdef CONFIRM_COMPILATION_ERRORS { strict_not_null x{nullptr}; helper(strict_not_null{nullptr}); helper_const(strict_not_null{nullptr}); } #endif } #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) GSL-4.0.0/tests/string_span_tests.cpp000066400000000000000000000767241417507532300176060ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for Expects, fail_fast (ptr only) #include // for owner #include // for span, dynamic_extent #include // for basic_string_span, operator==, ensure_z #include // for move, find #include // for size_t #include // for map #include // for basic_string, string, char_traits, operat... #include // for remove_reference<>::type #include // for vector, allocator #include "deathTestCommon.h" using namespace gsl; // Generic string functions namespace generic { template auto strlen(const CharT* s) { auto p = s; while (*p) ++p; return p - s; } template auto strnlen(const CharT* s, std::size_t n) { return std::find(s, s + n, CharT{0}) - s; } } // namespace generic namespace { template T move_wrapper(T&& t) { return std::move(t); } // not used otherwise #ifdef CONFIRM_COMPILATION_ERRORS template T create() { return T{}; } template void use(basic_string_span) {} #endif czstring_span<> CreateTempName(string_span<> span) { Expects(span.size() > 1); std::size_t last = 0; if (span.size() > 4) { span[0] = 't'; span[1] = 'm'; span[2] = 'p'; last = 3; } span[last] = '\0'; auto ret = span.subspan(0, 4); return {ret}; } cwzstring_span<> CreateTempNameW(wstring_span<> span) { Expects(span.size() > 1); std::size_t last = 0; if (span.size() > 4) { span[0] = L't'; span[1] = L'm'; span[2] = L'p'; last = 3; } span[last] = L'\0'; auto ret = span.subspan(0, 4); return {ret}; } cu16zstring_span<> CreateTempNameU16(u16string_span<> span) { Expects(span.size() > 1); std::size_t last = 0; if (span.size() > 4) { span[0] = u't'; span[1] = u'm'; span[2] = u'p'; last = 3; } span[last] = u'\0'; auto ret = span.subspan(0, 4); return {ret}; } cu32zstring_span<> CreateTempNameU32(u32string_span<> span) { Expects(span.size() > 1); std::size_t last = 0; if (span.size() > 4) { span[0] = U't'; span[1] = U'm'; span[2] = U'p'; last = 3; } span[last] = U'\0'; auto ret = span.subspan(0, 4); return {ret}; } } // namespace TEST(string_span_tests, TestLiteralConstruction) { cwstring_span<> v = ensure_z(L"Hello"); EXPECT_TRUE(5 == v.length()); #ifdef CONFIRM_COMPILATION_ERRORS wstring_span<> v2 = ensure0(L"Hello"); #endif } TEST(string_span_tests, TestConstructFromStdString) { std::string s = "Hello there world"; cstring_span<> v = s; EXPECT_TRUE(v.length() == static_cast::size_type>(s.length())); } TEST(string_span_tests, TestConstructFromStdVector) { std::vector vec(5, 'h'); string_span<> v{vec}; EXPECT_TRUE(v.length() == static_cast::size_type>(vec.size())); } TEST(string_span_tests, TestStackArrayConstruction) { wchar_t stack_string[] = L"Hello"; { cwstring_span<> v = ensure_z(stack_string); EXPECT_TRUE(v.length() == 5); } { cwstring_span<> v = stack_string; EXPECT_TRUE(v.length() == 5); } { wstring_span<> v = ensure_z(stack_string); EXPECT_TRUE(v.length() == 5); } { wstring_span<> v = stack_string; EXPECT_TRUE(v.length() == 5); } } TEST(string_span_tests, TestConstructFromConstCharPointer) { const char* s = "Hello"; cstring_span<> v = ensure_z(s); EXPECT_TRUE(v.length() == 5); } TEST(string_span_tests, TestConversionToConst) { char stack_string[] = "Hello"; string_span<> v = ensure_z(stack_string); cstring_span<> v2 = v; EXPECT_TRUE(v.length() == v2.length()); } TEST(string_span_tests, TestConversionFromConst) { char stack_string[] = "Hello"; cstring_span<> v = ensure_z(stack_string); (void) v; #ifdef CONFIRM_COMPILATION_ERRORS string_span<> v2 = v; string_span<> v3 = "Hello"; #endif } TEST(string_span_tests, TestToString) { auto s = gsl::to_string(cstring_span<>{}); EXPECT_TRUE(s.length() == static_cast(0)); char stack_string[] = "Hello"; cstring_span<> v = ensure_z(stack_string); auto s2 = gsl::to_string(v); EXPECT_TRUE(static_cast::size_type>(s2.length()) == v.length()); EXPECT_TRUE(s2.length() == static_cast(5)); } TEST(string_span_tests, TestToBasicString) { auto s = gsl::to_basic_string, ::std::allocator>( cstring_span<>{}); EXPECT_TRUE(s.length() == static_cast(0)); char stack_string[] = "Hello"; cstring_span<> v = ensure_z(stack_string); auto s2 = gsl::to_basic_string, ::std::allocator>(v); EXPECT_TRUE(static_cast::size_type>(s2.length()) == v.length()); EXPECT_TRUE(s2.length() == static_cast(5)); } TEST(string_span_tests, EqualityAndImplicitConstructors) { { cstring_span<> span = "Hello"; cstring_span<> span1; // comparison to empty span EXPECT_TRUE(span1 != span); EXPECT_TRUE(span != span1); } { cstring_span<> span = "Hello"; cstring_span<> span1 = "Hello1"; // comparison to different span EXPECT_TRUE(span1 != span); EXPECT_TRUE(span != span1); } { cstring_span<> span = "Hello"; const char ar[] = {'H', 'e', 'l', 'l', 'o'}; const char ar1[] = "Hello"; const char ar2[10] = "Hello"; const char* ptr = "Hello"; const std::string str = "Hello"; const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; gsl::span sp = ensure_z("Hello"); // comparison to literal EXPECT_TRUE(span == cstring_span<>("Hello")); // comparison to static array with no null termination EXPECT_TRUE(span == cstring_span<>(ar)); // comparison to static array with null at the end EXPECT_TRUE(span == cstring_span<>(ar1)); // comparison to static array with null in the middle EXPECT_TRUE(span == cstring_span<>(ar2)); // comparison to null-terminated c string EXPECT_TRUE(span == cstring_span<>(ptr, 5)); // comparison to string EXPECT_TRUE(span == cstring_span<>(str)); // comparison to vector of charaters with no null termination EXPECT_TRUE(span == cstring_span<>(vec)); // comparison to span EXPECT_TRUE(span == cstring_span<>(sp)); // comparison to string_span EXPECT_TRUE(span == span); } { char ar[] = {'H', 'e', 'l', 'l', 'o'}; string_span<> span = ar; char ar1[] = "Hello"; char ar2[10] = "Hello"; char* ptr = ar; std::string str = "Hello"; std::vector vec = {'H', 'e', 'l', 'l', 'o'}; gsl::span sp = ensure_z(ar1); // comparison to static array with no null termination EXPECT_TRUE(span == string_span<>(ar)); // comparison to static array with null at the end EXPECT_TRUE(span == string_span<>(ar1)); // comparison to static array with null in the middle EXPECT_TRUE(span == string_span<>(ar2)); // comparison to null-terminated c string EXPECT_TRUE(span == string_span<>(ptr, 5)); // comparison to string EXPECT_TRUE(span == string_span<>(str)); // comparison to vector of charaters with no null termination EXPECT_TRUE(span == string_span<>(vec)); // comparison to span EXPECT_TRUE(span == string_span<>(sp)); // comparison to string_span EXPECT_TRUE(span == span); } { const char ar[] = {'H', 'e', 'l', 'l', 'o'}; const char ar1[] = "Hello"; const char ar2[10] = "Hello"; const std::string str = "Hello"; const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const gsl::span sp = ensure_z("Hello"); cstring_span<> span = "Hello"; // const span, const other type EXPECT_TRUE(span == "Hello"); EXPECT_TRUE(span == ar); EXPECT_TRUE(span == ar1); EXPECT_TRUE(span == ar2); #ifdef CONFIRM_COMPILATION_ERRORS const char* ptr = "Hello"; EXPECT_TRUE(span == ptr); #endif EXPECT_TRUE(span == str); EXPECT_TRUE(span == vec); EXPECT_TRUE(span == sp); EXPECT_TRUE("Hello" == span); EXPECT_TRUE(ar == span); EXPECT_TRUE(ar1 == span); EXPECT_TRUE(ar2 == span); #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(ptr == span); #endif EXPECT_TRUE(str == span); EXPECT_TRUE(vec == span); EXPECT_TRUE(sp == span); // const span, non-const other type char _ar[] = {'H', 'e', 'l', 'l', 'o'}; char _ar1[] = "Hello"; char _ar2[10] = "Hello"; char* _ptr = _ar; std::string _str = "Hello"; std::vector _vec = {'H', 'e', 'l', 'l', 'o'}; gsl::span _sp{_ar, 5}; EXPECT_TRUE(span == _ar); EXPECT_TRUE(span == _ar1); EXPECT_TRUE(span == _ar2); #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(span == _ptr); #endif EXPECT_TRUE(span == _str); EXPECT_TRUE(span == _vec); EXPECT_TRUE(span == _sp); EXPECT_TRUE(_ar == span); EXPECT_TRUE(_ar1 == span); EXPECT_TRUE(_ar2 == span); #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(_ptr == span); #endif EXPECT_TRUE(_str == span); EXPECT_TRUE(_vec == span); EXPECT_TRUE(_sp == span); string_span<> _span{_ptr, 5}; // non-const span, non-const other type EXPECT_TRUE(_span == _ar); EXPECT_TRUE(_span == _ar1); EXPECT_TRUE(_span == _ar2); #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(_span == _ptr); #endif EXPECT_TRUE(_span == _str); EXPECT_TRUE(_span == _vec); EXPECT_TRUE(_span == _sp); EXPECT_TRUE(_ar == _span); EXPECT_TRUE(_ar1 == _span); EXPECT_TRUE(_ar2 == _span); #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(_ptr == _span); #endif EXPECT_TRUE(_str == _span); EXPECT_TRUE(_vec == _span); EXPECT_TRUE(_sp == _span); // non-const span, const other type EXPECT_TRUE(_span == "Hello"); EXPECT_TRUE(_span == ar); EXPECT_TRUE(_span == ar1); EXPECT_TRUE(_span == ar2); #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(_span == ptr); #endif EXPECT_TRUE(_span == str); EXPECT_TRUE(_span == vec); EXPECT_TRUE(_span == sp); EXPECT_TRUE("Hello" == _span); EXPECT_TRUE(ar == _span); EXPECT_TRUE(ar1 == _span); EXPECT_TRUE(ar2 == _span); #ifdef CONFIRM_COMPILATION_ERRORS EXPECT_TRUE(ptr == _span); #endif EXPECT_TRUE(str == _span); EXPECT_TRUE(vec == _span); EXPECT_TRUE(sp == _span); // two spans EXPECT_TRUE(_span == span); EXPECT_TRUE(span == _span); } { std::vector str1 = {'H', 'e', 'l', 'l', 'o'}; cstring_span<> span1 = str1; std::vector str2 = std::move(str1); cstring_span<> span2 = str2; // comparison of spans from the same vector before and after move (ok) EXPECT_TRUE(span1 == span2); } } TEST(string_span_tests, ComparisonAndImplicitConstructors) { { cstring_span<> span = "Hello"; const char ar[] = {'H', 'e', 'l', 'l', 'o'}; const char ar1[] = "Hello"; const char ar2[10] = "Hello"; const char* ptr = "Hello"; const std::string str = "Hello"; const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; // comparison to literal EXPECT_TRUE(span < cstring_span<>("Helloo")); EXPECT_TRUE(span > cstring_span<>("Hell")); // comparison to static array with no null termination EXPECT_TRUE(span >= cstring_span<>(ar)); // comparison to static array with null at the end EXPECT_TRUE(span <= cstring_span<>(ar1)); // comparison to static array with null in the middle EXPECT_TRUE(span >= cstring_span<>(ar2)); // comparison to null-terminated c string EXPECT_TRUE(span <= cstring_span<>(ptr, 5)); // comparison to string EXPECT_TRUE(span >= cstring_span<>(str)); // comparison to vector of charaters with no null termination EXPECT_TRUE(span <= cstring_span<>(vec)); } { char ar[] = {'H', 'e', 'l', 'l', 'o'}; string_span<> span = ar; char larr[] = "Hell"; char rarr[] = "Helloo"; char ar1[] = "Hello"; char ar2[10] = "Hello"; char* ptr = ar; std::string str = "Hello"; std::vector vec = {'H', 'e', 'l', 'l', 'o'}; // comparison to static array with no null termination EXPECT_TRUE(span <= string_span<>(ar)); EXPECT_TRUE(span < string_span<>(rarr)); EXPECT_TRUE(span > string_span<>(larr)); // comparison to static array with null at the end EXPECT_TRUE(span >= string_span<>(ar1)); // comparison to static array with null in the middle EXPECT_TRUE(span <= string_span<>(ar2)); // comparison to null-terminated c string EXPECT_TRUE(span >= string_span<>(ptr, 5)); // comparison to string EXPECT_TRUE(span <= string_span<>(str)); // comparison to vector of charaters with no null termination EXPECT_TRUE(span >= string_span<>(vec)); } } TEST(string_span_tests, ConstrutorsEnsureZ) { // remove z from literals { cstring_span<> sp = "hello"; EXPECT_TRUE(sp.length() == 5); } // take the string as is { auto str = std::string("hello"); cstring_span<> sp = str; EXPECT_TRUE(sp.length() == 5); } // ensure z on c strings { gsl::owner ptr = new char[3]; ptr[0] = 'a'; ptr[1] = 'b'; ptr[2] = '\0'; string_span<> span = ensure_z(ptr); EXPECT_TRUE(span.length() == 2); delete[] ptr; } } TEST(string_span_tests, Constructors) { // creating cstring_span // from span of a final extent { span sp = "Hello"; cstring_span<> span = sp; EXPECT_TRUE(span.length() == 6); } // from const span of a final extent to non-const string_span #ifdef CONFIRM_COMPILATION_ERRORS { span sp = "Hello"; string_span<> span = sp; EXPECT_TRUE(span.length() == 6); } #endif // from string temporary #ifdef CONFIRM_COMPILATION_ERRORS { cstring_span<> span = std::string("Hello"); } #endif // default { cstring_span<> span; EXPECT_TRUE(span.length() == 0); } // from string literal { cstring_span<> span = "Hello"; EXPECT_TRUE(span.length() == 5); } // from const static array { const char ar[] = {'H', 'e', 'l', 'l', 'o'}; cstring_span<> span = ar; EXPECT_TRUE(span.length() == 5); } // from non-const static array { char ar[] = {'H', 'e', 'l', 'l', 'o'}; cstring_span<> span = ar; EXPECT_TRUE(span.length() == 5); } // from const ptr and length { const char* ptr = "Hello"; cstring_span<> span{ptr, 5}; EXPECT_TRUE(span.length() == 5); } // from const ptr and length, include 0 { const char* ptr = "Hello"; cstring_span<> span{ptr, 6}; EXPECT_TRUE(span.length() == 6); } // from const ptr and length, 0 inside { const char* ptr = "He\0lo"; cstring_span<> span{ptr, 5}; EXPECT_TRUE(span.length() == 5); } // from non-const ptr and length { char ar[] = {'H', 'e', 'l', 'l', 'o'}; char* ptr = ar; cstring_span<> span{ptr, 5}; EXPECT_TRUE(span.length() == 5); } // from non-const ptr and length, 0 inside { char ar[] = {'H', 'e', '\0', 'l', 'o'}; char* ptr = ar; cstring_span<> span{ptr, 5}; EXPECT_TRUE(span.length() == 5); } // from const string { const std::string str = "Hello"; const cstring_span<> span = str; EXPECT_TRUE(span.length() == 5); } // from non-const string { std::string str = "Hello"; const cstring_span<> span = str; EXPECT_TRUE(span.length() == 5); } // from const vector { const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const cstring_span<> span = vec; EXPECT_TRUE(span.length() == 5); } // from non-const vector { std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const cstring_span<> span = vec; EXPECT_TRUE(span.length() == 5); } // from const span { const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const span inner = vec; const cstring_span<> span = inner; EXPECT_TRUE(span.length() == 5); } // from non-const span { std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const span inner = vec; const cstring_span<> span = inner; EXPECT_TRUE(span.length() == 5); } // from const string_span { const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const cstring_span<> tmp = vec; const cstring_span<> span = tmp; EXPECT_TRUE(span.length() == 5); } // from non-const string_span { std::vector vec = {'H', 'e', 'l', 'l', 'o'}; string_span<> tmp = vec; cstring_span<> span = tmp; EXPECT_TRUE(span.length() == 5); } // creating string_span // from string literal { #ifdef CONFIRM_COMPILATION_ERRORS string_span<> span = "Hello"; #endif } // from const static array { #ifdef CONFIRM_COMPILATION_ERRORS const char ar[] = {'H', 'e', 'l', 'l', 'o'}; string_span<> span = ar; EXPECT_TRUE(span.length() == 5); #endif } // from non-const static array { char ar[] = {'H', 'e', 'l', 'l', 'o'}; string_span<> span = ar; EXPECT_TRUE(span.length() == 5); } // from const ptr and length { #ifdef CONFIRM_COMPILATION_ERRORS const char* ptr = "Hello"; string_span<> span{ptr, 5}; EXPECT_TRUE(span.length() == 5); #endif } // from non-const ptr and length { char ar[] = {'H', 'e', 'l', 'l', 'o'}; char* ptr = ar; string_span<> span{ptr, 5}; EXPECT_TRUE(span.length() == 5); } // from const string { #ifdef CONFIRM_COMPILATION_ERRORS const std::string str = "Hello"; string_span<> span = str; EXPECT_TRUE(span.length() == 5); #endif } // from non-const string { std::string str = "Hello"; string_span<> span = str; EXPECT_TRUE(span.length() == 5); } // from const vector { #ifdef CONFIRM_COMPILATION_ERRORS const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; string_span<> span = vec; EXPECT_TRUE(span.length() == 5); #endif } // from non-const vector { std::vector vec = {'H', 'e', 'l', 'l', 'o'}; string_span<> span = vec; EXPECT_TRUE(span.length() == 5); } // from const span { #ifdef CONFIRM_COMPILATION_ERRORS std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const span inner = vec; string_span<> span = inner; EXPECT_TRUE(span.length() == 5); #endif } // from non-const span { std::vector vec = {'H', 'e', 'l', 'l', 'o'}; span inner = vec; string_span<> span = inner; EXPECT_TRUE(span.length() == 5); } // from non-const span of non-const data from const vector { #ifdef CONFIRM_COMPILATION_ERRORS const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const span inner = vec; string_span<> span = inner; EXPECT_TRUE(span.length() == 5); #endif } // from const string_span { #ifdef CONFIRM_COMPILATION_ERRORS std::vector vec = {'H', 'e', 'l', 'l', 'o'}; cstring_span<> tmp = vec; string_span<> span = tmp; EXPECT_TRUE(span.length() == 5); #endif } // from non-const string_span { std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const string_span<> tmp = vec; const string_span<> span = tmp; EXPECT_TRUE(span.length() == 5); } // from non-const string_span from const vector { #ifdef CONFIRM_COMPILATION_ERRORS const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; string_span<> tmp = vec; string_span<> span = tmp; EXPECT_TRUE(span.length() == 5); #endif } // from const string_span of non-const data { std::vector vec = {'H', 'e', 'l', 'l', 'o'}; const string_span<> tmp = vec; const string_span<> span = tmp; EXPECT_TRUE(span.length() == 5); } } TEST(string_span_tests, MoveConstructors) { // move string_span { cstring_span<> span = "Hello"; const auto span1 = std::move(span); EXPECT_TRUE(span1.length() == 5); } { cstring_span<> span = "Hello"; const auto span1 = move_wrapper(std::move(span)); EXPECT_TRUE(span1.length() == 5); } { cstring_span<> span = "Hello"; const auto span1 = move_wrapper(std::move(span)); EXPECT_TRUE(span1.length() == 5); } // move span { span span = ensure_z("Hello"); const cstring_span<> span1 = std::move(span); EXPECT_TRUE(span1.length() == 5); } { span span = ensure_z("Hello"); const cstring_span<> span2 = move_wrapper(std::move(span)); EXPECT_TRUE(span2.length() == 5); } // move string { #ifdef CONFIRM_COMPILATION_ERRORS std::string str = "Hello"; string_span<> span = std::move(str); EXPECT_TRUE(span.length() == 5); #endif } { #ifdef CONFIRM_COMPILATION_ERRORS std::string str = "Hello"; string_span<> span = move_wrapper(std::move(str)); EXPECT_TRUE(span.length() == 5); #endif } { #ifdef CONFIRM_COMPILATION_ERRORS use(create()); #endif } // move container { #ifdef CONFIRM_COMPILATION_ERRORS std::vector vec = {'H', 'e', 'l', 'l', 'o'}; string_span<> span = std::move(vec); EXPECT_TRUE(span.length() == 5); #endif } { #ifdef CONFIRM_COMPILATION_ERRORS std::vector vec = {'H', 'e', 'l', 'l', 'o'}; string_span<> span = move_wrapper>(std::move(vec)); EXPECT_TRUE(span.length() == 5); #endif } { #ifdef CONFIRM_COMPILATION_ERRORS use(create>()); #endif } } TEST(string_span_tests, Conversion) { #ifdef CONFIRM_COMPILATION_ERRORS cstring_span<> span = "Hello"; cwstring_span<> wspan{span}; EXPECT_TRUE(wspan.length() == 5); #endif } TEST(string_span_tests, zstring) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. zstring"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); // create zspan from zero terminated string { char buf[1]; buf[0] = '\0'; zstring_span<> zspan({buf, 1}); EXPECT_TRUE(generic::strlen(zspan.assume_z()) == 0); EXPECT_TRUE(zspan.as_string_span().size() == 0); EXPECT_TRUE(zspan.ensure_z().size() == 0); } // create zspan from non-zero terminated string { char buf[1]; buf[0] = 'a'; auto workaround_macro = [&]() { const zstring_span<> zspan({buf, 1}); }; EXPECT_DEATH(workaround_macro(), expected); } // usage scenario: create zero-terminated temp file name and pass to a legacy API { char buf[10]; auto name = CreateTempName({buf, 10}); if (!name.empty()) { czstring str = name.assume_z(); EXPECT_TRUE(generic::strlen(str) == 3); EXPECT_TRUE(*(str + 3) == '\0'); } } } TEST(string_span_tests, wzstring) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. wzstring"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); // create zspan from zero terminated string { wchar_t buf[1]; buf[0] = L'\0'; wzstring_span<> zspan({buf, 1}); EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0); EXPECT_TRUE(zspan.as_string_span().size() == 0); EXPECT_TRUE(zspan.ensure_z().size() == 0); } // create zspan from non-zero terminated string { wchar_t buf[1]; buf[0] = L'a'; const auto workaround_macro = [&]() { const wzstring_span<> zspan({buf, 1}); }; EXPECT_DEATH(workaround_macro(), expected); } // usage scenario: create zero-terminated temp file name and pass to a legacy API { wchar_t buf[10]; const auto name = CreateTempNameW({buf, 10}); if (!name.empty()) { cwzstring str = name.assume_z(); EXPECT_TRUE(generic::strnlen(str, 10) == 3); EXPECT_TRUE(*(str + 3) == L'\0'); } } } TEST(string_span_tests, u16zstring) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. u16zstring"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); // create zspan from zero terminated string { char16_t buf[1]; buf[0] = L'\0'; u16zstring_span<> zspan({buf, 1}); EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0); EXPECT_TRUE(zspan.as_string_span().size() == 0); EXPECT_TRUE(zspan.ensure_z().size() == 0); } // create zspan from non-zero terminated string { char16_t buf[1]; buf[0] = u'a'; const auto workaround_macro = [&]() { const u16zstring_span<> zspan({buf, 1}); }; EXPECT_DEATH(workaround_macro(), expected); } // usage scenario: create zero-terminated temp file name and pass to a legacy API { char16_t buf[10]; const auto name = CreateTempNameU16({buf, 10}); if (!name.empty()) { cu16zstring str = name.assume_z(); EXPECT_TRUE(generic::strnlen(str, 10) == 3); EXPECT_TRUE(*(str + 3) == L'\0'); } } } TEST(string_span_tests, u32zstring) { const auto terminateHandler = std::set_terminate([] { std::cerr << "Expected Death. u31zstring"; std::abort(); }); const auto expected = GetExpectedDeathString(terminateHandler); // create zspan from zero terminated string { char32_t buf[1]; buf[0] = L'\0'; u32zstring_span<> zspan({buf, 1}); EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0); EXPECT_TRUE(zspan.as_string_span().size() == 0); EXPECT_TRUE(zspan.ensure_z().size() == 0); } // create zspan from non-zero terminated string { char32_t buf[1]; buf[0] = u'a'; const auto workaround_macro = [&]() { const u32zstring_span<> zspan({buf, 1}); }; EXPECT_DEATH(workaround_macro(), expected); } // usage scenario: create zero-terminated temp file name and pass to a legacy API { char32_t buf[10]; const auto name = CreateTempNameU32({buf, 10}); if (!name.empty()) { cu32zstring str = name.assume_z(); EXPECT_TRUE(generic::strnlen(str, 10) == 3); EXPECT_TRUE(*(str + 3) == L'\0'); } } } TEST(string_span_tests, Issue305) { std::map, int> foo = {{"foo", 0}, {"bar", 1}}; EXPECT_TRUE(foo["foo"] == 0); EXPECT_TRUE(foo["bar"] == 1); } TEST(string_span_tests, char16_t_type) { gsl::cu16string_span<> ss1 = gsl::ensure_z(u"abc"); EXPECT_TRUE(ss1.size() == 3); EXPECT_TRUE(ss1.size_bytes() == 6); std::u16string s1 = gsl::to_string(ss1); EXPECT_TRUE(s1 == u"abc"); std::u16string s2 = u"abc"; gsl::u16string_span<> ss2 = s2; EXPECT_TRUE(ss2.size() == 3); gsl::u16string_span<> ss3 = ss2.subspan(1, 1); EXPECT_TRUE(ss3.size() == 1); EXPECT_TRUE(ss3[0] == u'b'); char16_t buf[4]{u'a', u'b', u'c', u'\0'}; gsl::u16string_span<> ss4{buf, 4}; EXPECT_TRUE(ss4[3] == u'\0'); gsl::cu16zstring_span<> ss5(u"abc"); EXPECT_TRUE((ss5.as_string_span().size()) == 3); gsl::cu16string_span<> ss6 = ss5.as_string_span(); EXPECT_TRUE(ss6 == ss1); std::vector v7 = {u'a', u'b', u'c'}; gsl::cu16string_span<> ss7{v7}; EXPECT_TRUE(ss7 == ss1); gsl::cu16string_span<> ss8 = gsl::ensure_z(u"abc"); gsl::cu16string_span<> ss9 = gsl::ensure_z(u"abc"); EXPECT_TRUE(ss8 == ss9); ss9 = gsl::ensure_z(u"abd"); EXPECT_TRUE(ss8 < ss9); EXPECT_TRUE(ss8 <= ss9); EXPECT_TRUE(ss8 != ss9); } TEST(string_span_tests, char32_t_type) { gsl::cu32string_span<> ss1 = gsl::ensure_z(U"abc"); EXPECT_TRUE(ss1.size() == 3); EXPECT_TRUE(ss1.size_bytes() == 12); std::u32string s1 = gsl::to_string(ss1); EXPECT_TRUE(s1 == U"abc"); std::u32string s2 = U"abc"; gsl::u32string_span<> ss2 = s2; EXPECT_TRUE(ss2.size() == 3); gsl::u32string_span<> ss3 = ss2.subspan(1, 1); EXPECT_TRUE(ss3.size() == 1); EXPECT_TRUE(ss3[0] == U'b'); char32_t buf[4]{U'a', U'b', U'c', U'\0'}; gsl::u32string_span<> ss4{buf, 4}; EXPECT_TRUE(ss4[3] == u'\0'); gsl::cu32zstring_span<> ss5(U"abc"); EXPECT_TRUE(ss5.as_string_span().size() == 3); gsl::cu32string_span<> ss6 = ss5.as_string_span(); EXPECT_TRUE(ss6 == ss1); gsl::cu32string_span<> ss8 = gsl::ensure_z(U"abc"); gsl::cu32string_span<> ss9 = gsl::ensure_z(U"abc"); EXPECT_TRUE(ss8 == ss9); ss9 = gsl::ensure_z(U"abd"); EXPECT_TRUE(ss8 < ss9); EXPECT_TRUE(ss8 <= ss9); EXPECT_TRUE(ss8 != ss9); } TEST(string_span_tests, as_bytes) { cwzstring_span<> v(L"qwerty"); const auto s = v.as_string_span(); const auto bs = as_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } TEST(string_span_tests, as_writable_bytes) { wchar_t buf[]{L"qwerty"}; wzstring_span<> v(buf); const auto s = v.as_string_span(); const auto bs = as_writable_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } GSL-4.0.0/tests/utils_tests.cpp000066400000000000000000000076671417507532300164170ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include // for move #include #include // for std::ptrdiff_t #include // for reference_wrapper, _Bind_helper<>::type #include // for narrow, narrowing_error #include // finally, narrow_cast #include // for numeric_limits #include // for uint32_t, int32_t #include // for is_same using namespace gsl; 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) { static_assert(std::is_same::value, "gsl::index represents wrong arithmetic type"); } TEST(utils_tests, finally_lambda) { int i = 0; { auto _ = finally([&]() { f(i); }); EXPECT_TRUE(i == 0); } EXPECT_TRUE(i == 1); } TEST(utils_tests, finally_lambda_move) { int i = 0; { auto _1 = finally([&]() { f(i); }); { auto _2 = std::move(_1); EXPECT_TRUE(i == 0); } EXPECT_TRUE(i == 1); { auto _2 = std::move(_1); EXPECT_TRUE(i == 1); } EXPECT_TRUE(i == 1); } EXPECT_TRUE(i == 1); } TEST(utils_tests, finally_const_lvalue_lambda) { int i = 0; { const auto const_lvalue_lambda = [&]() { f(i); }; auto _ = finally(const_lvalue_lambda); EXPECT_TRUE(i == 0); } EXPECT_TRUE(i == 1); } TEST(utils_tests, finally_mutable_lvalue_lambda) { int i = 0; { auto mutable_lvalue_lambda = [&]() { f(i); }; auto _ = finally(mutable_lvalue_lambda); EXPECT_TRUE(i == 0); } EXPECT_TRUE(i == 1); } TEST(utils_tests, finally_function_with_bind) { int i = 0; { auto _ = finally(std::bind(&f, std::ref(i))); EXPECT_TRUE(i == 0); } EXPECT_TRUE(i == 1); } TEST(utils_tests, finally_function_ptr) { j = 0; { auto _ = finally(&g); EXPECT_TRUE(j == 0); } EXPECT_TRUE(j == 1); } TEST(utils_tests, narrow_cast) { int n = 120; char c = narrow_cast(n); EXPECT_TRUE(c == 120); n = 300; unsigned char uc = narrow_cast(n); EXPECT_TRUE(uc == 44); } #ifndef GSL_KERNEL_MODE TEST(utils_tests, narrow) { int n = 120; const char c = narrow(n); EXPECT_TRUE(c == 120); n = 300; EXPECT_THROW(narrow(n), narrowing_error); const auto int32_max = std::numeric_limits::max(); const auto int32_min = std::numeric_limits::min(); EXPECT_TRUE(narrow(int32_t(0)) == 0); EXPECT_TRUE(narrow(int32_t(1)) == 1); EXPECT_TRUE(narrow(int32_max) == static_cast(int32_max)); EXPECT_THROW(narrow(int32_t(-1)), narrowing_error); EXPECT_THROW(narrow(int32_min), narrowing_error); n = -42; EXPECT_THROW(narrow(n), narrowing_error); EXPECT_TRUE( narrow>(std::complex(4, 2)) == std::complex(4, 2)); EXPECT_THROW(narrow>(std::complex(4.2)), narrowing_error); } #endif // GSL_KERNEL_MODE