summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt9
-rw-r--r--cmake/Findzstd.cmake10
-rw-r--r--cmake/ONTFindModuleHelpers.cmake5
-rw-r--r--cmake/SignFile.cmake30
-rw-r--r--cmake/conan.cmake344
-rw-r--r--debian/changelog15
-rw-r--r--debian/control8
-rw-r--r--debian/libvbz-hdf-plugin0.symbols33
-rw-r--r--debian/patches/fix-install-location.patch6
-rw-r--r--debian/patches/series1
-rw-r--r--debian/patches/update-catch2.patch9997
-rw-r--r--debian/patches/use-packaged-streamvbyte.patch16
-rwxr-xr-xdebian/rules1
-rw-r--r--python/test/requirements_1.10.txt5
-rw-r--r--python/test/requirements_1.12.txt2
-rw-r--r--third_party/gsl-disable-gsl-suppress.patch11
-rw-r--r--[-rwxr-xr-x]third_party/gsl.h10
-rw-r--r--[-rwxr-xr-x]third_party/gsl/gsl6
-rw-r--r--[-rwxr-xr-x]third_party/gsl/gsl-lite-vc6.hpp (renamed from third_party/gsl/gsl-lite-vc6.h)56
-rw-r--r--[-rwxr-xr-x]third_party/gsl/gsl-lite.h2258
-rw-r--r--third_party/gsl/gsl-lite.hpp5197
-rw-r--r--vbz/CMakeLists.txt4
-rw-r--r--vbz/perf/test_data_generator.h2
-rw-r--r--vbz/test/CMakeLists.txt5
-rw-r--r--vbz/test/test_utils.h2
-rw-r--r--vbz/v0/vbz_streamvbyte.cpp2
-rw-r--r--vbz/v0/vbz_streamvbyte_impl.h8
-rw-r--r--vbz/v1/vbz_streamvbyte.cpp2
-rw-r--r--vbz/v1/vbz_streamvbyte_impl.h7
-rw-r--r--vbz/vbz.cpp2
-rw-r--r--vbz_plugin/CMakeLists.txt12
-rw-r--r--vbz_plugin/vbz_plugin.cpp8
32 files changed, 5653 insertions, 12421 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a6f360..b3b7f1d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,6 +17,7 @@ project(hdf_plugins
)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+set(CMAKE_CXX_STANDARD 14)
include(ExternalProject)
include(GenerateExportHeader)
@@ -75,6 +76,8 @@ if (NOT VBZ_BUILD_ARCHIVE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
+option(BUILD_SHARED_LIBS "Build shared library for VBZ plugin" ON)
+
if (ENABLE_CONAN)
#
# Dependencies: Conan
@@ -87,7 +90,7 @@ if (ENABLE_CONAN)
include(conan)
set(_requirements
- "zstd/1.3.4@nanopore/stable")
+ "zstd/1.4.8@nanopore/stable")
set(_generators
cmake
json)
@@ -111,10 +114,14 @@ if (ENABLE_CONAN)
list(APPEND _extra_args BUILD_TYPE "${_build_type_${_build_type}}")
endif()
endif()
+ if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ list(APPEND CONAN_EXTRA_SETTINGS "compiler.cppstd=${CMAKE_CXX_STANDARD}")
+ endif()
if (CONAN_EXTRA_SETTINGS)
list(APPEND _extra_args
SETTINGS
${CONAN_EXTRA_SETTINGS}
+ BUILD missing
)
endif()
diff --git a/cmake/Findzstd.cmake b/cmake/Findzstd.cmake
index 7fd4b4a..493a53b 100644
--- a/cmake/Findzstd.cmake
+++ b/cmake/Findzstd.cmake
@@ -1,6 +1,8 @@
find_path(ZSTD_INCLUDE_DIR
NAMES zstd.h
- PATHS ${CONAN_INCLUDE_DIRS_RELEASE}
+ PATHS
+ ${CONAN_INCLUDE_DIRS_RELEASE}
+ ${CONAN_INCLUDE_DIRS_DEBUG}
)
set(ZSTD_NAMES zstd zstd_static)
@@ -11,7 +13,9 @@ find_library(ZSTD_LIBRARY_RELEASE
PATHS ${CONAN_LIB_DIRS_RELEASE}
)
find_library(ZSTD_LIBRARY_DEBUG
- NAMES ${ZSTD_NAMES_DEBUG}
+ NAMES
+ ${ZSTD_NAMES_DEBUG}
+ ${ZSTD_NAMES}
PATHS ${CONAN_LIB_DIRS_DEBUG}
)
@@ -68,4 +72,4 @@ if (ZSTD_FOUND)
IMPORTED_LOCATION "${ZSTD_LIBRARY}")
endif()
endif()
-endif() \ No newline at end of file
+endif()
diff --git a/cmake/ONTFindModuleHelpers.cmake b/cmake/ONTFindModuleHelpers.cmake
index d795912..bcc987c 100644
--- a/cmake/ONTFindModuleHelpers.cmake
+++ b/cmake/ONTFindModuleHelpers.cmake
@@ -172,6 +172,9 @@ macro(ont_find_package_handle_library_components module_name)
if(NOT _ONT_FPWC_SKIP_PKG_CONFIG)
find_package(PkgConfig QUIET)
endif()
+ # CMake 3.17+ warns when find_package_handle_standard_args() is called with a name that doesn't
+ # match the find module name; this tells it that we really did mean to do that
+ set(FPHSA_NAME_MISMATCHED TRUE)
foreach(_comp ${_ONT_FPWC_COMPONENTS})
set(_dep_vars)
set(_dep_targets)
@@ -290,6 +293,8 @@ macro(ont_find_package_handle_library_components module_name)
"${module_name}::${_comp}")
endif()
endforeach()
+ # we need to unset it again because this is a macro, not a function
+ unset(FPHSA_NAME_MISMATCHED)
if(${module_name}_DEBUG_LIBRARIES)
list(REMOVE_DUPLICATES ${module_name}_DEBUG_LIBRARIES)
endif()
diff --git a/cmake/SignFile.cmake b/cmake/SignFile.cmake
index cfa320d..286bacc 100644
--- a/cmake/SignFile.cmake
+++ b/cmake/SignFile.cmake
@@ -24,7 +24,8 @@ elseif(WIN32)
message("Signing file... ${file_to_sign}${comment}")
set(SIGN_COMMAND ${SIGNTOOL_EXE} sign "/v" "/sha1" "${MINKNOW_CODE_SIGN_IDENTITY}"
- "/t" "http://timestamp.globalsign.com/scripts/"
+ "/tr" "http://rfc3161timestamp.globalsign.com/advanced"
+ "/td" "SHA256"
${file_to_sign}
)
@@ -32,13 +33,26 @@ else()
message(FATAL_ERROR "Cannot sign code on this platform.")
endif()
-message("Running sign command: ${SIGN_COMMAND}")
-execute_process(
- COMMAND ${SIGN_COMMAND}
- RESULT_VARIABLE result
- OUTPUT_VARIABLE output
- ERROR_VARIABLE output
-)
+set(retry_count 10)
+foreach(retry_index RANGE ${retry_count})
+ message("Running sign command: ${SIGN_COMMAND}")
+ execute_process(
+ COMMAND ${SIGN_COMMAND}
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE output
+ ERROR_VARIABLE output
+ )
+
+ if (result EQUAL 0)
+ break()
+ endif()
+
+ message(WARN "Signing failed, waiting and retrying (${retry_index}/${retry_count})")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E sleep 5
+ )
+
+endforeach()
if (NOT result EQUAL 0)
message(FATAL_ERROR "Could not sign file: ${result}: ${output}")
diff --git a/cmake/conan.cmake b/cmake/conan.cmake
index db9a18a..1bd1289 100644
--- a/cmake/conan.cmake
+++ b/cmake/conan.cmake
@@ -52,40 +52,49 @@ function(_get_msvc_ide_version result)
set(${result} 14 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1910 AND MSVC_VERSION VERSION_LESS 1920)
set(${result} 15 PARENT_SCOPE)
+ elseif(NOT MSVC_VERSION VERSION_LESS 1920 AND MSVC_VERSION VERSION_LESS 1930)
+ set(${result} 16 PARENT_SCOPE)
else()
message(FATAL_ERROR "Conan: Unknown MSVC compiler version [${MSVC_VERSION}]")
endif()
endfunction()
function(conan_cmake_settings result)
- message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER})
- message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER_ID})
- message(STATUS "VERSION " ${CMAKE_CXX_COMPILER_VERSION})
- message(STATUS "FLAGS " ${CMAKE_LANG_FLAGS})
- message(STATUS "LIB ARCH " ${CMAKE_CXX_LIBRARY_ARCHITECTURE})
- message(STATUS "BUILD TYPE " ${CMAKE_BUILD_TYPE})
- message(STATUS "GENERATOR " ${CMAKE_GENERATOR})
- message(STATUS "GENERATOR WIN64 " ${CMAKE_CL_64})
-
- message(STATUS "Conan ** WARNING** : This detection of settings from cmake is experimental and incomplete. "
- "Please check 'conan.cmake' and contribute")
+ #message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER})
+ #message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER_ID})
+ #message(STATUS "VERSION " ${CMAKE_CXX_COMPILER_VERSION})
+ #message(STATUS "FLAGS " ${CMAKE_LANG_FLAGS})
+ #message(STATUS "LIB ARCH " ${CMAKE_CXX_LIBRARY_ARCHITECTURE})
+ #message(STATUS "BUILD TYPE " ${CMAKE_BUILD_TYPE})
+ #message(STATUS "GENERATOR " ${CMAKE_GENERATOR})
+ #message(STATUS "GENERATOR WIN64 " ${CMAKE_CL_64})
+
+ message(STATUS "Conan: Automatic detection of conan settings from cmake")
parse_arguments(${ARGV})
- set(arch ${ARGUMENTS_ARCH})
- if(CONAN_CMAKE_MULTI)
- set(_SETTINGS -g cmake_multi)
- else()
- set(_SETTINGS -g cmake)
- endif()
if(ARGUMENTS_BUILD_TYPE)
- set(_SETTINGS ${_SETTINGS} -s build_type=${ARGUMENTS_BUILD_TYPE})
+ set(_CONAN_SETTING_BUILD_TYPE ${ARGUMENTS_BUILD_TYPE})
elseif(CMAKE_BUILD_TYPE)
- set(_SETTINGS ${_SETTINGS} -s build_type=${CMAKE_BUILD_TYPE})
+ set(_CONAN_SETTING_BUILD_TYPE ${CMAKE_BUILD_TYPE})
else()
message(FATAL_ERROR "Please specify in command line CMAKE_BUILD_TYPE (-DCMAKE_BUILD_TYPE=Release)")
endif()
+ string(TOUPPER ${_CONAN_SETTING_BUILD_TYPE} _CONAN_SETTING_BUILD_TYPE_UPPER)
+ if (_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "DEBUG")
+ set(_CONAN_SETTING_BUILD_TYPE "Debug")
+ elseif(_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "RELEASE")
+ set(_CONAN_SETTING_BUILD_TYPE "Release")
+ elseif(_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "RELWITHDEBINFO")
+ set(_CONAN_SETTING_BUILD_TYPE "RelWithDebInfo")
+ elseif(_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "MINSIZEREL")
+ set(_CONAN_SETTING_BUILD_TYPE "MinSizeRel")
+ endif()
+
+ if(ARGUMENTS_ARCH)
+ set(_CONAN_SETTING_ARCH ${ARGUMENTS_ARCH})
+ endif()
#handle -s os setting
if(CMAKE_SYSTEM_NAME)
#use default conan os setting if CMAKE_SYSTEM_NAME is not defined
@@ -93,11 +102,11 @@ function(conan_cmake_settings result)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set(CONAN_SYSTEM_NAME Macos)
endif()
- set(CONAN_SUPPORTED_PLATFORMS Windows Linux Macos Android iOS FreeBSD)
+ set(CONAN_SUPPORTED_PLATFORMS Windows Linux Macos Android iOS FreeBSD WindowsStore)
list (FIND CONAN_SUPPORTED_PLATFORMS "${CONAN_SYSTEM_NAME}" _index)
if (${_index} GREATER -1)
#check if the cmake system is a conan supported one
- set(_SETTINGS ${_SETTINGS} -s os=${CONAN_SYSTEM_NAME})
+ set(_CONAN_SETTING_OS ${CONAN_SYSTEM_NAME})
else()
message(FATAL_ERROR "cmake system ${CONAN_SYSTEM_NAME} is not supported by conan. Use one of ${CONAN_SUPPORTED_PLATFORMS}")
endif()
@@ -114,10 +123,6 @@ function(conan_cmake_settings result)
message(FATAL_ERROR "Conan: Neither C or C++ was detected as a language for the project. Unabled to detect compiler version.")
endif()
- if(arch)
- set(_SETTINGS ${_SETTINGS} -s arch=${arch})
- endif()
-
if (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL GNU)
# using GCC
# TODO: Handle other params
@@ -128,72 +133,74 @@ function(conan_cmake_settings result)
if(${MAJOR} GREATER 4)
set(COMPILER_VERSION ${MAJOR})
endif()
- set(_SETTINGS ${_SETTINGS} -s compiler=gcc -s compiler.version=${COMPILER_VERSION})
+ set(_CONAN_SETTING_COMPILER gcc)
+ set(_CONAN_SETTING_COMPILER_VERSION ${COMPILER_VERSION})
if (USING_CXX)
- conan_cmake_detect_gnu_libcxx(_LIBCXX)
- set(_SETTINGS ${_SETTINGS} -s compiler.libcxx=${_LIBCXX})
+ conan_cmake_detect_unix_libcxx(_LIBCXX)
+ set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
endif ()
elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL AppleClang)
# using AppleClang
string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION})
list(GET VERSION_LIST 0 MAJOR)
list(GET VERSION_LIST 1 MINOR)
- set(_SETTINGS ${_SETTINGS} -s compiler=apple-clang -s compiler.version=${MAJOR}.${MINOR})
+ set(_CONAN_SETTING_COMPILER apple-clang)
+ set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}.${MINOR})
if (USING_CXX)
- set(_SETTINGS ${_SETTINGS} -s compiler.libcxx=libc++)
+ conan_cmake_detect_unix_libcxx(_LIBCXX)
+ set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
endif ()
elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Clang)
string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION})
list(GET VERSION_LIST 0 MAJOR)
list(GET VERSION_LIST 1 MINOR)
+ set(_CONAN_SETTING_COMPILER clang)
+ set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}.${MINOR})
if(APPLE)
cmake_policy(GET CMP0025 APPLE_CLANG_POLICY_ENABLED)
if(NOT APPLE_CLANG_POLICY_ENABLED)
message(STATUS "Conan: APPLE and Clang detected. Assuming apple-clang compiler. Set CMP0025 to avoid it")
- set(_SETTINGS ${_SETTINGS} -s compiler=apple-clang -s compiler.version=${MAJOR}.${MINOR})
- else()
- set(_SETTINGS ${_SETTINGS} -s compiler=clang -s compiler.version=${MAJOR}.${MINOR})
+ set(_CONAN_SETTING_COMPILER apple-clang)
endif()
- if (USING_CXX)
- set(_SETTINGS ${_SETTINGS} -s compiler.libcxx=libc++)
- endif ()
- else()
- set(_SETTINGS ${_SETTINGS} -s compiler=clang -s compiler.version=${MAJOR}.${MINOR})
- if (USING_CXX)
- conan_cmake_detect_gnu_libcxx(_LIBCXX)
- set(_SETTINGS ${_SETTINGS} -s compiler.libcxx=${_LIBCXX})
- endif ()
endif()
+ if(${_CONAN_SETTING_COMPILER} STREQUAL clang AND ${MAJOR} GREATER 7)
+ set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR})
+ endif()
+ if (USING_CXX)
+ conan_cmake_detect_unix_libcxx(_LIBCXX)
+ set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
+ endif ()
elseif(${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL MSVC)
set(_VISUAL "Visual Studio")
_get_msvc_ide_version(_VISUAL_VERSION)
if("${_VISUAL_VERSION}" STREQUAL "")
message(FATAL_ERROR "Conan: Visual Studio not recognized")
else()
- set(_SETTINGS ${_SETTINGS} -s compiler=${_VISUAL} -s compiler.version=${_VISUAL_VERSION})
+ set(_CONAN_SETTING_COMPILER ${_VISUAL})
+ set(_CONAN_SETTING_COMPILER_VERSION ${_VISUAL_VERSION})
endif()
- if(NOT arch)
+ if(NOT _CONAN_SETTING_ARCH)
if (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "64")
- set(_SETTINGS ${_SETTINGS} -s arch=x86_64)
+ set(_CONAN_SETTING_ARCH x86_64)
elseif (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "^ARM")
message(STATUS "Conan: Using default ARM architecture from MSVC")
- set(_SETTINGS ${_SETTINGS} -s arch=armv6)
+ set(_CONAN_SETTING_ARCH armv6)
elseif (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "86")
- set(_SETTINGS ${_SETTINGS} -s arch=x86)
+ set(_CONAN_SETTING_ARCH x86)
else ()
message(FATAL_ERROR "Conan: Unknown MSVC architecture [${MSVC_${LANGUAGE}_ARCHITECTURE_ID}]")
endif()
endif()
conan_cmake_detect_vs_runtime(_vs_runtime)
- message(STATUS "Detected VS runtime: ${_vs_runtime}")
- set(_SETTINGS ${_SETTINGS} -s compiler.runtime=${_vs_runtime})
-
+ message(STATUS "Conan: Detected VS runtime: ${_vs_runtime}")
+ set(_CONAN_SETTING_COMPILER_RUNTIME ${_vs_runtime})
+
if (CMAKE_GENERATOR_TOOLSET)
- set(_SETTINGS ${_SETTINGS} -s compiler.toolset=${CMAKE_VS_PLATFORM_TOOLSET})
+ set(_CONAN_SETTING_COMPILER_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET})
elseif(CMAKE_VS_PLATFORM_TOOLSET AND (CMAKE_GENERATOR STREQUAL "Ninja"))
- set(_SETTINGS ${_SETTINGS} -s compiler.toolset=${CMAKE_VS_PLATFORM_TOOLSET})
+ set(_CONAN_SETTING_COMPILER_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET})
endif()
# Temp fix due to https://github.com/conan-io/cmake-conan/issues/166
elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Intel)
@@ -205,56 +212,113 @@ function(conan_cmake_settings result)
set(_CONAN_SETTING_COMPILER_VERSION ${COMPILER_VERSION})
set(_SETTINGS ${_SETTINGS} -s compiler=icc -s compiler.version=${COMPILER_VERSION})
if (USING_CXX)
- conan_cmake_detect_gnu_libcxx(_LIBCXX)
+ conan_cmake_detect_unix_libcxx(_LIBCXX)
set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
endif ()
else()
message(FATAL_ERROR "Conan: compiler setup not recognized")
endif()
+ # If profile is defined it is used
+ if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND ARGUMENTS_DEBUG_PROFILE)
+ set(_APPLIED_PROFILES ${ARGUMENTS_DEBUG_PROFILE})
+ elseif(CMAKE_BUILD_TYPE STREQUAL "Release" AND ARGUMENTS_RELEASE_PROFILE)
+ set(_APPLIED_PROFILES ${ARGUMENTS_RELEASE_PROFILE})
+ elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" AND ARGUMENTS_RELWITHDEBINFO_PROFILE)
+ set(_APPLIED_PROFILES ${ARGUMENTS_RELWITHDEBINFO_PROFILE})
+ elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel" AND ARGUMENTS_MINSIZEREL_PROFILE)
+ set(_APPLIED_PROFILES ${ARGUMENTS_MINSIZEREL_PROFILE})
+ elseif(ARGUMENTS_PROFILE)
+ set(_APPLIED_PROFILES ${ARGUMENTS_PROFILE})
+ endif()
+
+ foreach(ARG ${_APPLIED_PROFILES})
+ set(_SETTINGS ${_SETTINGS} -pr ${ARG})
+ endforeach()
+
+ if(NOT _SETTINGS OR ARGUMENTS_PROFILE_AUTO STREQUAL "ALL")
+ set(ARGUMENTS_PROFILE_AUTO arch build_type compiler compiler.version
+ compiler.runtime compiler.libcxx compiler.toolset)
+ endif()
+
+ # Automatic from CMake
+ foreach(ARG ${ARGUMENTS_PROFILE_AUTO})
+ string(TOUPPER ${ARG} _arg_name)
+ string(REPLACE "." "_" _arg_name ${_arg_name})
+ if(_CONAN_SETTING_${_arg_name})
+ set(_SETTINGS ${_SETTINGS} -s ${ARG}=${_CONAN_SETTING_${_arg_name}})
+ endif()
+ endforeach()
+
foreach(ARG ${ARGUMENTS_SETTINGS})
set(_SETTINGS ${_SETTINGS} -s ${ARG})
endforeach()
+ message(STATUS "Conan: Settings= ${_SETTINGS}")
+
set(${result} ${_SETTINGS} PARENT_SCOPE)
endfunction()
-function(conan_cmake_detect_gnu_libcxx result)
- # Allow -D_GLIBCXX_USE_CXX11_ABI=ON/OFF as argument to cmake
- if(DEFINED _GLIBCXX_USE_CXX11_ABI)
- if(_GLIBCXX_USE_CXX11_ABI)
- set(${result} libstdc++11 PARENT_SCOPE)
- return()
- else()
- set(${result} libstdc++ PARENT_SCOPE)
- return()
+function(conan_cmake_detect_unix_libcxx result)
+ set(compile_options)
+
+ # Take into account any -stdlib in compile options
+ get_directory_property(options DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS)
+ foreach(option ${options})
+ if(option MATCHES "^-std")
+ set(compile_options ${compile_options} "${option}")
endif()
- endif()
+ endforeach()
- # Check if there's any add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+ # Take into account any _GLIBCXX_USE_CXX11_ABI in compile definitions
get_directory_property(defines DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS)
foreach(define ${defines})
- if(define STREQUAL "_GLIBCXX_USE_CXX11_ABI=0")
- set(${result} libstdc++ PARENT_SCOPE)
- return()
+ if(define MATCHES "_GLIBCXX_USE_CXX11_ABI")
+ if(define MATCHES "^-D")
+ set(compile_options ${compile_options} "${define}")
+ else()
+ set(compile_options ${compile_options} "-D${define}")
+ endif()
endif()
endforeach()
- # Use C++11 stdlib as default if gcc is 5.1+
- if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.1")
- set(${result} libstdc++ PARENT_SCOPE)
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E echo "#include <string>"
+ COMMAND ${CMAKE_CXX_COMPILER} -x c++ ${compile_options} -E -dM -
+ OUTPUT_VARIABLE string_defines
+ )
+
+ if(string_defines MATCHES "#define __GLIBCXX__")
+ # Allow -D_GLIBCXX_USE_CXX11_ABI=ON/OFF as argument to cmake
+ if(DEFINED _GLIBCXX_USE_CXX11_ABI)
+ if(_GLIBCXX_USE_CXX11_ABI)
+ set(${result} libstdc++11 PARENT_SCOPE)
+ return()
+ else()
+ set(${result} libstdc++ PARENT_SCOPE)
+ return()
+ endif()
+ endif()
+
+ if(string_defines MATCHES "#define _GLIBCXX_USE_CXX11_ABI 1\n")
+ set(${result} libstdc++11 PARENT_SCOPE)
+ else()
+ # Either the compiler is missing the define because it is old, and so
+ # it can't use the new abi, or the compiler was configured to use the
+ # old abi by the user or distro (e.g. devtoolset on RHEL/CentOS)
+ set(${result} libstdc++ PARENT_SCOPE)
+ endif()
else()
- set(${result} libstdc++11 PARENT_SCOPE)
+ set(${result} libc++ PARENT_SCOPE)
endif()
endfunction()
-
function(conan_cmake_detect_vs_runtime result)
string(TOUPPER ${CMAKE_BUILD_TYPE} build_type)
set(variables CMAKE_CXX_FLAGS_${build_type} CMAKE_C_FLAGS_${build_type} CMAKE_CXX_FLAGS CMAKE_C_FLAGS)
foreach(variable ${variables})
- string(REPLACE " " ";" flags ${${variable}})
+ string(REPLACE " " ";" flags "${${variable}}")
foreach (flag ${flags})
if(${flag} STREQUAL "/MD" OR ${flag} STREQUAL "/MDd" OR ${flag} STREQUAL "/MT" OR ${flag} STREQUAL "/MTd")
string(SUBSTRING ${flag} 1 -1 runtime)
@@ -272,10 +336,12 @@ endfunction()
macro(parse_arguments)
- set(options BASIC_SETUP CMAKE_TARGETS UPDATE KEEP_RPATHS NO_OUTPUT_DIRS)
- set(oneValueArgs CONANFILE DEBUG_PROFILE RELEASE_PROFILE RELWITHDEBINFO_PROFILE MINSIZEREL_PROFILE PROFILE ARCH BUILD_TYPE)
- set(multiValueArgs REQUIRES OPTIONS IMPORTS SETTINGS BUILD CONAN_COMMAND)
- cmake_parse_arguments(ARGUMENTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
+ set(options BASIC_SETUP CMAKE_TARGETS UPDATE KEEP_RPATHS NO_LOAD NO_OUTPUT_DIRS OUTPUT_QUIET NO_IMPORTS)
+ set(oneValueArgs CONANFILE ARCH BUILD_TYPE INSTALL_FOLDER CONAN_COMMAND)
+ set(multiValueArgs DEBUG_PROFILE RELEASE_PROFILE RELWITHDEBINFO_PROFILE MINSIZEREL_PROFILE
+ PROFILE REQUIRES OPTIONS IMPORTS SETTINGS BUILD ENV GENERATORS PROFILE_AUTO
+ INSTALL_ARGS)
+ cmake_parse_arguments(ARGUMENTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
endmacro()
function(conan_cmake_install)
@@ -286,6 +352,12 @@ function(conan_cmake_install)
# cmake does not identify conan as command, even if it is +x and it is in the path
parse_arguments(${ARGV})
+ if(CONAN_CMAKE_MULTI)
+ set(ARGUMENTS_GENERATORS ${ARGUMENTS_GENERATORS} cmake_multi)
+ else()
+ set(ARGUMENTS_GENERATORS ${ARGUMENTS_GENERATORS} cmake)
+ endif()
+
set(CONAN_BUILD_POLICY "")
foreach(ARG ${ARGUMENTS_BUILD})
if(${ARG} STREQUAL "all")
@@ -305,37 +377,43 @@ function(conan_cmake_install)
set(CONANFILE ${CMAKE_CURRENT_SOURCE_DIR}/${ARGUMENTS_CONANFILE})
# A conan file has been specified - apply specified options as well if provided
foreach(ARG ${ARGUMENTS_OPTIONS})
- set(CONAN_OPTIONS ${CONAN_OPTIONS} -o ${ARG})
+ set(CONAN_OPTIONS ${CONAN_OPTIONS} -o=${ARG})
endforeach()
else()
set(CONANFILE ".")
endif()
- if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND ARGUMENTS_DEBUG_PROFILE)
- set(settings -pr ${ARGUMENTS_DEBUG_PROFILE})
- endif()
- if(CMAKE_BUILD_TYPE STREQUAL "Release" AND ARGUMENTS_RELEASE_PROFILE)
- set(settings -pr ${ARGUMENTS_RELEASE_PROFILE})
- endif()
- if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" AND ARGUMENTS_RELWITHDEBINFO_PROFILE)
- set(settings -pr ${ARGUMENTS_RELWITHDEBINFO_PROFILE})
- endif()
- if(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel" AND ARGUMENTS_MINSIZEREL_PROFILE)
- set(settings -pr ${ARGUMENTS_MINSIZEREL_PROFILE})
- endif()
- if(ARGUMENTS_PROFILE)
- set(settings -pr ${ARGUMENTS_PROFILE})
- endif()
if(ARGUMENTS_UPDATE)
set(CONAN_INSTALL_UPDATE --update)
endif()
- set(conan_args install ${CONANFILE} ${settings} ${CONAN_BUILD_POLICY} ${CONAN_INSTALL_UPDATE} ${CONAN_OPTIONS})
+ if(ARGUMENTS_NO_IMPORTS)
+ set(CONAN_INSTALL_NO_IMPORTS --no-imports)
+ endif()
+ set(CONAN_INSTALL_FOLDER "")
+ if(ARGUMENTS_INSTALL_FOLDER)
+ set(CONAN_INSTALL_FOLDER -if=${ARGUMENTS_INSTALL_FOLDER})
+ endif()
+ foreach(ARG ${ARGUMENTS_GENERATORS})
+ set(CONAN_GENERATORS ${CONAN_GENERATORS} -g=${ARG})
+ endforeach()
+ foreach(ARG ${ARGUMENTS_ENV})
+ set(CONAN_ENV_VARS ${CONAN_ENV_VARS} -e=${ARG})
+ endforeach()
+ set(conan_args install ${CONANFILE} ${settings} ${CONAN_ENV_VARS} ${CONAN_GENERATORS} ${CONAN_BUILD_POLICY} ${CONAN_INSTALL_UPDATE} ${CONAN_INSTALL_NO_IMPORTS} ${CONAN_OPTIONS} ${CONAN_INSTALL_FOLDER} ${ARGUMENTS_INSTALL_ARGS})
string (REPLACE ";" " " _conan_args "${conan_args}")
message(STATUS "Conan executing: ${conan_command} ${_conan_args}")
- execute_process(COMMAND ${conan_command} ${conan_args}
- RESULT_VARIABLE return_code
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ if(ARGUMENTS_OUTPUT_QUIET)
+ execute_process(COMMAND ${conan_command} ${conan_args}
+ RESULT_VARIABLE return_code
+ OUTPUT_VARIABLE conan_output
+ ERROR_VARIABLE conan_output
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ else()
+ execute_process(COMMAND ${conan_command} ${conan_args}
+ RESULT_VARIABLE return_code
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ endif()
if(NOT "${return_code}" STREQUAL "0")
message(FATAL_ERROR "Conan install failed='${return_code}'")
@@ -347,9 +425,10 @@ endfunction()
function(conan_cmake_setup_conanfile)
parse_arguments(${ARGV})
if(ARGUMENTS_CONANFILE)
+ get_filename_component(_CONANFILE_NAME ${ARGUMENTS_CONANFILE} NAME)
# configure_file will make sure cmake re-runs when conanfile is updated
- configure_file(${ARGUMENTS_CONANFILE} ${ARGUMENTS_CONANFILE}.junk)
- file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${ARGUMENTS_CONANFILE}.junk)
+ configure_file(${ARGUMENTS_CONANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${_CONANFILE_NAME}.junk)
+ file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${_CONANFILE_NAME}.junk)
else()
conan_cmake_generate_conanfile(${ARGV})
endif()
@@ -385,11 +464,16 @@ macro(conan_load_buildinfo)
else()
set(_CONANBUILDINFO conanbuildinfo.cmake)
endif()
+ if(ARGUMENTS_INSTALL_FOLDER)
+ set(_CONANBUILDINFOFOLDER ${ARGUMENTS_INSTALL_FOLDER})
+ else()
+ set(_CONANBUILDINFOFOLDER ${CMAKE_CURRENT_BINARY_DIR})
+ endif()
# Checks for the existence of conanbuildinfo.cmake, and loads it
# important that it is macro, so variables defined at parent scope
- if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${_CONANBUILDINFO}")
+ if(EXISTS "${_CONANBUILDINFOFOLDER}/${_CONANBUILDINFO}")
message(STATUS "Conan: Loading ${_CONANBUILDINFO}")
- include(${CMAKE_CURRENT_BINARY_DIR}/${_CONANBUILDINFO})
+ include(${_CONANBUILDINFOFOLDER}/${_CONANBUILDINFO})
else()
message(FATAL_ERROR "${_CONANBUILDINFO} doesn't exist in ${CMAKE_CURRENT_BINARY_DIR}")
endif()
@@ -399,16 +483,19 @@ endmacro()
macro(conan_cmake_run)
parse_arguments(${ARGV})
- if(CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE AND NOT CONAN_EXPORTED)
+ if(CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE AND NOT CONAN_EXPORTED
+ AND NOT ARGUMENTS_BUILD_TYPE)
set(CONAN_CMAKE_MULTI ON)
message(STATUS "Conan: Using cmake-multi generator")
else()
set(CONAN_CMAKE_MULTI OFF)
endif()
+
if(NOT CONAN_EXPORTED)
conan_cmake_setup_conanfile(${ARGV})
if(CONAN_CMAKE_MULTI)
foreach(CMAKE_BUILD_TYPE "Release" "Debug")
+ set(ENV{CONAN_IMPORT_PATH} ${CMAKE_BUILD_TYPE})
conan_cmake_settings(settings ${ARGV})
conan_cmake_install(SETTINGS ${settings} ${ARGV})
endforeach()
@@ -419,7 +506,9 @@ macro(conan_cmake_run)
endif()
endif()
- conan_load_buildinfo()
+ if (NOT ARGUMENTS_NO_LOAD)
+ conan_load_buildinfo()
+ endif()
if(ARGUMENTS_BASIC_SETUP)
foreach(_option CMAKE_TARGETS KEEP_RPATHS NO_OUTPUT_DIRS)
@@ -434,3 +523,52 @@ macro(conan_cmake_run)
conan_basic_setup(${_setup_options})
endif()
endmacro()
+
+macro(conan_check)
+ # Checks conan availability in PATH
+ # Arguments REQUIRED and VERSION are optional
+ # Example usage:
+ # conan_check(VERSION 1.0.0 REQUIRED)
+ message(STATUS "Conan: checking conan executable in path")
+ set(options REQUIRED)
+ set(oneValueArgs VERSION)
+ cmake_parse_arguments(CONAN "${options}" "${oneValueArgs}" "" ${ARGN})
+
+ find_program(CONAN_CMD conan)
+ if(NOT CONAN_CMD AND CONAN_REQUIRED)
+ message(FATAL_ERROR "Conan executable not found!")
+ endif()
+ message(STATUS "Conan: Found program ${CONAN_CMD}")
+ execute_process(COMMAND ${CONAN_CMD} --version
+ OUTPUT_VARIABLE CONAN_VERSION_OUTPUT
+ ERROR_VARIABLE CONAN_VERSION_OUTPUT)
+ message(STATUS "Conan: Version found ${CONAN_VERSION_OUTPUT}")
+
+ if(DEFINED CONAN_VERSION)
+ string(REGEX MATCH ".*Conan version ([0-9]+\.[0-9]+\.[0-9]+)" FOO
+ "${CONAN_VERSION_OUTPUT}")
+ if(${CMAKE_MATCH_1} VERSION_LESS ${CONAN_VERSION})
+ message(FATAL_ERROR "Conan outdated. Installed: ${CMAKE_MATCH_1}, \
+ required: ${CONAN_VERSION}. Consider updating via 'pip \
+ install conan==${CONAN_VERSION}'.")
+ endif()
+ endif()
+endmacro()
+
+macro(conan_add_remote)
+ # Adds a remote
+ # Arguments URL and NAME are required, INDEX is optional
+ # Example usage:
+ # conan_add_remote(NAME bincrafters INDEX 1
+ # URL https://api.bintray.com/conan/bincrafters/public-conan)
+ set(oneValueArgs URL NAME INDEX)
+ cmake_parse_arguments(CONAN "" "${oneValueArgs}" "" ${ARGN})
+
+ if(DEFINED CONAN_INDEX)
+ set(CONAN_INDEX_ARG "-i ${CONAN_INDEX}")
+ endif()
+
+ message(STATUS "Conan: Adding ${CONAN_NAME} remote repository (${CONAN_URL})")
+ execute_process(COMMAND ${CONAN_CMD} remote add ${CONAN_NAME} ${CONAN_URL}
+ ${CONAN_INDEX_ARG} -f)
+endmacro()
diff --git a/debian/changelog b/debian/changelog
index c810268..9764f81 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,18 @@
+libvbz-hdf-plugin (1.0.2-1) unstable; urgency=medium
+
+ * New upstream version
+ * Standards-Version: 4.6.1 (routine-update)
+ * Drop unnecessary dependency on build-essential.
+ * Apply multi-arch hints.
+ + libvbz-hdf-plugin-dev: Add Multi-Arch: same.
+ * Refresh use-packaged-streamvbyte.patch.
+ * Refresh fix-install-location.patch.
+ * Delete update-catch2.patch: applied upstream.
+ * d/rules: enable hardening.
+ * Add symbols tracking for libvbz-hdf-plugin0.
+
+ -- Étienne Mollier <emollier@debian.org> Sun, 03 Jul 2022 14:23:31 +0200
+
libvbz-hdf-plugin (1.0.1-3) unstable; urgency=medium
[ Steve Langasek ]
diff --git a/debian/control b/debian/control
index bdb016d..f30f5b5 100644
--- a/debian/control
+++ b/debian/control
@@ -1,16 +1,17 @@
Source: libvbz-hdf-plugin
Maintainer: Debian Med Packaging Team <debian-med-packaging@lists.alioth.debian.org>
-Uploaders: Andreas Tille <tille@debian.org>, Nilesh Patra <nilesh@debian.org>
+Uploaders: Andreas Tille <tille@debian.org>,
+ Nilesh Patra <nilesh@debian.org>,
+ Étienne Mollier <emollier@debian.org>
Section: science
Priority: optional
Build-Depends: debhelper-compat (= 13),
-# d-shlibs, # not possible since no static lib
cmake,
libzstd-dev,
libhdf5-dev,
libstreamvbyte-dev,
dh-exec
-Standards-Version: 4.6.0
+Standards-Version: 4.6.1
Vcs-Browser: https://salsa.debian.org/med-team/libvbz-hdf-plugin
Vcs-Git: https://salsa.debian.org/med-team/libvbz-hdf-plugin.git
Homepage: https://github.com/nanoporetech/vbz_compression/
@@ -41,6 +42,7 @@ Section: libdevel
Depends: libvbz-hdf-plugin0 (= ${binary:Version}),
${shlibs:Depends},
${misc:Depends}
+Multi-Arch: same
Description: VBZ compression plugin for nanopore signal data (devel)
VBZ Compression uses variable byte integer encoding to compress nanopore
signal data.
diff --git a/debian/libvbz-hdf-plugin0.symbols b/debian/libvbz-hdf-plugin0.symbols
new file mode 100644
index 0000000..613eef4
--- /dev/null
+++ b/debian/libvbz-hdf-plugin0.symbols
@@ -0,0 +1,33 @@
+libvbz_hdf_plugin.so.0 libvbz-hdf-plugin0 #MINVER#
+* Build-Depends-Package: libvbz-hdf-plugin-dev
+ H5PLget_plugin_info@Base 1.0.2
+ H5PLget_plugin_type@Base 1.0.2
+ (arch=any-amd64 arm64 mips64el ppc64el s390x alpha ia64 ppc64 sparc64 riscv64)_Z10vbz_filterjmPKjmPmPPv@Base 1.0.2
+ (arch=any-i386 armel armhf mipsel hppa m68k powerpc sh4)_Z10vbz_filterjjPKjjPjPPv@Base 1.0.2
+ _Z23streamvbyte_decode_halfPKhPjj@Base 1.0.2
+ _Z23streamvbyte_encode_halfPKjjPh@Base 1.0.2
+ (arch=any-amd64 arm64 mips64el ppc64el s390x alpha ia64 ppc64 sparc64 riscv64)_Z38vbz_max_streamvbyte_compressed_size_v0mj@Base 1.0.2
+ (arch=any-amd64 arm64 mips64el ppc64el s390x alpha ia64 ppc64 sparc64 riscv64)_Z38vbz_max_streamvbyte_compressed_size_v1mj@Base 1.0.2
+ (arch=any-i386 armel armhf mipsel hppa m68k powerpc sh4)_Z38vbz_max_streamvbyte_compressed_size_v0jj@Base 1.0.2
+ (arch=any-i386 armel armhf mipsel hppa m68k powerpc sh4)_Z38vbz_max_streamvbyte_compressed_size_v1jj@Base 1.0.2
+ _Z41vbz_delta_zig_zag_streamvbyte_compress_v0PKvjPvjib@Base 1.0.2
+ _Z41vbz_delta_zig_zag_streamvbyte_compress_v1PKvjPvjib@Base 1.0.2
+ _Z43vbz_delta_zig_zag_streamvbyte_decompress_v0PKvjPvjib@Base 1.0.2
+ _Z43vbz_delta_zig_zag_streamvbyte_decompress_v1PKvjPvjib@Base 1.0.2
+ (arch=any-amd64)_ZN19StreamVByteWorkerV0IsLb1EE10decompressEN3gsl4spanIKcEENS2_IcEE@Base 1.0.2
+ _ZNKSt5ctypeIcE8do_widenEc@Base 1.0.2
+ streamvbyte_decode@Base 1.0.2
+ streamvbyte_encode@Base 1.0.2
+ vbz_compress@Base 1.0.2
+ vbz_compress_sized@Base 1.0.2
+ vbz_decompress@Base 1.0.2
+ vbz_decompress_sized@Base 1.0.2
+ vbz_decompressed_size@Base 1.0.2
+ vbz_error_string@Base 1.0.2
+ vbz_is_error@Base 1.0.2
+ vbz_max_compressed_size@Base 1.0.2
+ vbz_plugin_info@Base 1.0.2
+ zigzag_decode@Base 1.0.2
+ zigzag_delta_decode@Base 1.0.2
+ zigzag_delta_encode@Base 1.0.2
+ zigzag_encode@Base 1.0.2
diff --git a/debian/patches/fix-install-location.patch b/debian/patches/fix-install-location.patch
index e6a3177..bf3d071 100644
--- a/debian/patches/fix-install-location.patch
+++ b/debian/patches/fix-install-location.patch
@@ -2,9 +2,9 @@ Description: Fix install location for .so
Author: Nilesh Patra <nilesh@debian.org>
Forwarded: not-needed
Last-Update: 2021-05-22
---- a/vbz_plugin/CMakeLists.txt
-+++ b/vbz_plugin/CMakeLists.txt
-@@ -62,7 +62,7 @@
+--- libvbz-hdf-plugin.orig/vbz_plugin/CMakeLists.txt
++++ libvbz-hdf-plugin/vbz_plugin/CMakeLists.txt
+@@ -72,7 +72,7 @@
set(VBZ_PLUGIN_COMPONENT COMPONENT hdf_plugin)
endif()
diff --git a/debian/patches/series b/debian/patches/series
index 2d66ccd..06ebda1 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,4 +1,3 @@
use-packaged-streamvbyte.patch
fix-install-location.patch
soversion.patch
-update-catch2.patch
diff --git a/debian/patches/update-catch2.patch b/debian/patches/update-catch2.patch
deleted file mode 100644
index 072fc69..0000000
--- a/debian/patches/update-catch2.patch
+++ /dev/null
@@ -1,9997 +0,0 @@
-Description: import catch2 version 2.13.8 to fix build failure with glibc 2.34
-Author: Steve Langasek <steve.langasek@ubuntu.com>
-Last-Update: 2022-04-12
-Forwarded: no
-Bug-Debian: https://bugs.debian.org/1009620
-
-Index: libvbz-hdf-plugin-1.0.1/third_party/catch2/catch.hpp
-===================================================================
---- libvbz-hdf-plugin-1.0.1.orig/third_party/catch2/catch.hpp
-+++ libvbz-hdf-plugin-1.0.1/third_party/catch2/catch.hpp
-@@ -1,9 +1,9 @@
- /*
-- * Catch v2.5.0
-- * Generated: 2018-11-26 20:46:12.165372
-+ * Catch v2.13.8
-+ * Generated: 2022-01-03 21:20:09.589503
- * ----------------------------------------------------------
- * This file has been merged from multiple headers. Please don't edit it directly
-- * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved.
-+ * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved.
- *
- * Distributed under the Boost Software License, Version 1.0. (See accompanying
- * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-@@ -14,8 +14,8 @@
-
-
- #define CATCH_VERSION_MAJOR 2
--#define CATCH_VERSION_MINOR 5
--#define CATCH_VERSION_PATCH 0
-+#define CATCH_VERSION_MINOR 13
-+#define CATCH_VERSION_PATCH 8
-
- #ifdef __clang__
- # pragma clang system_header
-@@ -36,10 +36,11 @@
- # pragma clang diagnostic ignored "-Wcovered-switch-default"
- # endif
- #elif defined __GNUC__
-- // GCC likes to warn on REQUIREs, and we cannot suppress them
-- // locally because g++'s support for _Pragma is lacking in older,
-- // still supported, versions
--# pragma GCC diagnostic ignored "-Wparentheses"
-+ // Because REQUIREs trigger GCC's -Wparentheses, and because still
-+ // supported version of g++ have only buggy support for _Pragmas,
-+ // Wparentheses have to be suppressed globally.
-+# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
-+
- # pragma GCC diagnostic push
- # pragma GCC diagnostic ignored "-Wunused-variable"
- # pragma GCC diagnostic ignored "-Wpadded"
-@@ -65,13 +66,16 @@
- #if !defined(CATCH_CONFIG_IMPL_ONLY)
- // start catch_platform.h
-
-+// See e.g.:
-+// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
- #ifdef __APPLE__
--# include <TargetConditionals.h>
--# if TARGET_OS_OSX == 1
--# define CATCH_PLATFORM_MAC
--# elif TARGET_OS_IPHONE == 1
--# define CATCH_PLATFORM_IPHONE
--# endif
-+# include <TargetConditionals.h>
-+# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
-+ (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
-+# define CATCH_PLATFORM_MAC
-+# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
-+# define CATCH_PLATFORM_IPHONE
-+# endif
-
- #elif defined(linux) || defined(__linux) || defined(__linux__)
- # define CATCH_PLATFORM_LINUX
-@@ -131,30 +135,51 @@
-
- #endif
-
--#if defined(CATCH_CPP17_OR_GREATER)
--# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
-+// Only GCC compiler should be used in this block, so other compilers trying to
-+// mask themselves as GCC should be ignored.
-+#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
-+# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
-+# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
-+
-+# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
-+
- #endif
-
--#ifdef __clang__
-+#if defined(__clang__)
-
--# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-- _Pragma( "clang diagnostic push" ) \
-- _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
-- _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
--# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
-- _Pragma( "clang diagnostic pop" )
--
--# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
-- _Pragma( "clang diagnostic push" ) \
-- _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
--# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
-- _Pragma( "clang diagnostic pop" )
--
--# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
-- _Pragma( "clang diagnostic push" ) \
-- _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
--# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
-- _Pragma( "clang diagnostic pop" )
-+# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
-+# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
-+
-+// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
-+// which results in calls to destructors being emitted for each temporary,
-+// without a matching initialization. In practice, this can result in something
-+// like `std::string::~string` being called on an uninitialized value.
-+//
-+// For example, this code will likely segfault under IBM XL:
-+// ```
-+// REQUIRE(std::string("12") + "34" == "1234")
-+// ```
-+//
-+// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
-+# if !defined(__ibmxl__) && !defined(__CUDACC__)
-+# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
-+# endif
-+
-+# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-+ _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
-+ _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
-+
-+# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
-+ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
-+
-+# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
-+ _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
-+
-+# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
-+ _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
-+
-+# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
-+ _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
-
- #endif // __clang__
-
-@@ -179,6 +204,7 @@
- // Android somehow still does not support std::to_string
- #if defined(__ANDROID__)
- # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
-+# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
- #endif
-
- ////////////////////////////////////////////////////////////////////////////////
-@@ -203,20 +229,16 @@
- // some versions of cygwin (most) do not support std::to_string. Use the libstd check.
- // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
- # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
-- && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
-+ && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
-
--# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
-+# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
-
- # endif
- #endif // __CYGWIN__
-
- ////////////////////////////////////////////////////////////////////////////////
- // Visual C++
--#ifdef _MSC_VER
--
--# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
--# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
--# endif
-+#if defined(_MSC_VER)
-
- // Universal Windows platform does not support SEH
- // Or console colours (or console at all...)
-@@ -226,13 +248,25 @@
- # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
- # endif
-
-+# if !defined(__clang__) // Handle Clang masquerading for msvc
-+
- // MSVC traditional preprocessor needs some workaround for __VA_ARGS__
- // _MSVC_TRADITIONAL == 0 means new conformant preprocessor
- // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
--# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
--# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
--# endif
-+# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
-+# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+# endif // MSVC_TRADITIONAL
-+
-+// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop`
-+# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
-+# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
-+# endif // __clang__
-+
-+#endif // _MSC_VER
-
-+#if defined(_REENTRANT) || defined(_MSC_VER)
-+// Enable async processing, as -pthread is specified or no additional linking is required
-+# define CATCH_INTERNAL_CONFIG_USE_ASYNC
- #endif // _MSC_VER
-
- ////////////////////////////////////////////////////////////////////////////////
-@@ -265,30 +299,56 @@
- #endif
-
- ////////////////////////////////////////////////////////////////////////////////
--// Check if string_view is available and usable
--// The check is split apart to work around v140 (VS2015) preprocessor issue...
--#if defined(__has_include)
--#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
--# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
-+
-+// RTX is a special version of Windows that is real time.
-+// This means that it is detected as Windows, but does not provide
-+// the same set of capabilities as real Windows does.
-+#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
-+ #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
-+ #define CATCH_INTERNAL_CONFIG_NO_ASYNC
-+ #define CATCH_CONFIG_COLOUR_NONE
- #endif
-+
-+#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
-+#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
- #endif
-
--////////////////////////////////////////////////////////////////////////////////
--// Check if variant is available and usable
-+// Various stdlib support checks that require __has_include
- #if defined(__has_include)
--# if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
--# if defined(__clang__) && (__clang_major__ < 8)
-- // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
-- // fix should be in clang 8, workaround in libstdc++ 8.2
--# include <ciso646>
--# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
--# define CATCH_CONFIG_NO_CPP17_VARIANT
--# else
--# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
--# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
--# endif // defined(__clang__) && (__clang_major__ < 8)
--# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
--#endif // __has_include
-+ // Check if string_view is available and usable
-+ #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
-+ # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
-+ #endif
-+
-+ // Check if optional is available and usable
-+ # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
-+ # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
-+ # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
-+
-+ // Check if byte is available and usable
-+ # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
-+ # include <cstddef>
-+ # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
-+ # define CATCH_INTERNAL_CONFIG_CPP17_BYTE
-+ # endif
-+ # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
-+
-+ // Check if variant is available and usable
-+ # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
-+ # if defined(__clang__) && (__clang_major__ < 8)
-+ // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
-+ // fix should be in clang 8, workaround in libstdc++ 8.2
-+ # include <ciso646>
-+ # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
-+ # define CATCH_CONFIG_NO_CPP17_VARIANT
-+ # else
-+ # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
-+ # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
-+ # else
-+ # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
-+ # endif // defined(__clang__) && (__clang_major__ < 8)
-+ # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
-+#endif // defined(__has_include)
-
- #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
- # define CATCH_CONFIG_COUNTER
-@@ -309,8 +369,8 @@
- # define CATCH_CONFIG_CPP11_TO_STRING
- #endif
-
--#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
--# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
-+#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
-+# define CATCH_CONFIG_CPP17_OPTIONAL
- #endif
-
- #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
-@@ -321,6 +381,10 @@
- # define CATCH_CONFIG_CPP17_VARIANT
- #endif
-
-+#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
-+# define CATCH_CONFIG_CPP17_BYTE
-+#endif
-+
- #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
- # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
- #endif
-@@ -337,17 +401,53 @@
- # define CATCH_CONFIG_POLYFILL_ISNAN
- #endif
-
-+#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
-+# define CATCH_CONFIG_USE_ASYNC
-+#endif
-+
-+#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE)
-+# define CATCH_CONFIG_ANDROID_LOGWRITE
-+#endif
-+
-+#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
-+# define CATCH_CONFIG_GLOBAL_NEXTAFTER
-+#endif
-+
-+// Even if we do not think the compiler has that warning, we still have
-+// to provide a macro that can be used by the code.
-+#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
-+# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
-+#endif
-+#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
-+# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-+#endif
- #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
- # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
--# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
- #endif
- #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
- # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
--# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
- #endif
- #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
- # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
--# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
-+#endif
-+#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
-+# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
-+#endif
-+
-+// The goal of this macro is to avoid evaluation of the arguments, but
-+// still have the compiler warn on problems inside...
-+#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
-+# define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
-+#endif
-+
-+#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
-+# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
-+#elif defined(__clang__) && (__clang_major__ < 5)
-+# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
-+#endif
-+
-+#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
-+# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
- #endif
-
- #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
-@@ -407,12 +507,12 @@
- line( _line )
- {}
-
-- SourceLineInfo( SourceLineInfo const& other ) = default;
-- SourceLineInfo( SourceLineInfo && ) = default;
-- SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
-- SourceLineInfo& operator = ( SourceLineInfo && ) = default;
-+ SourceLineInfo( SourceLineInfo const& other ) = default;
-+ SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
-+ SourceLineInfo( SourceLineInfo&& ) noexcept = default;
-+ SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
-
-- bool empty() const noexcept;
-+ bool empty() const noexcept { return file[0] == '\0'; }
- bool operator == ( SourceLineInfo const& other ) const noexcept;
- bool operator < ( SourceLineInfo const& other ) const noexcept;
-
-@@ -453,9 +553,10 @@
- } // end namespace Catch
-
- #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-
- // end catch_tag_alias_autoregistrar.h
- // start catch_test_registry.h
-@@ -463,7 +564,6 @@
- // start catch_interfaces_testcase.h
-
- #include <vector>
--#include <memory>
-
- namespace Catch {
-
-@@ -474,8 +574,6 @@
- virtual ~ITestInvoker();
- };
-
-- using ITestCasePtr = std::shared_ptr<ITestInvoker>;
--
- class TestCase;
- struct IConfig;
-
-@@ -485,6 +583,7 @@
- virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
- };
-
-+ bool isThrowSafe( TestCase const& testCase, IConfig const& config );
- bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
- std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
- std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
-@@ -497,55 +596,30 @@
- #include <cstddef>
- #include <string>
- #include <iosfwd>
-+#include <cassert>
-
- namespace Catch {
-
-- class StringData;
--
- /// A non-owning string class (similar to the forthcoming std::string_view)
- /// Note that, because a StringRef may be a substring of another string,
-- /// it may not be null terminated. c_str() must return a null terminated
-- /// string, however, and so the StringRef will internally take ownership
-- /// (taking a copy), if necessary. In theory this ownership is not externally
-- /// visible - but it does mean (substring) StringRefs should not be shared between
-- /// threads.
-+ /// it may not be null terminated.
- class StringRef {
- public:
- using size_type = std::size_t;
-+ using const_iterator = const char*;
-
- private:
-- friend struct StringRefTestAccess;
--
-- char const* m_start;
-- size_type m_size;
--
-- char* m_data = nullptr;
--
-- void takeOwnership();
--
- static constexpr char const* const s_empty = "";
-
-- public: // construction/ assignment
-- StringRef() noexcept
-- : StringRef( s_empty, 0 )
-- {}
-+ char const* m_start = s_empty;
-+ size_type m_size = 0;
-
-- StringRef( StringRef const& other ) noexcept
-- : m_start( other.m_start ),
-- m_size( other.m_size )
-- {}
--
-- StringRef( StringRef&& other ) noexcept
-- : m_start( other.m_start ),
-- m_size( other.m_size ),
-- m_data( other.m_data )
-- {
-- other.m_data = nullptr;
-- }
-+ public: // construction
-+ constexpr StringRef() noexcept = default;
-
- StringRef( char const* rawChars ) noexcept;
-
-- StringRef( char const* rawChars, size_type size ) noexcept
-+ constexpr StringRef( char const* rawChars, size_type size ) noexcept
- : m_start( rawChars ),
- m_size( size )
- {}
-@@ -555,99 +629,64 @@
- m_size( stdString.size() )
- {}
-
-- ~StringRef() noexcept {
-- delete[] m_data;
-- }
--
-- auto operator = ( StringRef const &other ) noexcept -> StringRef& {
-- delete[] m_data;
-- m_data = nullptr;
-- m_start = other.m_start;
-- m_size = other.m_size;
-- return *this;
-+ explicit operator std::string() const {
-+ return std::string(m_start, m_size);
- }
-
-- operator std::string() const;
--
-- void swap( StringRef& other ) noexcept;
--
- public: // operators
- auto operator == ( StringRef const& other ) const noexcept -> bool;
-- auto operator != ( StringRef const& other ) const noexcept -> bool;
-+ auto operator != (StringRef const& other) const noexcept -> bool {
-+ return !(*this == other);
-+ }
-
-- auto operator[] ( size_type index ) const noexcept -> char;
-+ auto operator[] ( size_type index ) const noexcept -> char {
-+ assert(index < m_size);
-+ return m_start[index];
-+ }
-
- public: // named queries
-- auto empty() const noexcept -> bool {
-+ constexpr auto empty() const noexcept -> bool {
- return m_size == 0;
- }
-- auto size() const noexcept -> size_type {
-+ constexpr auto size() const noexcept -> size_type {
- return m_size;
- }
-
-- auto numberOfCharacters() const noexcept -> size_type;
-+ // Returns the current start pointer. If the StringRef is not
-+ // null-terminated, throws std::domain_exception
- auto c_str() const -> char const*;
-
- public: // substrings and searches
-- auto substr( size_type start, size_type size ) const noexcept -> StringRef;
-+ // Returns a substring of [start, start + length).
-+ // If start + length > size(), then the substring is [start, size()).
-+ // If start > size(), then the substring is empty.
-+ auto substr( size_type start, size_type length ) const noexcept -> StringRef;
-
-- // Returns the current start pointer.
-- // Note that the pointer can change when if the StringRef is a substring
-- auto currentData() const noexcept -> char const*;
-+ // Returns the current start pointer. May not be null-terminated.
-+ auto data() const noexcept -> char const*;
-
-- private: // ownership queries - may not be consistent between calls
-- auto isOwned() const noexcept -> bool;
-- auto isSubstring() const noexcept -> bool;
-- };
-+ constexpr auto isNullTerminated() const noexcept -> bool {
-+ return m_start[m_size] == '\0';
-+ }
-
-- auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
-- auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
-- auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
-+ public: // iterators
-+ constexpr const_iterator begin() const { return m_start; }
-+ constexpr const_iterator end() const { return m_start + m_size; }
-+ };
-
- auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
- auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
-
-- inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
-+ constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
- return StringRef( rawChars, size );
- }
--
- } // namespace Catch
-
--inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
-+constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
- return Catch::StringRef( rawChars, size );
- }
-
- // end catch_stringref.h
--// start catch_type_traits.hpp
--
--
--namespace Catch{
--
--#ifdef CATCH_CPP17_OR_GREATER
-- template <typename...>
-- inline constexpr auto is_unique = std::true_type{};
--
-- template <typename T, typename... Rest>
-- inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
-- (!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
-- >{};
--#else
--
--template <typename...>
--struct is_unique : std::true_type{};
--
--template <typename T0, typename T1, typename... Rest>
--struct is_unique<T0, T1, Rest...> : std::integral_constant
--<bool,
-- !std::is_same<T0, T1>::value
-- && is_unique<T0, Rest...>::value
-- && is_unique<T1, Rest...>::value
-->{};
--
--#endif
--}
--
--// end catch_type_traits.hpp
- // start catch_preprocessor.hpp
-
-
-@@ -699,21 +738,224 @@
- #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
- #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
- #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
-+#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
-+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
-+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
-+#else
-+// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
-+#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
-+#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
-+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
-+#endif
-+
-+#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
-+#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
-
- #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
-
--#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__)
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
--#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__
--#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
-+#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
-+#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
-+#else
-+#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))
-+#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
-+#endif
-+
-+#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
-+ CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
-+
-+#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
-+#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
-+#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
-+#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3)
-+#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4)
-+#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5)
-+#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6)
-+#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7)
-+#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8)
-+#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9)
-+#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)
-+
-+#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
-+
-+#define INTERNAL_CATCH_TYPE_GEN\
-+ template<typename...> struct TypeList {};\
-+ template<typename...Ts>\
-+ constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
-+ template<template<typename...> class...> struct TemplateTypeList{};\
-+ template<template<typename...> class...Cs>\
-+ constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
-+ template<typename...>\
-+ struct append;\
-+ template<typename...>\
-+ struct rewrap;\
-+ template<template<typename...> class, typename...>\
-+ struct create;\
-+ template<template<typename...> class, typename>\
-+ struct convert;\
-+ \
-+ template<typename T> \
-+ struct append<T> { using type = T; };\
-+ template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
-+ struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
-+ template< template<typename...> class L1, typename...E1, typename...Rest>\
-+ struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
-+ \
-+ template< template<typename...> class Container, template<typename...> class List, typename...elems>\
-+ struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
-+ template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
-+ struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
-+ \
-+ template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
-+ struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
-+ template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
-+ struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
-+
-+#define INTERNAL_CATCH_NTTP_1(signature, ...)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
-+ constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
-+ template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
-+ template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
-+ constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
-+ \
-+ template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
-+ struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
-+ template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
-+ struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
-+ template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
-+ struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
-+
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
-+ static void TestName()
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
-+ static void TestName()
-+
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
-+ static void TestName()
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
-+ static void TestName()
-+
-+#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
-+ template<typename Type>\
-+ void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\
-+ {\
-+ Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
-+ }
-+
-+#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
-+ void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
-+ {\
-+ Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
-+ }
-+
-+#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
-+ template<typename Type>\
-+ void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
-+ {\
-+ Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
-+ }
-+
-+#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
-+ void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
-+ {\
-+ Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
-+ }
-+
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
-+ template<typename TestType> \
-+ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
-+ void test();\
-+ }
-+
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
-+ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
-+ void test();\
-+ }
-+
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
-+ template<typename TestType> \
-+ void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
-+ template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
-+ void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
-+
-+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+#define INTERNAL_CATCH_NTTP_0
-+#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0)
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)
-+#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)
-+#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)
-+#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)
- #else
--// MSVC is adding extra space and needs more calls to properly remove ()
--#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__
--#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__)
--#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
-+#define INTERNAL_CATCH_NTTP_0(signature)
-+#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__))
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))
-+#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))
-+#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))
-+#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))
-+#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))
-+#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))
- #endif
-
- // end catch_preprocessor.hpp
-+// start catch_meta.hpp
-+
-+
-+#include <type_traits>
-+
-+namespace Catch {
-+ template<typename T>
-+ struct always_false : std::false_type {};
-+
-+ template <typename> struct true_given : std::true_type {};
-+ struct is_callable_tester {
-+ template <typename Fun, typename... Args>
-+ true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int);
-+ template <typename...>
-+ std::false_type static test(...);
-+ };
-+
-+ template <typename T>
-+ struct is_callable;
-+
-+ template <typename Fun, typename... Args>
-+ struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
-+
-+#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
-+ // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
-+ // replaced with std::invoke_result here.
-+ template <typename Func, typename... U>
-+ using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
-+#else
-+ // Keep ::type here because we still support C++11
-+ template <typename Func, typename... U>
-+ using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U...)>::type>::type>::type;
-+#endif
-+
-+} // namespace Catch
-+
-+namespace mpl_{
-+ struct na;
-+}
-+
-+// end catch_meta.hpp
- namespace Catch {
-
- template<typename C>
-@@ -758,38 +1000,70 @@
- }; \
- } \
- void TestName::test()
-- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... ) \
-- template<typename TestType> \
-- static void TestName()
-- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \
-+ INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
- namespace{ \
-- template<typename TestType> \
-- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
-- void test(); \
-- }; \
-+ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
-+ INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
- } \
-- template<typename TestType> \
-- void TestName::test()
-+ } \
-+ INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
-+
-+ #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
-+ INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ )
-+ #else
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
-+ #endif
-+
-+ #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
-+ INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ )
-+ #else
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
-+ #endif
-+
-+ #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
-+ INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
-+ #else
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
-+ #endif
-+
-+ #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
-+ INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
-+ #else
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
-+ #endif
- #endif
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
- static void TestName(); \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- static void TestName()
- #define INTERNAL_CATCH_TESTCASE( ... ) \
-- INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
-+ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), __VA_ARGS__ )
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ \
- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
-@@ -797,88 +1071,273 @@
- }; \
- Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
- } \
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- void TestName::test()
- #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
-- INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
-+ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), ClassName, __VA_ARGS__ )
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-
- ///////////////////////////////////////////////////////////////////////////////
-- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-- template<typename TestType> \
-- static void TestFunc();\
-+ CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
-+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
-+ INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
- namespace {\
-+ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
-+ INTERNAL_CATCH_TYPE_GEN\
-+ INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
-+ INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
- template<typename...Types> \
- struct TestName{\
-- template<typename...Ts> \
-- TestName(Ts...names){\
-- CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
-+ TestName(){\
-+ int index = 0; \
-+ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
- using expander = int[];\
-- (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
-+ (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
- }\
- };\
-- INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \
-+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
-+ TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
-+ return 0;\
-+ }();\
- }\
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
-- template<typename TestType> \
-- static void TestFunc()
-+ }\
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
-+ INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
-
--#if defined(CATCH_CPP17_OR_GREATER)
--#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case");
-+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
-+ INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ )
- #else
--#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case");
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
- #endif
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
-- INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ )
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
-+ INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ )
- #else
-- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
-- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
- #endif
-
-- #define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\
-- static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
-- TestName<CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)>(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\
-- return 0;\
-- }();
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
-+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-+ CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
-+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
-+ template<typename TestType> static void TestFuncName(); \
-+ namespace {\
-+ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
-+ INTERNAL_CATCH_TYPE_GEN \
-+ INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
-+ template<typename... Types> \
-+ struct TestName { \
-+ void reg_tests() { \
-+ int index = 0; \
-+ using expander = int[]; \
-+ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
-+ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
-+ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
-+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\
-+ } \
-+ }; \
-+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
-+ using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
-+ TestInit t; \
-+ t.reg_tests(); \
-+ return 0; \
-+ }(); \
-+ } \
-+ } \
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
-+ template<typename TestType> \
-+ static void TestFuncName()
-+
-+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
-+ INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T,__VA_ARGS__)
-+#else
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T, __VA_ARGS__ ) )
-+#endif
-
-- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \
-+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
-+ INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__)
-+#else
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
-+#endif
-+
-+ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-- namespace{ \
-- template<typename TestType> \
-+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
-+ template<typename TestType> static void TestFunc(); \
-+ namespace {\
-+ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
-+ INTERNAL_CATCH_TYPE_GEN\
-+ template<typename... Types> \
-+ struct TestName { \
-+ void reg_tests() { \
-+ int index = 0; \
-+ using expander = int[]; \
-+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
-+ } \
-+ };\
-+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
-+ using TestInit = typename convert<TestName, TmplList>::type; \
-+ TestInit t; \
-+ t.reg_tests(); \
-+ return 0; \
-+ }(); \
-+ }}\
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
-+ template<typename TestType> \
-+ static void TestFunc()
-+
-+ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
-+ INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, TmplList )
-+
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
-+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-+ CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
-+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
-+ namespace {\
-+ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
-+ INTERNAL_CATCH_TYPE_GEN\
-+ INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
-+ INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
-+ INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
-+ template<typename...Types> \
-+ struct TestNameClass{\
-+ TestNameClass(){\
-+ int index = 0; \
-+ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
-+ using expander = int[];\
-+ (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
-+ }\
-+ };\
-+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
-+ TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
-+ return 0;\
-+ }();\
-+ }\
-+ }\
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
-+ INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
-+
-+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
-+ INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
-+#else
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
-+#endif
-+
-+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
-+ INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
-+#else
-+ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
-+#endif
-+
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
-+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-+ CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
-+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
-+ template<typename TestType> \
- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
- void test();\
- };\
-- template<typename...Types> \
-+ namespace {\
-+ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
-+ INTERNAL_CATCH_TYPE_GEN \
-+ INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
-+ template<typename...Types>\
- struct TestNameClass{\
-- template<typename...Ts> \
-- TestNameClass(Ts...names){\
-- CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
-+ void reg_tests(){\
-+ int index = 0;\
- using expander = int[];\
-- (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
-+ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
-+ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
-+ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
-+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \
- }\
- };\
-- INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\
-+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
-+ using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
-+ TestInit t;\
-+ t.reg_tests();\
-+ return 0;\
-+ }(); \
-+ }\
- }\
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- template<typename TestType> \
- void TestName<TestType>::test()
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
-- INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ )
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
-+ INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
- #else
-- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
-- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) )
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
- #endif
-
-+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
-+ INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
-+#else
-+ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
-+ INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
-+#endif
-+
-+ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
-+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
-+ template<typename TestType> \
-+ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
-+ void test();\
-+ };\
-+ namespace {\
-+ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
-+ INTERNAL_CATCH_TYPE_GEN\
-+ template<typename...Types>\
-+ struct TestNameClass{\
-+ void reg_tests(){\
-+ int index = 0;\
-+ using expander = int[];\
-+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
-+ }\
-+ };\
-+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
-+ using TestInit = typename convert<TestNameClass, TmplList>::type;\
-+ TestInit t;\
-+ t.reg_tests();\
-+ return 0;\
-+ }(); \
-+ }}\
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
-+ template<typename TestType> \
-+ void TestName<TestType>::test()
-+
-+#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
-+ INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, TmplList )
-+
- // end catch_test_registry.h
- // start catch_capture.hpp
-
-@@ -978,7 +1437,7 @@
-
- auto makeStream( StringRef const &filename ) -> IStream const*;
-
-- class ReusableStringStream {
-+ class ReusableStringStream : NonCopyable {
- std::size_t m_index;
- std::ostream* m_oss;
- public:
-@@ -997,6 +1456,42 @@
- }
-
- // end catch_stream.h
-+// start catch_interfaces_enum_values_registry.h
-+
-+#include <vector>
-+
-+namespace Catch {
-+
-+ namespace Detail {
-+ struct EnumInfo {
-+ StringRef m_name;
-+ std::vector<std::pair<int, StringRef>> m_values;
-+
-+ ~EnumInfo();
-+
-+ StringRef lookup( int value ) const;
-+ };
-+ } // namespace Detail
-+
-+ struct IMutableEnumValuesRegistry {
-+ virtual ~IMutableEnumValuesRegistry();
-+
-+ virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
-+
-+ template<typename E>
-+ Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
-+ static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
-+ std::vector<int> intValues;
-+ intValues.reserve( values.size() );
-+ for( auto enumValue : values )
-+ intValues.push_back( static_cast<int>( enumValue ) );
-+ return registerEnum( enumName, allEnums, intValues );
-+ }
-+ };
-+
-+} // Catch
-+
-+// end catch_interfaces_enum_values_registry.h
-
- #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
- #include <string_view>
-@@ -1067,9 +1562,9 @@
-
- template<typename T>
- class IsStreamInsertable {
-- template<typename SS, typename TT>
-+ template<typename Stream, typename U>
- static auto test(int)
-- -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
-+ -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
-
- template<typename, typename>
- static auto test(...)->std::false_type;
-@@ -1231,6 +1726,12 @@
- }
- };
-
-+#if defined(CATCH_CONFIG_CPP17_BYTE)
-+ template<>
-+ struct StringMaker<std::byte> {
-+ static std::string convert(std::byte value);
-+ };
-+#endif // defined(CATCH_CONFIG_CPP17_BYTE)
- template<>
- struct StringMaker<int> {
- static std::string convert(int value);
-@@ -1282,10 +1783,13 @@
- template<>
- struct StringMaker<float> {
- static std::string convert(float value);
-+ static int precision;
- };
-+
- template<>
- struct StringMaker<double> {
- static std::string convert(double value);
-+ static int precision;
- };
-
- template <typename T>
-@@ -1321,8 +1825,8 @@
- #endif
-
- namespace Detail {
-- template<typename InputIterator>
-- std::string rangeToString(InputIterator first, InputIterator last) {
-+ template<typename InputIterator, typename Sentinel = InputIterator>
-+ std::string rangeToString(InputIterator first, Sentinel last) {
- ReusableStringStream rss;
- rss << "{ ";
- if (first != last) {
-@@ -1370,6 +1874,7 @@
- # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
- # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
- # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
-+# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
- #endif
-
- // Separate std::pair specialization
-@@ -1391,6 +1896,24 @@
- }
- #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
-
-+#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
-+#include <optional>
-+namespace Catch {
-+ template<typename T>
-+ struct StringMaker<std::optional<T> > {
-+ static std::string convert(const std::optional<T>& optional) {
-+ ReusableStringStream rss;
-+ if (optional.has_value()) {
-+ rss << ::Catch::Detail::stringify(*optional);
-+ } else {
-+ rss << "{ }";
-+ }
-+ return rss.str();
-+ }
-+ };
-+}
-+#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
-+
- // Separate std::tuple specialization
- #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
- #include <tuple>
-@@ -1461,20 +1984,27 @@
- #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
-
- namespace Catch {
-- struct not_this_one {}; // Tag type for detecting which begin/ end are being selected
--
-- // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace
-+ // Import begin/ end from std here
- using std::begin;
- using std::end;
-
-- not_this_one begin( ... );
-- not_this_one end( ... );
-+ namespace detail {
-+ template <typename...>
-+ struct void_type {
-+ using type = void;
-+ };
-+
-+ template <typename T, typename = void>
-+ struct is_range_impl : std::false_type {
-+ };
-+
-+ template <typename T>
-+ struct is_range_impl<T, typename void_type<decltype(begin(std::declval<T>()))>::type> : std::true_type {
-+ };
-+ } // namespace detail
-
- template <typename T>
-- struct is_range {
-- static const bool value =
-- !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value &&
-- !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
-+ struct is_range : detail::is_range_impl<T> {
- };
-
- #if defined(_MANAGED) // Managed types are never ranges
-@@ -1639,6 +2169,18 @@
- }
- #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
-
-+#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
-+namespace Catch { \
-+ template<> struct StringMaker<enumName> { \
-+ static std::string convert( enumName value ) { \
-+ static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
-+ return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
-+ } \
-+ }; \
-+}
-+
-+#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
-+
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
-@@ -1652,6 +2194,7 @@
- #pragma warning(disable:4018) // more "signed/unsigned mismatch"
- #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
- #pragma warning(disable:4180) // qualifier applied to function type has no meaning
-+#pragma warning(disable:4800) // Forcing result to true or false
- #endif
-
- namespace Catch {
-@@ -1695,6 +2238,62 @@
- m_op( op ),
- m_rhs( rhs )
- {}
-+
-+ template<typename T>
-+ auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<T>::value,
-+ "chained comparisons are not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-+
-+ template<typename T>
-+ auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<T>::value,
-+ "chained comparisons are not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-+
-+ template<typename T>
-+ auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<T>::value,
-+ "chained comparisons are not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-+
-+ template<typename T>
-+ auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<T>::value,
-+ "chained comparisons are not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-+
-+ template<typename T>
-+ auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<T>::value,
-+ "chained comparisons are not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-+
-+ template<typename T>
-+ auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<T>::value,
-+ "chained comparisons are not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-+
-+ template<typename T>
-+ auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<T>::value,
-+ "chained comparisons are not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-+
-+ template<typename T>
-+ auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<T>::value,
-+ "chained comparisons are not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
- };
-
- template<typename LhsT>
-@@ -1707,7 +2306,7 @@
-
- public:
- explicit UnaryExpr( LhsT lhs )
-- : ITransientExpression{ false, lhs ? true : false },
-+ : ITransientExpression{ false, static_cast<bool>(lhs) },
- m_lhs( lhs )
- {}
- };
-@@ -1773,6 +2372,32 @@
- auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
- return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
- }
-+ template <typename RhsT>
-+ auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
-+ return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs };
-+ }
-+ template <typename RhsT>
-+ auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
-+ return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs };
-+ }
-+ template <typename RhsT>
-+ auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
-+ return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs };
-+ }
-+
-+ template<typename RhsT>
-+ auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<RhsT>::value,
-+ "operator&& is not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-+
-+ template<typename RhsT>
-+ auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
-+ static_assert(always_false<RhsT>::value,
-+ "operator|| is not supported inside assertions, "
-+ "wrap the expression inside parentheses, or decompose it");
-+ }
-
- auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
- return UnaryExpr<LhsT>{ m_lhs };
-@@ -1807,6 +2432,7 @@
- // start catch_interfaces_capture.h
-
- #include <string>
-+#include <chrono>
-
- namespace Catch {
-
-@@ -1815,15 +2441,20 @@
- struct SectionInfo;
- struct SectionEndInfo;
- struct MessageInfo;
-+ struct MessageBuilder;
- struct Counts;
-- struct BenchmarkInfo;
-- struct BenchmarkStats;
- struct AssertionReaction;
- struct SourceLineInfo;
-
- struct ITransientExpression;
- struct IGeneratorTracker;
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ struct BenchmarkInfo;
-+ template <typename Duration = std::chrono::duration<double, std::nano>>
-+ struct BenchmarkStats;
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-+
- struct IResultCapture {
-
- virtual ~IResultCapture();
-@@ -1833,14 +2464,20 @@
- virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
- virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
-
-- virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
-+ virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ virtual void benchmarkPreparing( std::string const& name ) = 0;
- virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
-- virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
-+ virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
-+ virtual void benchmarkFailed( std::string const& error ) = 0;
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
- virtual void pushScopedMessage( MessageInfo const& message ) = 0;
- virtual void popScopedMessage( MessageInfo const& message ) = 0;
-
-+ virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
-+
- virtual void handleFatalErrorCondition( StringRef message ) = 0;
-
- virtual void handleExpr
-@@ -2004,9 +2641,12 @@
- class ScopedMessage {
- public:
- explicit ScopedMessage( MessageBuilder const& builder );
-+ ScopedMessage( ScopedMessage& duplicate ) = delete;
-+ ScopedMessage( ScopedMessage&& old );
- ~ScopedMessage();
-
- MessageInfo m_info;
-+ bool m_moved;
- };
-
- class Capturer {
-@@ -2062,15 +2702,16 @@
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
- do { \
-+ CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
- Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
- INTERNAL_CATCH_TRY { \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
- catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
-- CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
- INTERNAL_CATCH_REACT( catchAssertionHandler ) \
-- } while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
-- // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
-+ } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) )
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
-@@ -2151,6 +2792,10 @@
- Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
-
- ///////////////////////////////////////////////////////////////////////////////
-+#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
-+ Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
-+
-+///////////////////////////////////////////////////////////////////////////////
- // Although this is matcher-based, it can be used with just a string
- #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
- do { \
-@@ -2283,62 +2928,18 @@
- } // end namespace Catch
-
- #define INTERNAL_CATCH_SECTION( ... ) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
- if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
-- CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-
- #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
- if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
-- CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-
- // end catch_section.h
--// start catch_benchmark.h
--
--#include <cstdint>
--#include <string>
--
--namespace Catch {
--
-- class BenchmarkLooper {
--
-- std::string m_name;
-- std::size_t m_count = 0;
-- std::size_t m_iterationsToRun = 1;
-- uint64_t m_resolution;
-- Timer m_timer;
--
-- static auto getResolution() -> uint64_t;
-- public:
-- // Keep most of this inline as it's on the code path that is being timed
-- BenchmarkLooper( StringRef name )
-- : m_name( name ),
-- m_resolution( getResolution() )
-- {
-- reportStart();
-- m_timer.start();
-- }
--
-- explicit operator bool() {
-- if( m_count < m_iterationsToRun )
-- return true;
-- return needsMoreIterations();
-- }
--
-- void increment() {
-- ++m_count;
-- }
--
-- void reportStart();
-- auto needsMoreIterations() -> bool;
-- };
--
--} // end namespace Catch
--
--#define BENCHMARK( name ) \
-- for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
--
--// end catch_benchmark.h
- // start catch_interfaces_exception.h
-
- // start catch_interfaces_registry_hub.h
-@@ -2355,6 +2956,8 @@
- struct IReporterRegistry;
- struct IReporterFactory;
- struct ITagAliasRegistry;
-+ struct IMutableEnumValuesRegistry;
-+
- class StartupExceptionRegistry;
-
- using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
-@@ -2365,7 +2968,6 @@
- virtual IReporterRegistry const& getReporterRegistry() const = 0;
- virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
- virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
--
- virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
-
- virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
-@@ -2379,6 +2981,7 @@
- virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
- virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
- virtual void registerStartupException() noexcept = 0;
-+ virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
- };
-
- IRegistryHub const& getRegistryHub();
-@@ -2425,6 +3028,9 @@
- {}
-
- std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
-+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
-+ return "";
-+#else
- try {
- if( it == itEnd )
- std::rethrow_exception(std::current_exception());
-@@ -2434,6 +3040,7 @@
- catch( T& ex ) {
- return m_translateFunction( ex );
- }
-+#endif
- }
-
- protected:
-@@ -2452,9 +3059,10 @@
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
- static std::string translatorName( signature ); \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- static std::string translatorName( signature )
-
- #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
-@@ -2485,7 +3093,7 @@
- Approx operator-() const;
-
- template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
-- Approx operator()( T const& value ) {
-+ Approx operator()( T const& value ) const {
- Approx approx( static_cast<double>(value) );
- approx.m_epsilon = m_epsilon;
- approx.m_margin = m_margin;
-@@ -2585,6 +3193,7 @@
-
- #include <string>
- #include <iosfwd>
-+#include <vector>
-
- namespace Catch {
-
-@@ -2595,7 +3204,13 @@
- bool contains( std::string const& s, std::string const& infix );
- void toLowerInPlace( std::string& s );
- std::string toLower( std::string const& s );
-+ //! Returns a new string without whitespace at the start/end
- std::string trim( std::string const& str );
-+ //! Returns a substring of the original ref without whitespace. Beware lifetimes!
-+ StringRef trim(StringRef ref);
-+
-+ // !!! Be aware, returns refs into original string - make sure original string outlives them
-+ std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
- bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
-
- struct pluralise {
-@@ -2648,6 +3263,15 @@
- virtual bool match( ObjectT const& arg ) const = 0;
- };
-
-+#if defined(__OBJC__)
-+ // Hack to fix Catch GH issue #1661. Could use id for generic Object support.
-+ // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation
-+ template<>
-+ struct MatcherMethod<NSString*> {
-+ virtual bool match( NSString* arg ) const = 0;
-+ };
-+#endif
-+
- #ifdef __clang__
- # pragma clang diagnostic pop
- #endif
-@@ -2685,9 +3309,10 @@
- return description;
- }
-
-- MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
-- m_matchers.push_back( &other );
-- return *this;
-+ MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) {
-+ auto copy(*this);
-+ copy.m_matchers.push_back( &other );
-+ return copy;
- }
-
- std::vector<MatcherBase<ArgT> const*> m_matchers;
-@@ -2718,9 +3343,10 @@
- return description;
- }
-
-- MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
-- m_matchers.push_back( &other );
-- return *this;
-+ MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) {
-+ auto copy(*this);
-+ copy.m_matchers.push_back( &other );
-+ return copy;
- }
-
- std::vector<MatcherBase<ArgT> const*> m_matchers;
-@@ -2764,10 +3390,34 @@
- } // namespace Catch
-
- // end catch_matchers.h
--// start catch_matchers_floating.h
-+// start catch_matchers_exception.hpp
-
--#include <type_traits>
--#include <cmath>
-+namespace Catch {
-+namespace Matchers {
-+namespace Exception {
-+
-+class ExceptionMessageMatcher : public MatcherBase<std::exception> {
-+ std::string m_message;
-+public:
-+
-+ ExceptionMessageMatcher(std::string const& message):
-+ m_message(message)
-+ {}
-+
-+ bool match(std::exception const& ex) const override;
-+
-+ std::string describe() const override;
-+};
-+
-+} // namespace Exception
-+
-+Exception::ExceptionMessageMatcher Message(std::string const& message);
-+
-+} // namespace Matchers
-+} // namespace Catch
-+
-+// end catch_matchers_exception.hpp
-+// start catch_matchers_floating.h
-
- namespace Catch {
- namespace Matchers {
-@@ -2786,22 +3436,43 @@
- };
-
- struct WithinUlpsMatcher : MatcherBase<double> {
-- WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType);
-+ WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType);
- bool match(double const& matchee) const override;
- std::string describe() const override;
- private:
- double m_target;
-- int m_ulps;
-+ uint64_t m_ulps;
- FloatingPointKind m_type;
- };
-
-+ // Given IEEE-754 format for floats and doubles, we can assume
-+ // that float -> double promotion is lossless. Given this, we can
-+ // assume that if we do the standard relative comparison of
-+ // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
-+ // the same result if we do this for floats, as if we do this for
-+ // doubles that were promoted from floats.
-+ struct WithinRelMatcher : MatcherBase<double> {
-+ WithinRelMatcher(double target, double epsilon);
-+ bool match(double const& matchee) const override;
-+ std::string describe() const override;
-+ private:
-+ double m_target;
-+ double m_epsilon;
-+ };
-+
- } // namespace Floating
-
- // The following functions create the actual matcher objects.
- // This allows the types to be inferred
-- Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff);
-- Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff);
-+ Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
-+ Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
- Floating::WithinAbsMatcher WithinAbs(double target, double margin);
-+ Floating::WithinRelMatcher WithinRel(double target, double eps);
-+ // defaults epsilon to 100*numeric_limits<double>::epsilon()
-+ Floating::WithinRelMatcher WithinRel(double target);
-+ Floating::WithinRelMatcher WithinRel(float target, float eps);
-+ // defaults epsilon to 100*numeric_limits<float>::epsilon()
-+ Floating::WithinRelMatcher WithinRel(float target);
-
- } // namespace Matchers
- } // namespace Catch
-@@ -2844,7 +3515,7 @@
-
- // The following functions create the actual matcher objects.
- // The user has to explicitly specify type to the function, because
-- // infering std::function<bool(T const&)> is hard (but possible) and
-+ // inferring std::function<bool(T const&)> is hard (but possible) and
- // requires a lot of TMP.
- template<typename T>
- Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
-@@ -2932,34 +3603,12 @@
- namespace Matchers {
-
- namespace Vector {
-- namespace Detail {
-- template <typename InputIterator, typename T>
-- size_t count(InputIterator first, InputIterator last, T const& item) {
-- size_t cnt = 0;
-- for (; first != last; ++first) {
-- if (*first == item) {
-- ++cnt;
-- }
-- }
-- return cnt;
-- }
-- template <typename InputIterator, typename T>
-- bool contains(InputIterator first, InputIterator last, T const& item) {
-- for (; first != last; ++first) {
-- if (*first == item) {
-- return true;
-- }
-- }
-- return false;
-- }
-- }
--
-- template<typename T>
-- struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
-+ template<typename T, typename Alloc>
-+ struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {
-
- ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
-
-- bool match(std::vector<T> const &v) const override {
-+ bool match(std::vector<T, Alloc> const &v) const override {
- for (auto const& el : v) {
- if (el == m_comparator) {
- return true;
-@@ -2975,12 +3624,12 @@
- T const& m_comparator;
- };
-
-- template<typename T>
-- struct ContainsMatcher : MatcherBase<std::vector<T>> {
-+ template<typename T, typename AllocComp, typename AllocMatch>
-+ struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
-
-- ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
-+ ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
-
-- bool match(std::vector<T> const &v) const override {
-+ bool match(std::vector<T, AllocMatch> const &v) const override {
- // !TBD: see note in EqualsMatcher
- if (m_comparator.size() > v.size())
- return false;
-@@ -3002,18 +3651,18 @@
- return "Contains: " + ::Catch::Detail::stringify( m_comparator );
- }
-
-- std::vector<T> const& m_comparator;
-+ std::vector<T, AllocComp> const& m_comparator;
- };
-
-- template<typename T>
-- struct EqualsMatcher : MatcherBase<std::vector<T>> {
-+ template<typename T, typename AllocComp, typename AllocMatch>
-+ struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
-
-- EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
-+ EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
-
-- bool match(std::vector<T> const &v) const override {
-+ bool match(std::vector<T, AllocMatch> const &v) const override {
- // !TBD: This currently works if all elements can be compared using !=
- // - a more general approach would be via a compare template that defaults
-- // to using !=. but could be specialised for, e.g. std::vector<T> etc
-+ // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc
- // - then just call that directly
- if (m_comparator.size() != v.size())
- return false;
-@@ -3025,47 +3674,60 @@
- std::string describe() const override {
- return "Equals: " + ::Catch::Detail::stringify( m_comparator );
- }
-- std::vector<T> const& m_comparator;
-+ std::vector<T, AllocComp> const& m_comparator;
- };
-
-- template<typename T>
-- struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
-- UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
-- bool match(std::vector<T> const& vec) const override {
-- // Note: This is a reimplementation of std::is_permutation,
-- // because I don't want to include <algorithm> inside the common path
-- if (m_target.size() != vec.size()) {
-- return false;
-- }
-- auto lfirst = m_target.begin(), llast = m_target.end();
-- auto rfirst = vec.begin(), rlast = vec.end();
-- // Cut common prefix to optimize checking of permuted parts
-- while (lfirst != llast && *lfirst == *rfirst) {
-- ++lfirst; ++rfirst;
-- }
-- if (lfirst == llast) {
-- return true;
-- }
-+ template<typename T, typename AllocComp, typename AllocMatch>
-+ struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {
-
-- for (auto mid = lfirst; mid != llast; ++mid) {
-- // Skip already counted items
-- if (Detail::contains(lfirst, mid, *mid)) {
-- continue;
-- }
-- size_t num_vec = Detail::count(rfirst, rlast, *mid);
-- if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
-- return false;
-- }
-- }
-+ ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {}
-
-+ bool match(std::vector<T, AllocMatch> const &v) const override {
-+ if (m_comparator.size() != v.size())
-+ return false;
-+ for (std::size_t i = 0; i < v.size(); ++i)
-+ if (m_comparator[i] != approx(v[i]))
-+ return false;
- return true;
- }
-+ std::string describe() const override {
-+ return "is approx: " + ::Catch::Detail::stringify( m_comparator );
-+ }
-+ template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
-+ ApproxMatcher& epsilon( T const& newEpsilon ) {
-+ approx.epsilon(newEpsilon);
-+ return *this;
-+ }
-+ template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
-+ ApproxMatcher& margin( T const& newMargin ) {
-+ approx.margin(newMargin);
-+ return *this;
-+ }
-+ template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
-+ ApproxMatcher& scale( T const& newScale ) {
-+ approx.scale(newScale);
-+ return *this;
-+ }
-+
-+ std::vector<T, AllocComp> const& m_comparator;
-+ mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
-+ };
-+
-+ template<typename T, typename AllocComp, typename AllocMatch>
-+ struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
-+ UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}
-+ bool match(std::vector<T, AllocMatch> const& vec) const override {
-+ if (m_target.size() != vec.size()) {
-+ return false;
-+ }
-+ return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
-+ }
-
- std::string describe() const override {
- return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
- }
- private:
-- std::vector<T> const& m_target;
-+ std::vector<T, AllocComp> const& m_target;
- };
-
- } // namespace Vector
-@@ -3073,24 +3735,29 @@
- // The following functions create the actual matcher objects.
- // This allows the types to be inferred
-
-- template<typename T>
-- Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
-- return Vector::ContainsMatcher<T>( comparator );
-+ template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
-+ Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
-+ return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator );
- }
-
-- template<typename T>
-- Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
-- return Vector::ContainsElementMatcher<T>( comparator );
-+ template<typename T, typename Alloc = std::allocator<T>>
-+ Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
-+ return Vector::ContainsElementMatcher<T, Alloc>( comparator );
- }
-
-- template<typename T>
-- Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
-- return Vector::EqualsMatcher<T>( comparator );
-+ template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
-+ Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
-+ return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator );
- }
-
-- template<typename T>
-- Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
-- return Vector::UnorderedEqualsMatcher<T>(target);
-+ template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
-+ Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
-+ return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator );
-+ }
-+
-+ template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
-+ Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
-+ return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target );
- }
-
- } // namespace Matchers
-@@ -3175,16 +3842,17 @@
- namespace Catch {
-
- namespace Generators {
-- class GeneratorBase {
-- protected:
-- size_t m_size = 0;
--
-+ class GeneratorUntypedBase {
- public:
-- GeneratorBase( size_t size ) : m_size( size ) {}
-- virtual ~GeneratorBase();
-- auto size() const -> size_t { return m_size; }
-+ GeneratorUntypedBase() = default;
-+ virtual ~GeneratorUntypedBase();
-+ // Attempts to move the generator to the next element
-+ //
-+ // Returns true iff the move succeeded (and a valid element
-+ // can be retrieved).
-+ virtual bool next() = 0;
- };
-- using GeneratorBasePtr = std::unique_ptr<GeneratorBase>;
-+ using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
-
- } // namespace Generators
-
-@@ -3193,7 +3861,6 @@
- virtual auto hasGenerator() const -> bool = 0;
- virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
- virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
-- virtual auto getIndex() const -> std::size_t = 0;
- };
-
- } // namespace Catch
-@@ -3201,7 +3868,7 @@
- // end catch_interfaces_generatortracker.h
- // start catch_enforce.h
-
--#include <stdexcept>
-+#include <exception>
-
- namespace Catch {
- #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
-@@ -3214,18 +3881,30 @@
- [[noreturn]]
- void throw_exception(std::exception const& e);
- #endif
-+
-+ [[noreturn]]
-+ void throw_logic_error(std::string const& msg);
-+ [[noreturn]]
-+ void throw_domain_error(std::string const& msg);
-+ [[noreturn]]
-+ void throw_runtime_error(std::string const& msg);
-+
- } // namespace Catch;
-
--#define CATCH_PREPARE_EXCEPTION( type, msg ) \
-- type( ( Catch::ReusableStringStream() << msg ).str() )
--#define CATCH_INTERNAL_ERROR( msg ) \
-- Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg))
--#define CATCH_ERROR( msg ) \
-- Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))
--#define CATCH_RUNTIME_ERROR( msg ) \
-- Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))
--#define CATCH_ENFORCE( condition, msg ) \
-- do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
-+#define CATCH_MAKE_MSG(...) \
-+ (Catch::ReusableStringStream() << __VA_ARGS__).str()
-+
-+#define CATCH_INTERNAL_ERROR(...) \
-+ Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
-+
-+#define CATCH_ERROR(...) \
-+ Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
-+
-+#define CATCH_RUNTIME_ERROR(...) \
-+ Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
-+
-+#define CATCH_ENFORCE( condition, ... ) \
-+ do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
-
- // end catch_enforce.h
- #include <memory>
-@@ -3233,8 +3912,21 @@
- #include <cassert>
-
- #include <utility>
-+#include <exception>
-
- namespace Catch {
-+
-+class GeneratorException : public std::exception {
-+ const char* const m_msg = "";
-+
-+public:
-+ GeneratorException(const char* msg):
-+ m_msg(msg)
-+ {}
-+
-+ const char* what() const noexcept override final;
-+};
-+
- namespace Generators {
-
- // !TBD move this into its own location?
-@@ -3246,223 +3938,819 @@
- }
-
- template<typename T>
-- struct IGenerator {
-- virtual ~IGenerator() {}
-- virtual auto get( size_t index ) const -> T = 0;
-+ struct IGenerator : GeneratorUntypedBase {
-+ virtual ~IGenerator() = default;
-+
-+ // Returns the current element of the generator
-+ //
-+ // \Precondition The generator is either freshly constructed,
-+ // or the last call to `next()` returned true
-+ virtual T const& get() const = 0;
-+ using type = T;
- };
-
- template<typename T>
-- class SingleValueGenerator : public IGenerator<T> {
-+ class SingleValueGenerator final : public IGenerator<T> {
- T m_value;
- public:
-- SingleValueGenerator( T const& value ) : m_value( value ) {}
-+ SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
-
-- auto get( size_t ) const -> T override {
-+ T const& get() const override {
- return m_value;
- }
-+ bool next() override {
-+ return false;
-+ }
- };
-
- template<typename T>
-- class FixedValuesGenerator : public IGenerator<T> {
-+ class FixedValuesGenerator final : public IGenerator<T> {
-+ static_assert(!std::is_same<T, bool>::value,
-+ "FixedValuesGenerator does not support bools because of std::vector<bool>"
-+ "specialization, use SingleValue Generator instead.");
- std::vector<T> m_values;
--
-+ size_t m_idx = 0;
- public:
- FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
-
-- auto get( size_t index ) const -> T override {
-- return m_values[index];
-+ T const& get() const override {
-+ return m_values[m_idx];
-+ }
-+ bool next() override {
-+ ++m_idx;
-+ return m_idx < m_values.size();
-+ }
-+ };
-+
-+ template <typename T>
-+ class GeneratorWrapper final {
-+ std::unique_ptr<IGenerator<T>> m_generator;
-+ public:
-+ GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):
-+ m_generator(std::move(generator))
-+ {}
-+ T const& get() const {
-+ return m_generator->get();
-+ }
-+ bool next() {
-+ return m_generator->next();
- }
- };
-
-+ template <typename T>
-+ GeneratorWrapper<T> value(T&& value) {
-+ return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));
-+ }
-+ template <typename T>
-+ GeneratorWrapper<T> values(std::initializer_list<T> values) {
-+ return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
-+ }
-+
- template<typename T>
-- class RangeGenerator : public IGenerator<T> {
-- T const m_first;
-- T const m_last;
-+ class Generators : public IGenerator<T> {
-+ std::vector<GeneratorWrapper<T>> m_generators;
-+ size_t m_current = 0;
-+
-+ void populate(GeneratorWrapper<T>&& generator) {
-+ m_generators.emplace_back(std::move(generator));
-+ }
-+ void populate(T&& val) {
-+ m_generators.emplace_back(value(std::forward<T>(val)));
-+ }
-+ template<typename U>
-+ void populate(U&& val) {
-+ populate(T(std::forward<U>(val)));
-+ }
-+ template<typename U, typename... Gs>
-+ void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {
-+ populate(std::forward<U>(valueOrGenerator));
-+ populate(std::forward<Gs>(moreGenerators)...);
-+ }
-
- public:
-- RangeGenerator( T const& first, T const& last ) : m_first( first ), m_last( last ) {
-- assert( m_last > m_first );
-+ template <typename... Gs>
-+ Generators(Gs &&... moreGenerators) {
-+ m_generators.reserve(sizeof...(Gs));
-+ populate(std::forward<Gs>(moreGenerators)...);
- }
-
-- auto get( size_t index ) const -> T override {
-- // ToDo:: introduce a safe cast to catch potential overflows
-- return static_cast<T>(m_first+index);
-+ T const& get() const override {
-+ return m_generators[m_current].get();
- }
-- };
-
-- template<typename T>
-- struct NullGenerator : IGenerator<T> {
-- auto get( size_t ) const -> T override {
-- CATCH_INTERNAL_ERROR("A Null Generator is always empty");
-+ bool next() override {
-+ if (m_current >= m_generators.size()) {
-+ return false;
-+ }
-+ const bool current_status = m_generators[m_current].next();
-+ if (!current_status) {
-+ ++m_current;
-+ }
-+ return m_current < m_generators.size();
- }
- };
-
-+ template<typename... Ts>
-+ GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {
-+ return values<std::tuple<Ts...>>( tuples );
-+ }
-+
-+ // Tag type to signal that a generator sequence should convert arguments to a specific type
-+ template <typename T>
-+ struct as {};
-+
-+ template<typename T, typename... Gs>
-+ auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
-+ return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
-+ }
- template<typename T>
-- class Generator {
-- std::unique_ptr<IGenerator<T>> m_generator;
-- size_t m_size;
-+ auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
-+ return Generators<T>(std::move(generator));
-+ }
-+ template<typename T, typename... Gs>
-+ auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {
-+ return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
-+ }
-+ template<typename T, typename U, typename... Gs>
-+ auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
-+ return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
-+ }
-
-- public:
-- Generator( size_t size, std::unique_ptr<IGenerator<T>> generator )
-- : m_generator( std::move( generator ) ),
-- m_size( size )
-- {}
-+ auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
-
-- auto size() const -> size_t { return m_size; }
-- auto operator[]( size_t index ) const -> T {
-- assert( index < m_size );
-- return m_generator->get( index );
-+ template<typename L>
-+ // Note: The type after -> is weird, because VS2015 cannot parse
-+ // the expression used in the typedef inside, when it is in
-+ // return type. Yeah.
-+ auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
-+ using UnderlyingType = typename decltype(generatorExpression())::type;
-+
-+ IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo );
-+ if (!tracker.hasGenerator()) {
-+ tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
- }
-- };
-
-- std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize );
-+ auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
-+ return generator.get();
-+ }
-+
-+} // namespace Generators
-+} // namespace Catch
-
-- template<typename T>
-- class GeneratorRandomiser : public IGenerator<T> {
-- Generator<T> m_baseGenerator;
-+#define GENERATE( ... ) \
-+ Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
-+ CATCH_INTERNAL_LINEINFO, \
-+ [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
-+#define GENERATE_COPY( ... ) \
-+ Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
-+ CATCH_INTERNAL_LINEINFO, \
-+ [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
-+#define GENERATE_REF( ... ) \
-+ Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
-+ CATCH_INTERNAL_LINEINFO, \
-+ [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
-+
-+// end catch_generators.hpp
-+// start catch_generators_generic.hpp
-+
-+namespace Catch {
-+namespace Generators {
-
-- std::vector<size_t> m_indices;
-+ template <typename T>
-+ class TakeGenerator : public IGenerator<T> {
-+ GeneratorWrapper<T> m_generator;
-+ size_t m_returned = 0;
-+ size_t m_target;
- public:
-- GeneratorRandomiser( Generator<T>&& baseGenerator, size_t numberOfItems )
-- : m_baseGenerator( std::move( baseGenerator ) ),
-- m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) )
-- {}
-+ TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
-+ m_generator(std::move(generator)),
-+ m_target(target)
-+ {
-+ assert(target != 0 && "Empty generators are not allowed");
-+ }
-+ T const& get() const override {
-+ return m_generator.get();
-+ }
-+ bool next() override {
-+ ++m_returned;
-+ if (m_returned >= m_target) {
-+ return false;
-+ }
-
-- auto get( size_t index ) const -> T override {
-- return m_baseGenerator[m_indices[index]];
-+ const auto success = m_generator.next();
-+ // If the underlying generator does not contain enough values
-+ // then we cut short as well
-+ if (!success) {
-+ m_returned = m_target;
-+ }
-+ return success;
- }
- };
-
-- template<typename T>
-- struct RequiresASpecialisationFor;
-+ template <typename T>
-+ GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
-+ return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
-+ }
-
-- template<typename T>
-- auto all() -> Generator<T> { return RequiresASpecialisationFor<T>(); }
-+ template <typename T, typename Predicate>
-+ class FilterGenerator : public IGenerator<T> {
-+ GeneratorWrapper<T> m_generator;
-+ Predicate m_predicate;
-+ public:
-+ template <typename P = Predicate>
-+ FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
-+ m_generator(std::move(generator)),
-+ m_predicate(std::forward<P>(pred))
-+ {
-+ if (!m_predicate(m_generator.get())) {
-+ // It might happen that there are no values that pass the
-+ // filter. In that case we throw an exception.
-+ auto has_initial_value = nextImpl();
-+ if (!has_initial_value) {
-+ Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
-+ }
-+ }
-+ }
-
-- template<>
-- auto all<int>() -> Generator<int>;
-+ T const& get() const override {
-+ return m_generator.get();
-+ }
-
-- template<typename T>
-- auto range( T const& first, T const& last ) -> Generator<T> {
-- return Generator<T>( (last-first), pf::make_unique<RangeGenerator<T>>( first, last ) );
-+ bool next() override {
-+ return nextImpl();
-+ }
-+
-+ private:
-+ bool nextImpl() {
-+ bool success = m_generator.next();
-+ if (!success) {
-+ return false;
-+ }
-+ while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
-+ return success;
-+ }
-+ };
-+
-+ template <typename T, typename Predicate>
-+ GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
-+ return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
- }
-
-- template<typename T>
-- auto random( T const& first, T const& last ) -> Generator<T> {
-- auto gen = range( first, last );
-- auto size = gen.size();
-+ template <typename T>
-+ class RepeatGenerator : public IGenerator<T> {
-+ static_assert(!std::is_same<T, bool>::value,
-+ "RepeatGenerator currently does not support bools"
-+ "because of std::vector<bool> specialization");
-+ GeneratorWrapper<T> m_generator;
-+ mutable std::vector<T> m_returned;
-+ size_t m_target_repeats;
-+ size_t m_current_repeat = 0;
-+ size_t m_repeat_index = 0;
-+ public:
-+ RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
-+ m_generator(std::move(generator)),
-+ m_target_repeats(repeats)
-+ {
-+ assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
-+ }
-+
-+ T const& get() const override {
-+ if (m_current_repeat == 0) {
-+ m_returned.push_back(m_generator.get());
-+ return m_returned.back();
-+ }
-+ return m_returned[m_repeat_index];
-+ }
-+
-+ bool next() override {
-+ // There are 2 basic cases:
-+ // 1) We are still reading the generator
-+ // 2) We are reading our own cache
-+
-+ // In the first case, we need to poke the underlying generator.
-+ // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
-+ if (m_current_repeat == 0) {
-+ const auto success = m_generator.next();
-+ if (!success) {
-+ ++m_current_repeat;
-+ }
-+ return m_current_repeat < m_target_repeats;
-+ }
-+
-+ // In the second case, we need to move indices forward and check that we haven't run up against the end
-+ ++m_repeat_index;
-+ if (m_repeat_index == m_returned.size()) {
-+ m_repeat_index = 0;
-+ ++m_current_repeat;
-+ }
-+ return m_current_repeat < m_target_repeats;
-+ }
-+ };
-
-- return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( std::move( gen ), size ) );
-+ template <typename T>
-+ GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
-+ return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
- }
-- template<typename T>
-- auto random( size_t size ) -> Generator<T> {
-- return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( all<T>(), size ) );
-+
-+ template <typename T, typename U, typename Func>
-+ class MapGenerator : public IGenerator<T> {
-+ // TBD: provide static assert for mapping function, for friendly error message
-+ GeneratorWrapper<U> m_generator;
-+ Func m_function;
-+ // To avoid returning dangling reference, we have to save the values
-+ T m_cache;
-+ public:
-+ template <typename F2 = Func>
-+ MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
-+ m_generator(std::move(generator)),
-+ m_function(std::forward<F2>(function)),
-+ m_cache(m_function(m_generator.get()))
-+ {}
-+
-+ T const& get() const override {
-+ return m_cache;
-+ }
-+ bool next() override {
-+ const auto success = m_generator.next();
-+ if (success) {
-+ m_cache = m_function(m_generator.get());
-+ }
-+ return success;
-+ }
-+ };
-+
-+ template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
-+ GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
-+ return GeneratorWrapper<T>(
-+ pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
-+ );
- }
-
-- template<typename T>
-- auto values( std::initializer_list<T> values ) -> Generator<T> {
-- return Generator<T>( values.size(), pf::make_unique<FixedValuesGenerator<T>>( values ) );
-+ template <typename T, typename U, typename Func>
-+ GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
-+ return GeneratorWrapper<T>(
-+ pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
-+ );
- }
-- template<typename T>
-- auto value( T const& val ) -> Generator<T> {
-- return Generator<T>( 1, pf::make_unique<SingleValueGenerator<T>>( val ) );
-+
-+ template <typename T>
-+ class ChunkGenerator final : public IGenerator<std::vector<T>> {
-+ std::vector<T> m_chunk;
-+ size_t m_chunk_size;
-+ GeneratorWrapper<T> m_generator;
-+ bool m_used_up = false;
-+ public:
-+ ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
-+ m_chunk_size(size), m_generator(std::move(generator))
-+ {
-+ m_chunk.reserve(m_chunk_size);
-+ if (m_chunk_size != 0) {
-+ m_chunk.push_back(m_generator.get());
-+ for (size_t i = 1; i < m_chunk_size; ++i) {
-+ if (!m_generator.next()) {
-+ Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
-+ }
-+ m_chunk.push_back(m_generator.get());
-+ }
-+ }
-+ }
-+ std::vector<T> const& get() const override {
-+ return m_chunk;
-+ }
-+ bool next() override {
-+ m_chunk.clear();
-+ for (size_t idx = 0; idx < m_chunk_size; ++idx) {
-+ if (!m_generator.next()) {
-+ return false;
-+ }
-+ m_chunk.push_back(m_generator.get());
-+ }
-+ return true;
-+ }
-+ };
-+
-+ template <typename T>
-+ GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
-+ return GeneratorWrapper<std::vector<T>>(
-+ pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
-+ );
- }
-
-- template<typename T>
-- auto as() -> Generator<T> {
-- return Generator<T>( 0, pf::make_unique<NullGenerator<T>>() );
-+} // namespace Generators
-+} // namespace Catch
-+
-+// end catch_generators_generic.hpp
-+// start catch_generators_specific.hpp
-+
-+// start catch_context.h
-+
-+#include <memory>
-+
-+namespace Catch {
-+
-+ struct IResultCapture;
-+ struct IRunner;
-+ struct IConfig;
-+ struct IMutableContext;
-+
-+ using IConfigPtr = std::shared_ptr<IConfig const>;
-+
-+ struct IContext
-+ {
-+ virtual ~IContext();
-+
-+ virtual IResultCapture* getResultCapture() = 0;
-+ virtual IRunner* getRunner() = 0;
-+ virtual IConfigPtr const& getConfig() const = 0;
-+ };
-+
-+ struct IMutableContext : IContext
-+ {
-+ virtual ~IMutableContext();
-+ virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
-+ virtual void setRunner( IRunner* runner ) = 0;
-+ virtual void setConfig( IConfigPtr const& config ) = 0;
-+
-+ private:
-+ static IMutableContext *currentContext;
-+ friend IMutableContext& getCurrentMutableContext();
-+ friend void cleanUpContext();
-+ static void createContext();
-+ };
-+
-+ inline IMutableContext& getCurrentMutableContext()
-+ {
-+ if( !IMutableContext::currentContext )
-+ IMutableContext::createContext();
-+ // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
-+ return *IMutableContext::currentContext;
- }
-
-- template<typename... Ts>
-- auto table( std::initializer_list<std::tuple<Ts...>>&& tuples ) -> Generator<std::tuple<Ts...>> {
-- return values<std::tuple<Ts...>>( std::forward<std::initializer_list<std::tuple<Ts...>>>( tuples ) );
-+ inline IContext& getCurrentContext()
-+ {
-+ return getCurrentMutableContext();
- }
-
-- template<typename T>
-- struct Generators : GeneratorBase {
-- std::vector<Generator<T>> m_generators;
-+ void cleanUpContext();
-
-- using type = T;
-+ class SimplePcg32;
-+ SimplePcg32& rng();
-+}
-
-- Generators() : GeneratorBase( 0 ) {}
-+// end catch_context.h
-+// start catch_interfaces_config.h
-
-- void populate( T&& val ) {
-- m_size += 1;
-- m_generators.emplace_back( value( std::move( val ) ) );
-+// start catch_option.hpp
-+
-+namespace Catch {
-+
-+ // An optional type
-+ template<typename T>
-+ class Option {
-+ public:
-+ Option() : nullableValue( nullptr ) {}
-+ Option( T const& _value )
-+ : nullableValue( new( storage ) T( _value ) )
-+ {}
-+ Option( Option const& _other )
-+ : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
-+ {}
-+
-+ ~Option() {
-+ reset();
- }
-- template<typename U>
-- void populate( U&& val ) {
-- populate( T( std::move( val ) ) );
-+
-+ Option& operator= ( Option const& _other ) {
-+ if( &_other != this ) {
-+ reset();
-+ if( _other )
-+ nullableValue = new( storage ) T( *_other );
-+ }
-+ return *this;
- }
-- void populate( Generator<T>&& generator ) {
-- m_size += generator.size();
-- m_generators.emplace_back( std::move( generator ) );
-+ Option& operator = ( T const& _value ) {
-+ reset();
-+ nullableValue = new( storage ) T( _value );
-+ return *this;
- }
-
-- template<typename U, typename... Gs>
-- void populate( U&& valueOrGenerator, Gs... moreGenerators ) {
-- populate( std::forward<U>( valueOrGenerator ) );
-- populate( std::forward<Gs>( moreGenerators )... );
-+ void reset() {
-+ if( nullableValue )
-+ nullableValue->~T();
-+ nullableValue = nullptr;
- }
-
-- auto operator[]( size_t index ) const -> T {
-- size_t sizes = 0;
-- for( auto const& gen : m_generators ) {
-- auto localIndex = index-sizes;
-- sizes += gen.size();
-- if( index < sizes )
-- return gen[localIndex];
-- }
-- CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes << ')');
-+ T& operator*() { return *nullableValue; }
-+ T const& operator*() const { return *nullableValue; }
-+ T* operator->() { return nullableValue; }
-+ const T* operator->() const { return nullableValue; }
-+
-+ T valueOr( T const& defaultValue ) const {
-+ return nullableValue ? *nullableValue : defaultValue;
-+ }
-+
-+ bool some() const { return nullableValue != nullptr; }
-+ bool none() const { return nullableValue == nullptr; }
-+
-+ bool operator !() const { return nullableValue == nullptr; }
-+ explicit operator bool() const {
-+ return some();
- }
-+
-+ private:
-+ T *nullableValue;
-+ alignas(alignof(T)) char storage[sizeof(T)];
- };
-
-- template<typename T, typename... Gs>
-- auto makeGenerators( Generator<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
-- Generators<T> generators;
-- generators.m_generators.reserve( 1+sizeof...(Gs) );
-- generators.populate( std::move( generator ), std::forward<Gs>( moreGenerators )... );
-- return generators;
-+} // end namespace Catch
-+
-+// end catch_option.hpp
-+#include <chrono>
-+#include <iosfwd>
-+#include <string>
-+#include <vector>
-+#include <memory>
-+
-+namespace Catch {
-+
-+ enum class Verbosity {
-+ Quiet = 0,
-+ Normal,
-+ High
-+ };
-+
-+ struct WarnAbout { enum What {
-+ Nothing = 0x00,
-+ NoAssertions = 0x01,
-+ NoTests = 0x02
-+ }; };
-+
-+ struct ShowDurations { enum OrNot {
-+ DefaultForReporter,
-+ Always,
-+ Never
-+ }; };
-+ struct RunTests { enum InWhatOrder {
-+ InDeclarationOrder,
-+ InLexicographicalOrder,
-+ InRandomOrder
-+ }; };
-+ struct UseColour { enum YesOrNo {
-+ Auto,
-+ Yes,
-+ No
-+ }; };
-+ struct WaitForKeypress { enum When {
-+ Never,
-+ BeforeStart = 1,
-+ BeforeExit = 2,
-+ BeforeStartAndExit = BeforeStart | BeforeExit
-+ }; };
-+
-+ class TestSpec;
-+
-+ struct IConfig : NonCopyable {
-+
-+ virtual ~IConfig();
-+
-+ virtual bool allowThrows() const = 0;
-+ virtual std::ostream& stream() const = 0;
-+ virtual std::string name() const = 0;
-+ virtual bool includeSuccessfulResults() const = 0;
-+ virtual bool shouldDebugBreak() const = 0;
-+ virtual bool warnAboutMissingAssertions() const = 0;
-+ virtual bool warnAboutNoTests() const = 0;
-+ virtual int abortAfter() const = 0;
-+ virtual bool showInvisibles() const = 0;
-+ virtual ShowDurations::OrNot showDurations() const = 0;
-+ virtual double minDuration() const = 0;
-+ virtual TestSpec const& testSpec() const = 0;
-+ virtual bool hasTestFilters() const = 0;
-+ virtual std::vector<std::string> const& getTestsOrTags() const = 0;
-+ virtual RunTests::InWhatOrder runOrder() const = 0;
-+ virtual unsigned int rngSeed() const = 0;
-+ virtual UseColour::YesOrNo useColour() const = 0;
-+ virtual std::vector<std::string> const& getSectionsToRun() const = 0;
-+ virtual Verbosity verbosity() const = 0;
-+
-+ virtual bool benchmarkNoAnalysis() const = 0;
-+ virtual int benchmarkSamples() const = 0;
-+ virtual double benchmarkConfidenceInterval() const = 0;
-+ virtual unsigned int benchmarkResamples() const = 0;
-+ virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
-+ };
-+
-+ using IConfigPtr = std::shared_ptr<IConfig const>;
-+}
-+
-+// end catch_interfaces_config.h
-+// start catch_random_number_generator.h
-+
-+#include <cstdint>
-+
-+namespace Catch {
-+
-+ // This is a simple implementation of C++11 Uniform Random Number
-+ // Generator. It does not provide all operators, because Catch2
-+ // does not use it, but it should behave as expected inside stdlib's
-+ // distributions.
-+ // The implementation is based on the PCG family (http://pcg-random.org)
-+ class SimplePcg32 {
-+ using state_type = std::uint64_t;
-+ public:
-+ using result_type = std::uint32_t;
-+ static constexpr result_type (min)() {
-+ return 0;
-+ }
-+ static constexpr result_type (max)() {
-+ return static_cast<result_type>(-1);
-+ }
-+
-+ // Provide some default initial state for the default constructor
-+ SimplePcg32():SimplePcg32(0xed743cc4U) {}
-+
-+ explicit SimplePcg32(result_type seed_);
-+
-+ void seed(result_type seed_);
-+ void discard(uint64_t skip);
-+
-+ result_type operator()();
-+
-+ private:
-+ friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
-+ friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
-+
-+ // In theory we also need operator<< and operator>>
-+ // In practice we do not use them, so we will skip them for now
-+
-+ std::uint64_t m_state;
-+ // This part of the state determines which "stream" of the numbers
-+ // is chosen -- we take it as a constant for Catch2, so we only
-+ // need to deal with seeding the main state.
-+ // Picked by reading 8 bytes from `/dev/random` :-)
-+ static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
-+ };
-+
-+} // end namespace Catch
-+
-+// end catch_random_number_generator.h
-+#include <random>
-+
-+namespace Catch {
-+namespace Generators {
-+
-+template <typename Float>
-+class RandomFloatingGenerator final : public IGenerator<Float> {
-+ Catch::SimplePcg32& m_rng;
-+ std::uniform_real_distribution<Float> m_dist;
-+ Float m_current_number;
-+public:
-+
-+ RandomFloatingGenerator(Float a, Float b):
-+ m_rng(rng()),
-+ m_dist(a, b) {
-+ static_cast<void>(next());
- }
-- template<typename T>
-- auto makeGenerators( Generator<T>&& generator ) -> Generators<T> {
-- Generators<T> generators;
-- generators.populate( std::move( generator ) );
-- return generators;
-+
-+ Float const& get() const override {
-+ return m_current_number;
- }
-- template<typename T, typename... Gs>
-- auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
-- return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
-+ bool next() override {
-+ m_current_number = m_dist(m_rng);
-+ return true;
- }
-- template<typename T, typename U, typename... Gs>
-- auto makeGenerators( U&& val, Gs... moreGenerators ) -> Generators<T> {
-- return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
-+};
-+
-+template <typename Integer>
-+class RandomIntegerGenerator final : public IGenerator<Integer> {
-+ Catch::SimplePcg32& m_rng;
-+ std::uniform_int_distribution<Integer> m_dist;
-+ Integer m_current_number;
-+public:
-+
-+ RandomIntegerGenerator(Integer a, Integer b):
-+ m_rng(rng()),
-+ m_dist(a, b) {
-+ static_cast<void>(next());
-+ }
-+
-+ Integer const& get() const override {
-+ return m_current_number;
-+ }
-+ bool next() override {
-+ m_current_number = m_dist(m_rng);
-+ return true;
- }
-+};
-
-- auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
-+// TODO: Ideally this would be also constrained against the various char types,
-+// but I don't expect users to run into that in practice.
-+template <typename T>
-+typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,
-+GeneratorWrapper<T>>::type
-+random(T a, T b) {
-+ return GeneratorWrapper<T>(
-+ pf::make_unique<RandomIntegerGenerator<T>>(a, b)
-+ );
-+}
-
-- template<typename L>
-- // Note: The type after -> is weird, because VS2015 cannot parse
-- // the expression used in the typedef inside, when it is in
-- // return type. Yeah, ¯\_(ツ)_/¯
-- auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>()[0]) {
-- using UnderlyingType = typename decltype(generatorExpression())::type;
-+template <typename T>
-+typename std::enable_if<std::is_floating_point<T>::value,
-+GeneratorWrapper<T>>::type
-+random(T a, T b) {
-+ return GeneratorWrapper<T>(
-+ pf::make_unique<RandomFloatingGenerator<T>>(a, b)
-+ );
-+}
-+
-+template <typename T>
-+class RangeGenerator final : public IGenerator<T> {
-+ T m_current;
-+ T m_end;
-+ T m_step;
-+ bool m_positive;
-+
-+public:
-+ RangeGenerator(T const& start, T const& end, T const& step):
-+ m_current(start),
-+ m_end(end),
-+ m_step(step),
-+ m_positive(m_step > T(0))
-+ {
-+ assert(m_current != m_end && "Range start and end cannot be equal");
-+ assert(m_step != T(0) && "Step size cannot be zero");
-+ assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
-+ }
-+
-+ RangeGenerator(T const& start, T const& end):
-+ RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
-+ {}
-+
-+ T const& get() const override {
-+ return m_current;
-+ }
-+
-+ bool next() override {
-+ m_current += m_step;
-+ return (m_positive) ? (m_current < m_end) : (m_current > m_end);
-+ }
-+};
-+
-+template <typename T>
-+GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
-+ static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
-+ return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
-+}
-+
-+template <typename T>
-+GeneratorWrapper<T> range(T const& start, T const& end) {
-+ static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
-+ return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));
-+}
-
-- IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
-- if( !tracker.hasGenerator() )
-- tracker.setGenerator( pf::make_unique<Generators<UnderlyingType>>( generatorExpression() ) );
-+template <typename T>
-+class IteratorGenerator final : public IGenerator<T> {
-+ static_assert(!std::is_same<T, bool>::value,
-+ "IteratorGenerator currently does not support bools"
-+ "because of std::vector<bool> specialization");
-+
-+ std::vector<T> m_elems;
-+ size_t m_current = 0;
-+public:
-+ template <typename InputIterator, typename InputSentinel>
-+ IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
-+ if (m_elems.empty()) {
-+ Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values"));
-+ }
-+ }
-+
-+ T const& get() const override {
-+ return m_elems[m_current];
-+ }
-
-- auto const& generator = static_cast<Generators<UnderlyingType> const&>( *tracker.getGenerator() );
-- return generator[tracker.getIndex()];
-+ bool next() override {
-+ ++m_current;
-+ return m_current != m_elems.size();
- }
-+};
-+
-+template <typename InputIterator,
-+ typename InputSentinel,
-+ typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
-+GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
-+ return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to));
-+}
-+
-+template <typename Container,
-+ typename ResultType = typename Container::value_type>
-+GeneratorWrapper<ResultType> from_range(Container const& cnt) {
-+ return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end()));
-+}
-
- } // namespace Generators
- } // namespace Catch
-
--#define GENERATE( ... ) \
-- Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
--
--// end catch_generators.hpp
-+// end catch_generators_specific.hpp
-
- // These files are included here so the single_include script doesn't put them
- // in the conditionally compiled sections
-@@ -3662,7 +4950,7 @@
- arcSafeRelease( m_substr );
- }
-
-- bool match( NSString* arg ) const override {
-+ bool match( NSString* str ) const override {
- return false;
- }
-
-@@ -3685,7 +4973,7 @@
- struct Contains : StringHolder {
- Contains( NSString* substr ) : StringHolder( substr ){}
-
-- bool match( NSString* str ) const {
-+ bool match( NSString* str ) const override {
- return (str != nil || m_substr == nil ) &&
- [str rangeOfString:m_substr].location != NSNotFound;
- }
-@@ -3761,7 +5049,8 @@
- // end catch_objc.hpp
- #endif
-
--#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
-+// Benchmarking needs the externally-facing parts of reporters to work
-+#if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
- // start catch_external_interfaces.h
-
- // start catch_reporter_bases.hpp
-@@ -3803,7 +5092,7 @@
- virtual bool matches( std::string const& str ) const;
-
- private:
-- std::string adjustCase( std::string const& str ) const;
-+ std::string normaliseString( std::string const& str ) const;
- CaseSensitive::Choice m_caseSensitivity;
- WildcardPosition m_wildcard = NoWildcard;
- std::string m_pattern;
-@@ -3817,36 +5106,40 @@
-
- namespace Catch {
-
-+ struct IConfig;
-+
- class TestSpec {
-- struct Pattern {
-+ class Pattern {
-+ public:
-+ explicit Pattern( std::string const& name );
- virtual ~Pattern();
- virtual bool matches( TestCaseInfo const& testCase ) const = 0;
-+ std::string const& name() const;
-+ private:
-+ std::string const m_name;
- };
- using PatternPtr = std::shared_ptr<Pattern>;
-
- class NamePattern : public Pattern {
- public:
-- NamePattern( std::string const& name );
-- virtual ~NamePattern();
-- virtual bool matches( TestCaseInfo const& testCase ) const override;
-+ explicit NamePattern( std::string const& name, std::string const& filterString );
-+ bool matches( TestCaseInfo const& testCase ) const override;
- private:
- WildcardPattern m_wildcardPattern;
- };
-
- class TagPattern : public Pattern {
- public:
-- TagPattern( std::string const& tag );
-- virtual ~TagPattern();
-- virtual bool matches( TestCaseInfo const& testCase ) const override;
-+ explicit TagPattern( std::string const& tag, std::string const& filterString );
-+ bool matches( TestCaseInfo const& testCase ) const override;
- private:
- std::string m_tag;
- };
-
- class ExcludedPattern : public Pattern {
- public:
-- ExcludedPattern( PatternPtr const& underlyingPattern );
-- virtual ~ExcludedPattern();
-- virtual bool matches( TestCaseInfo const& testCase ) const override;
-+ explicit ExcludedPattern( PatternPtr const& underlyingPattern );
-+ bool matches( TestCaseInfo const& testCase ) const override;
- private:
- PatternPtr m_underlyingPattern;
- };
-@@ -3855,15 +5148,25 @@
- std::vector<PatternPtr> m_patterns;
-
- bool matches( TestCaseInfo const& testCase ) const;
-+ std::string name() const;
- };
-
- public:
-+ struct FilterMatch {
-+ std::string name;
-+ std::vector<TestCase const*> tests;
-+ };
-+ using Matches = std::vector<FilterMatch>;
-+ using vectorStrings = std::vector<std::string>;
-+
- bool hasFilters() const;
- bool matches( TestCaseInfo const& testCase ) const;
-+ Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
-+ const vectorStrings & getInvalidArgs() const;
-
- private:
- std::vector<Filter> m_filters;
--
-+ std::vector<std::string> m_invalidArgs;
- friend class TestSpecParser;
- };
- }
-@@ -3898,9 +5201,13 @@
- class TestSpecParser {
- enum Mode{ None, Name, QuotedName, Tag, EscapedName };
- Mode m_mode = None;
-+ Mode lastMode = None;
- bool m_exclusion = false;
-- std::size_t m_start = std::string::npos, m_pos = 0;
-+ std::size_t m_pos = 0;
-+ std::size_t m_realPatternPos = 0;
- std::string m_arg;
-+ std::string m_substring;
-+ std::string m_patternName;
- std::vector<std::size_t> m_escapeChars;
- TestSpec::Filter m_currentFilter;
- TestSpec m_testSpec;
-@@ -3913,32 +5220,32 @@
- TestSpec testSpec();
-
- private:
-- void visitChar( char c );
-- void startNewMode( Mode mode, std::size_t start );
-+ bool visitChar( char c );
-+ void startNewMode( Mode mode );
-+ bool processNoneChar( char c );
-+ void processNameChar( char c );
-+ bool processOtherChar( char c );
-+ void endMode();
- void escape();
-- std::string subString() const;
-+ bool isControlChar( char c ) const;
-+ void saveLastMode();
-+ void revertBackToLastMode();
-+ void addFilter();
-+ bool separate();
-
-- template<typename T>
-- void addPattern() {
-- std::string token = subString();
-- for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
-- token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
-- m_escapeChars.clear();
-- if( startsWith( token, "exclude:" ) ) {
-- m_exclusion = true;
-- token = token.substr( 8 );
-- }
-- if( !token.empty() ) {
-- TestSpec::PatternPtr pattern = std::make_shared<T>( token );
-- if( m_exclusion )
-- pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
-- m_currentFilter.m_patterns.push_back( pattern );
-- }
-- m_exclusion = false;
-- m_mode = None;
-+ // Handles common preprocessing of the pattern for name/tag patterns
-+ std::string preprocessPattern();
-+ // Adds the current pattern as a test name
-+ void addNamePattern();
-+ // Adds the current pattern as a tag
-+ void addTagPattern();
-+
-+ inline void addCharToPattern(char c) {
-+ m_substring += c;
-+ m_patternName += c;
-+ m_realPatternPos++;
- }
-
-- void addFilter();
- };
- TestSpec parseTestSpec( std::string const& arg );
-
-@@ -3949,79 +5256,6 @@
- #endif
-
- // end catch_test_spec_parser.h
--// start catch_interfaces_config.h
--
--#include <iosfwd>
--#include <string>
--#include <vector>
--#include <memory>
--
--namespace Catch {
--
-- enum class Verbosity {
-- Quiet = 0,
-- Normal,
-- High
-- };
--
-- struct WarnAbout { enum What {
-- Nothing = 0x00,
-- NoAssertions = 0x01,
-- NoTests = 0x02
-- }; };
--
-- struct ShowDurations { enum OrNot {
-- DefaultForReporter,
-- Always,
-- Never
-- }; };
-- struct RunTests { enum InWhatOrder {
-- InDeclarationOrder,
-- InLexicographicalOrder,
-- InRandomOrder
-- }; };
-- struct UseColour { enum YesOrNo {
-- Auto,
-- Yes,
-- No
-- }; };
-- struct WaitForKeypress { enum When {
-- Never,
-- BeforeStart = 1,
-- BeforeExit = 2,
-- BeforeStartAndExit = BeforeStart | BeforeExit
-- }; };
--
-- class TestSpec;
--
-- struct IConfig : NonCopyable {
--
-- virtual ~IConfig();
--
-- virtual bool allowThrows() const = 0;
-- virtual std::ostream& stream() const = 0;
-- virtual std::string name() const = 0;
-- virtual bool includeSuccessfulResults() const = 0;
-- virtual bool shouldDebugBreak() const = 0;
-- virtual bool warnAboutMissingAssertions() const = 0;
-- virtual bool warnAboutNoTests() const = 0;
-- virtual int abortAfter() const = 0;
-- virtual bool showInvisibles() const = 0;
-- virtual ShowDurations::OrNot showDurations() const = 0;
-- virtual TestSpec const& testSpec() const = 0;
-- virtual bool hasTestFilters() const = 0;
-- virtual RunTests::InWhatOrder runOrder() const = 0;
-- virtual unsigned int rngSeed() const = 0;
-- virtual int benchmarkResolutionMultiple() const = 0;
-- virtual UseColour::YesOrNo useColour() const = 0;
-- virtual std::vector<std::string> const& getSectionsToRun() const = 0;
-- virtual Verbosity verbosity() const = 0;
-- };
--
-- using IConfigPtr = std::shared_ptr<IConfig const>;
--}
--
--// end catch_interfaces_config.h
- // Libstdc++ doesn't like incomplete classes for unique_ptr
-
- #include <memory>
-@@ -4052,11 +5286,17 @@
-
- int abortAfter = -1;
- unsigned int rngSeed = 0;
-- int benchmarkResolutionMultiple = 100;
-+
-+ bool benchmarkNoAnalysis = false;
-+ unsigned int benchmarkSamples = 100;
-+ double benchmarkConfidenceInterval = 0.95;
-+ unsigned int benchmarkResamples = 100000;
-+ std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
-
- Verbosity verbosity = Verbosity::Normal;
- WarnAbout::What warnings = WarnAbout::Nothing;
- ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
-+ double minDuration = -1;
- RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
- UseColour::YesOrNo useColour = UseColour::Auto;
- WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
-@@ -4091,10 +5331,10 @@
- std::string getProcessName() const;
- std::string const& getReporterName() const;
-
-- std::vector<std::string> const& getTestsOrTags() const;
-+ std::vector<std::string> const& getTestsOrTags() const override;
- std::vector<std::string> const& getSectionsToRun() const override;
-
-- virtual TestSpec const& testSpec() const override;
-+ TestSpec const& testSpec() const override;
- bool hasTestFilters() const override;
-
- bool showHelp() const;
-@@ -4107,14 +5347,19 @@
- bool warnAboutMissingAssertions() const override;
- bool warnAboutNoTests() const override;
- ShowDurations::OrNot showDurations() const override;
-+ double minDuration() const override;
- RunTests::InWhatOrder runOrder() const override;
- unsigned int rngSeed() const override;
-- int benchmarkResolutionMultiple() const override;
- UseColour::YesOrNo useColour() const override;
- bool shouldDebugBreak() const override;
- int abortAfter() const override;
- bool showInvisibles() const override;
- Verbosity verbosity() const override;
-+ bool benchmarkNoAnalysis() const override;
-+ int benchmarkSamples() const override;
-+ double benchmarkConfidenceInterval() const override;
-+ unsigned int benchmarkResamples() const override;
-+ std::chrono::milliseconds benchmarkWarmupTime() const override;
-
- private:
-
-@@ -4175,76 +5420,61 @@
- } // end namespace Catch
-
- // end catch_assertionresult.h
--// start catch_option.hpp
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+// start catch_estimate.hpp
-
--namespace Catch {
-+ // Statistics estimates
-
-- // An optional type
-- template<typename T>
-- class Option {
-- public:
-- Option() : nullableValue( nullptr ) {}
-- Option( T const& _value )
-- : nullableValue( new( storage ) T( _value ) )
-- {}
-- Option( Option const& _other )
-- : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
-- {}
-
-- ~Option() {
-- reset();
-- }
-+namespace Catch {
-+ namespace Benchmark {
-+ template <typename Duration>
-+ struct Estimate {
-+ Duration point;
-+ Duration lower_bound;
-+ Duration upper_bound;
-+ double confidence_interval;
-
-- Option& operator= ( Option const& _other ) {
-- if( &_other != this ) {
-- reset();
-- if( _other )
-- nullableValue = new( storage ) T( *_other );
-+ template <typename Duration2>
-+ operator Estimate<Duration2>() const {
-+ return { point, lower_bound, upper_bound, confidence_interval };
- }
-- return *this;
-- }
-- Option& operator = ( T const& _value ) {
-- reset();
-- nullableValue = new( storage ) T( _value );
-- return *this;
-- }
--
-- void reset() {
-- if( nullableValue )
-- nullableValue->~T();
-- nullableValue = nullptr;
-- }
-+ };
-+ } // namespace Benchmark
-+} // namespace Catch
-
-- T& operator*() { return *nullableValue; }
-- T const& operator*() const { return *nullableValue; }
-- T* operator->() { return nullableValue; }
-- const T* operator->() const { return nullableValue; }
-+// end catch_estimate.hpp
-+// start catch_outlier_classification.hpp
-
-- T valueOr( T const& defaultValue ) const {
-- return nullableValue ? *nullableValue : defaultValue;
-- }
-+// Outlier information
-
-- bool some() const { return nullableValue != nullptr; }
-- bool none() const { return nullableValue == nullptr; }
-+namespace Catch {
-+ namespace Benchmark {
-+ struct OutlierClassification {
-+ int samples_seen = 0;
-+ int low_severe = 0; // more than 3 times IQR below Q1
-+ int low_mild = 0; // 1.5 to 3 times IQR below Q1
-+ int high_mild = 0; // 1.5 to 3 times IQR above Q3
-+ int high_severe = 0; // more than 3 times IQR above Q3
-
-- bool operator !() const { return nullableValue == nullptr; }
-- explicit operator bool() const {
-- return some();
-- }
-+ int total() const {
-+ return low_severe + low_mild + high_mild + high_severe;
-+ }
-+ };
-+ } // namespace Benchmark
-+} // namespace Catch
-
-- private:
-- T *nullableValue;
-- alignas(alignof(T)) char storage[sizeof(T)];
-- };
-+// end catch_outlier_classification.hpp
-
--} // end namespace Catch
-+#include <iterator>
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
--// end catch_option.hpp
- #include <string>
- #include <iosfwd>
- #include <map>
- #include <set>
- #include <memory>
-+#include <algorithm>
-
- namespace Catch {
-
-@@ -4301,8 +5531,8 @@
-
- AssertionStats( AssertionStats const& ) = default;
- AssertionStats( AssertionStats && ) = default;
-- AssertionStats& operator = ( AssertionStats const& ) = default;
-- AssertionStats& operator = ( AssertionStats && ) = default;
-+ AssertionStats& operator = ( AssertionStats const& ) = delete;
-+ AssertionStats& operator = ( AssertionStats && ) = delete;
- virtual ~AssertionStats();
-
- AssertionResult assertionResult;
-@@ -4380,14 +5610,43 @@
- bool aborting;
- };
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
- struct BenchmarkInfo {
- std::string name;
-+ double estimatedDuration;
-+ int iterations;
-+ int samples;
-+ unsigned int resamples;
-+ double clockResolution;
-+ double clockCost;
- };
-+
-+ template <class Duration>
- struct BenchmarkStats {
- BenchmarkInfo info;
-- std::size_t iterations;
-- uint64_t elapsedTimeInNanoseconds;
-+
-+ std::vector<Duration> samples;
-+ Benchmark::Estimate<Duration> mean;
-+ Benchmark::Estimate<Duration> standardDeviation;
-+ Benchmark::OutlierClassification outliers;
-+ double outlierVariance;
-+
-+ template <typename Duration2>
-+ operator BenchmarkStats<Duration2>() const {
-+ std::vector<Duration2> samples2;
-+ samples2.reserve(samples.size());
-+ std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); });
-+ return {
-+ info,
-+ std::move(samples2),
-+ mean,
-+ standardDeviation,
-+ outliers,
-+ outlierVariance,
-+ };
-+ }
- };
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
- struct IStreamingReporter {
- virtual ~IStreamingReporter() = default;
-@@ -4400,23 +5659,26 @@
-
- virtual void noMatchingTestCases( std::string const& spec ) = 0;
-
-+ virtual void reportInvalidArguments(std::string const&) {}
-+
- virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
- virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
-
- virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
- virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
-
-- // *** experimental ***
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ virtual void benchmarkPreparing( std::string const& ) {}
- virtual void benchmarkStarting( BenchmarkInfo const& ) {}
-+ virtual void benchmarkEnded( BenchmarkStats<> const& ) {}
-+ virtual void benchmarkFailed( std::string const& ) {}
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
- virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
-
- // The return value indicates if the messages buffer should be cleared:
- virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
-
-- // *** experimental ***
-- virtual void benchmarkEnded( BenchmarkStats const& ) {}
--
- virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
- virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
- virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
-@@ -4465,6 +5727,11 @@
- // Returns double formatted as %.3f (format expected on output)
- std::string getFormattedDuration( double duration );
-
-+ //! Should the reporter show
-+ bool shouldShowDuration( IConfig const& config, double duration );
-+
-+ std::string serializeFilters( std::vector<std::string> const& container );
-+
- template<typename DerivedT>
- struct StreamingReporterBase : IStreamingReporter {
-
-@@ -4489,9 +5756,12 @@
-
- void noMatchingTestCases(std::string const&) override {}
-
-+ void reportInvalidArguments(std::string const&) override {}
-+
- void testRunStarting(TestRunInfo const& _testRunInfo) override {
- currentTestRunInfo = _testRunInfo;
- }
-+
- void testGroupStarting(GroupInfo const& _groupInfo) override {
- currentGroupInfo = _groupInfo;
- }
-@@ -4782,11 +6052,11 @@
-
- class ReporterFactory : public IReporterFactory {
-
-- virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
-+ IStreamingReporterPtr create( ReporterConfig const& config ) const override {
- return std::unique_ptr<T>( new T( config ) );
- }
-
-- virtual std::string getDescription() const override {
-+ std::string getDescription() const override {
- return T::getDescription();
- }
- };
-@@ -4803,10 +6073,10 @@
-
- class ListenerFactory : public IReporterFactory {
-
-- virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
-+ IStreamingReporterPtr create( ReporterConfig const& config ) const override {
- return std::unique_ptr<T>( new T( config ) );
- }
-- virtual std::string getDescription() const override {
-+ std::string getDescription() const override {
- return std::string();
- }
- };
-@@ -4822,14 +6092,16 @@
- #if !defined(CATCH_CONFIG_DISABLE)
-
- #define CATCH_REGISTER_REPORTER( name, reporterType ) \
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
-- CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-
- #define CATCH_REGISTER_LISTENER( listenerType ) \
-- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-- namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
-- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
-+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-+ namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
- #else // CATCH_CONFIG_DISABLE
-
- #define CATCH_REGISTER_REPORTER(name, reporterType)
-@@ -4851,8 +6123,6 @@
-
- static std::string getDescription();
-
-- ReporterPreferences getPreferences() const override;
--
- void noMatchingTestCases(std::string const& spec) override;
-
- void assertionStarting(AssertionInfo const&) override;
-@@ -4891,6 +6161,8 @@
-
- void noMatchingTestCases(std::string const& spec) override;
-
-+ void reportInvalidArguments(std::string const&arg) override;
-+
- void assertionStarting(AssertionInfo const&) override;
-
- bool assertionEnded(AssertionStats const& _assertionStats) override;
-@@ -4898,13 +6170,17 @@
- void sectionStarting(SectionInfo const& _sectionInfo) override;
- void sectionEnded(SectionStats const& _sectionStats) override;
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ void benchmarkPreparing(std::string const& name) override;
- void benchmarkStarting(BenchmarkInfo const& info) override;
-- void benchmarkEnded(BenchmarkStats const& stats) override;
-+ void benchmarkEnded(BenchmarkStats<> const& stats) override;
-+ void benchmarkFailed(std::string const& error) override;
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
- void testCaseEnded(TestCaseStats const& _testCaseStats) override;
- void testGroupEnded(TestGroupStats const& _testGroupStats) override;
- void testRunEnded(TestRunStats const& _testRunStats) override;
--
-+ void testRunStarting(TestRunInfo const& _testRunInfo) override;
- private:
-
- void lazyPrint();
-@@ -4926,6 +6202,7 @@
-
- void printTotalsDivider(Totals const& totals);
- void printSummaryDivider();
-+ void printTestFilters();
-
- private:
- bool m_headerPrinted = false;
-@@ -4945,6 +6222,14 @@
- #include <vector>
-
- namespace Catch {
-+ enum class XmlFormatting {
-+ None = 0x00,
-+ Indent = 0x01,
-+ Newline = 0x02,
-+ };
-+
-+ XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs);
-+ XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs);
-
- class XmlEncode {
- public:
-@@ -4966,14 +6251,14 @@
-
- class ScopedElement {
- public:
-- ScopedElement( XmlWriter* writer );
-+ ScopedElement( XmlWriter* writer, XmlFormatting fmt );
-
- ScopedElement( ScopedElement&& other ) noexcept;
- ScopedElement& operator=( ScopedElement&& other ) noexcept;
-
- ~ScopedElement();
-
-- ScopedElement& writeText( std::string const& text, bool indent = true );
-+ ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent );
-
- template<typename T>
- ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
-@@ -4983,6 +6268,7 @@
-
- private:
- mutable XmlWriter* m_writer = nullptr;
-+ XmlFormatting m_fmt;
- };
-
- XmlWriter( std::ostream& os = Catch::cout() );
-@@ -4991,11 +6277,11 @@
- XmlWriter( XmlWriter const& ) = delete;
- XmlWriter& operator=( XmlWriter const& ) = delete;
-
-- XmlWriter& startElement( std::string const& name );
-+ XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
-
-- ScopedElement scopedElement( std::string const& name );
-+ ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
-
-- XmlWriter& endElement();
-+ XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
-
- XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
-
-@@ -5008,9 +6294,9 @@
- return writeAttribute( name, rss.str() );
- }
-
-- XmlWriter& writeText( std::string const& text, bool indent = true );
-+ XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
-
-- XmlWriter& writeComment( std::string const& text );
-+ XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
-
- void writeStylesheetRef( std::string const& url );
-
-@@ -5020,6 +6306,8 @@
-
- private:
-
-+ void applyFormatting(XmlFormatting fmt);
-+
- void writeDeclaration();
-
- void newlineIfNecessary();
-@@ -5063,9 +6351,10 @@
-
- void writeTestCase(TestCaseNode const& testCaseNode);
-
-- void writeSection(std::string const& className,
-- std::string const& rootName,
-- SectionNode const& sectionNode);
-+ void writeSection( std::string const& className,
-+ std::string const& rootName,
-+ SectionNode const& sectionNode,
-+ bool testOkToFail );
-
- void writeAssertions(SectionNode const& sectionNode);
- void writeAssertion(AssertionStats const& stats);
-@@ -5120,6 +6409,13 @@
-
- void testRunEnded(TestRunStats const& testRunStats) override;
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ void benchmarkPreparing(std::string const& name) override;
-+ void benchmarkStarting(BenchmarkInfo const&) override;
-+ void benchmarkEnded(BenchmarkStats<> const&) override;
-+ void benchmarkFailed(std::string const&) override;
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-+
- private:
- Timer m_testCaseTimer;
- XmlWriter m_xml;
-@@ -5133,6 +6429,1032 @@
- // end catch_external_interfaces.h
- #endif
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+// start catch_benchmarking_all.hpp
-+
-+// A proxy header that includes all of the benchmarking headers to allow
-+// concise include of the benchmarking features. You should prefer the
-+// individual includes in standard use.
-+
-+// start catch_benchmark.hpp
-+
-+ // Benchmark
-+
-+// start catch_chronometer.hpp
-+
-+// User-facing chronometer
-+
-+
-+// start catch_clock.hpp
-+
-+// Clocks
-+
-+
-+#include <chrono>
-+#include <ratio>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ template <typename Clock>
-+ using ClockDuration = typename Clock::duration;
-+ template <typename Clock>
-+ using FloatDuration = std::chrono::duration<double, typename Clock::period>;
-+
-+ template <typename Clock>
-+ using TimePoint = typename Clock::time_point;
-+
-+ using default_clock = std::chrono::steady_clock;
-+
-+ template <typename Clock>
-+ struct now {
-+ TimePoint<Clock> operator()() const {
-+ return Clock::now();
-+ }
-+ };
-+
-+ using fp_seconds = std::chrono::duration<double, std::ratio<1>>;
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_clock.hpp
-+// start catch_optimizer.hpp
-+
-+ // Hinting the optimizer
-+
-+
-+#if defined(_MSC_VER)
-+# include <atomic> // atomic_thread_fence
-+#endif
-+
-+namespace Catch {
-+ namespace Benchmark {
-+#if defined(__GNUC__) || defined(__clang__)
-+ template <typename T>
-+ inline void keep_memory(T* p) {
-+ asm volatile("" : : "g"(p) : "memory");
-+ }
-+ inline void keep_memory() {
-+ asm volatile("" : : : "memory");
-+ }
-+
-+ namespace Detail {
-+ inline void optimizer_barrier() { keep_memory(); }
-+ } // namespace Detail
-+#elif defined(_MSC_VER)
-+
-+#pragma optimize("", off)
-+ template <typename T>
-+ inline void keep_memory(T* p) {
-+ // thanks @milleniumbug
-+ *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
-+ }
-+ // TODO equivalent keep_memory()
-+#pragma optimize("", on)
-+
-+ namespace Detail {
-+ inline void optimizer_barrier() {
-+ std::atomic_thread_fence(std::memory_order_seq_cst);
-+ }
-+ } // namespace Detail
-+
-+#endif
-+
-+ template <typename T>
-+ inline void deoptimize_value(T&& x) {
-+ keep_memory(&x);
-+ }
-+
-+ template <typename Fn, typename... Args>
-+ inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type {
-+ deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...)));
-+ }
-+
-+ template <typename Fn, typename... Args>
-+ inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type {
-+ std::forward<Fn>(fn) (std::forward<Args...>(args...));
-+ }
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_optimizer.hpp
-+// start catch_complete_invoke.hpp
-+
-+// Invoke with a special case for void
-+
-+
-+#include <type_traits>
-+#include <utility>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ template <typename T>
-+ struct CompleteType { using type = T; };
-+ template <>
-+ struct CompleteType<void> { struct type {}; };
-+
-+ template <typename T>
-+ using CompleteType_t = typename CompleteType<T>::type;
-+
-+ template <typename Result>
-+ struct CompleteInvoker {
-+ template <typename Fun, typename... Args>
-+ static Result invoke(Fun&& fun, Args&&... args) {
-+ return std::forward<Fun>(fun)(std::forward<Args>(args)...);
-+ }
-+ };
-+ template <>
-+ struct CompleteInvoker<void> {
-+ template <typename Fun, typename... Args>
-+ static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) {
-+ std::forward<Fun>(fun)(std::forward<Args>(args)...);
-+ return {};
-+ }
-+ };
-+
-+ // invoke and not return void :(
-+ template <typename Fun, typename... Args>
-+ CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) {
-+ return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...);
-+ }
-+
-+ const std::string benchmarkErrorMsg = "a benchmark failed to run successfully";
-+ } // namespace Detail
-+
-+ template <typename Fun>
-+ Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) {
-+ CATCH_TRY{
-+ return Detail::complete_invoke(std::forward<Fun>(fun));
-+ } CATCH_CATCH_ALL{
-+ getResultCapture().benchmarkFailed(translateActiveException());
-+ CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg);
-+ }
-+ }
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_complete_invoke.hpp
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ struct ChronometerConcept {
-+ virtual void start() = 0;
-+ virtual void finish() = 0;
-+ virtual ~ChronometerConcept() = default;
-+ };
-+ template <typename Clock>
-+ struct ChronometerModel final : public ChronometerConcept {
-+ void start() override { started = Clock::now(); }
-+ void finish() override { finished = Clock::now(); }
-+
-+ ClockDuration<Clock> elapsed() const { return finished - started; }
-+
-+ TimePoint<Clock> started;
-+ TimePoint<Clock> finished;
-+ };
-+ } // namespace Detail
-+
-+ struct Chronometer {
-+ public:
-+ template <typename Fun>
-+ void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); }
-+
-+ int runs() const { return k; }
-+
-+ Chronometer(Detail::ChronometerConcept& meter, int k)
-+ : impl(&meter)
-+ , k(k) {}
-+
-+ private:
-+ template <typename Fun>
-+ void measure(Fun&& fun, std::false_type) {
-+ measure([&fun](int) { return fun(); }, std::true_type());
-+ }
-+
-+ template <typename Fun>
-+ void measure(Fun&& fun, std::true_type) {
-+ Detail::optimizer_barrier();
-+ impl->start();
-+ for (int i = 0; i < k; ++i) invoke_deoptimized(fun, i);
-+ impl->finish();
-+ Detail::optimizer_barrier();
-+ }
-+
-+ Detail::ChronometerConcept* impl;
-+ int k;
-+ };
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_chronometer.hpp
-+// start catch_environment.hpp
-+
-+// Environment information
-+
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ template <typename Duration>
-+ struct EnvironmentEstimate {
-+ Duration mean;
-+ OutlierClassification outliers;
-+
-+ template <typename Duration2>
-+ operator EnvironmentEstimate<Duration2>() const {
-+ return { mean, outliers };
-+ }
-+ };
-+ template <typename Clock>
-+ struct Environment {
-+ using clock_type = Clock;
-+ EnvironmentEstimate<FloatDuration<Clock>> clock_resolution;
-+ EnvironmentEstimate<FloatDuration<Clock>> clock_cost;
-+ };
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_environment.hpp
-+// start catch_execution_plan.hpp
-+
-+ // Execution plan
-+
-+
-+// start catch_benchmark_function.hpp
-+
-+ // Dumb std::function implementation for consistent call overhead
-+
-+
-+#include <cassert>
-+#include <type_traits>
-+#include <utility>
-+#include <memory>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ template <typename T>
-+ using Decay = typename std::decay<T>::type;
-+ template <typename T, typename U>
-+ struct is_related
-+ : std::is_same<Decay<T>, Decay<U>> {};
-+
-+ /// We need to reinvent std::function because every piece of code that might add overhead
-+ /// in a measurement context needs to have consistent performance characteristics so that we
-+ /// can account for it in the measurement.
-+ /// Implementations of std::function with optimizations that aren't always applicable, like
-+ /// small buffer optimizations, are not uncommon.
-+ /// This is effectively an implementation of std::function without any such optimizations;
-+ /// it may be slow, but it is consistently slow.
-+ struct BenchmarkFunction {
-+ private:
-+ struct callable {
-+ virtual void call(Chronometer meter) const = 0;
-+ virtual callable* clone() const = 0;
-+ virtual ~callable() = default;
-+ };
-+ template <typename Fun>
-+ struct model : public callable {
-+ model(Fun&& fun) : fun(std::move(fun)) {}
-+ model(Fun const& fun) : fun(fun) {}
-+
-+ model<Fun>* clone() const override { return new model<Fun>(*this); }
-+
-+ void call(Chronometer meter) const override {
-+ call(meter, is_callable<Fun(Chronometer)>());
-+ }
-+ void call(Chronometer meter, std::true_type) const {
-+ fun(meter);
-+ }
-+ void call(Chronometer meter, std::false_type) const {
-+ meter.measure(fun);
-+ }
-+
-+ Fun fun;
-+ };
-+
-+ struct do_nothing { void operator()() const {} };
-+
-+ template <typename T>
-+ BenchmarkFunction(model<T>* c) : f(c) {}
-+
-+ public:
-+ BenchmarkFunction()
-+ : f(new model<do_nothing>{ {} }) {}
-+
-+ template <typename Fun,
-+ typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0>
-+ BenchmarkFunction(Fun&& fun)
-+ : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {}
-+
-+ BenchmarkFunction(BenchmarkFunction&& that)
-+ : f(std::move(that.f)) {}
-+
-+ BenchmarkFunction(BenchmarkFunction const& that)
-+ : f(that.f->clone()) {}
-+
-+ BenchmarkFunction& operator=(BenchmarkFunction&& that) {
-+ f = std::move(that.f);
-+ return *this;
-+ }
-+
-+ BenchmarkFunction& operator=(BenchmarkFunction const& that) {
-+ f.reset(that.f->clone());
-+ return *this;
-+ }
-+
-+ void operator()(Chronometer meter) const { f->call(meter); }
-+
-+ private:
-+ std::unique_ptr<callable> f;
-+ };
-+ } // namespace Detail
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_benchmark_function.hpp
-+// start catch_repeat.hpp
-+
-+// repeat algorithm
-+
-+
-+#include <type_traits>
-+#include <utility>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ template <typename Fun>
-+ struct repeater {
-+ void operator()(int k) const {
-+ for (int i = 0; i < k; ++i) {
-+ fun();
-+ }
-+ }
-+ Fun fun;
-+ };
-+ template <typename Fun>
-+ repeater<typename std::decay<Fun>::type> repeat(Fun&& fun) {
-+ return { std::forward<Fun>(fun) };
-+ }
-+ } // namespace Detail
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_repeat.hpp
-+// start catch_run_for_at_least.hpp
-+
-+// Run a function for a minimum amount of time
-+
-+
-+// start catch_measure.hpp
-+
-+// Measure
-+
-+
-+// start catch_timing.hpp
-+
-+// Timing
-+
-+
-+#include <tuple>
-+#include <type_traits>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ template <typename Duration, typename Result>
-+ struct Timing {
-+ Duration elapsed;
-+ Result result;
-+ int iterations;
-+ };
-+ template <typename Clock, typename Func, typename... Args>
-+ using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_timing.hpp
-+#include <utility>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ template <typename Clock, typename Fun, typename... Args>
-+ TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) {
-+ auto start = Clock::now();
-+ auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...);
-+ auto end = Clock::now();
-+ auto delta = end - start;
-+ return { delta, std::forward<decltype(r)>(r), 1 };
-+ }
-+ } // namespace Detail
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_measure.hpp
-+#include <utility>
-+#include <type_traits>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ template <typename Clock, typename Fun>
-+ TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
-+ return Detail::measure<Clock>(fun, iters);
-+ }
-+ template <typename Clock, typename Fun>
-+ TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
-+ Detail::ChronometerModel<Clock> meter;
-+ auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
-+
-+ return { meter.elapsed(), std::move(result), iters };
-+ }
-+
-+ template <typename Clock, typename Fun>
-+ using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type;
-+
-+ struct optimized_away_error : std::exception {
-+ const char* what() const noexcept override {
-+ return "could not measure benchmark, maybe it was optimized away";
-+ }
-+ };
-+
-+ template <typename Clock, typename Fun>
-+ TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) {
-+ auto iters = seed;
-+ while (iters < (1 << 30)) {
-+ auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
-+
-+ if (Timing.elapsed >= how_long) {
-+ return { Timing.elapsed, std::move(Timing.result), iters };
-+ }
-+ iters *= 2;
-+ }
-+ Catch::throw_exception(optimized_away_error{});
-+ }
-+ } // namespace Detail
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_run_for_at_least.hpp
-+#include <algorithm>
-+#include <iterator>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ template <typename Duration>
-+ struct ExecutionPlan {
-+ int iterations_per_sample;
-+ Duration estimated_duration;
-+ Detail::BenchmarkFunction benchmark;
-+ Duration warmup_time;
-+ int warmup_iterations;
-+
-+ template <typename Duration2>
-+ operator ExecutionPlan<Duration2>() const {
-+ return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations };
-+ }
-+
-+ template <typename Clock>
-+ std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
-+ // warmup a bit
-+ Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{}));
-+
-+ std::vector<FloatDuration<Clock>> times;
-+ times.reserve(cfg.benchmarkSamples());
-+ std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] {
-+ Detail::ChronometerModel<Clock> model;
-+ this->benchmark(Chronometer(model, iterations_per_sample));
-+ auto sample_time = model.elapsed() - env.clock_cost.mean;
-+ if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero();
-+ return sample_time / iterations_per_sample;
-+ });
-+ return times;
-+ }
-+ };
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_execution_plan.hpp
-+// start catch_estimate_clock.hpp
-+
-+ // Environment measurement
-+
-+
-+// start catch_stats.hpp
-+
-+// Statistical analysis tools
-+
-+
-+#include <algorithm>
-+#include <functional>
-+#include <vector>
-+#include <iterator>
-+#include <numeric>
-+#include <tuple>
-+#include <cmath>
-+#include <utility>
-+#include <cstddef>
-+#include <random>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ using sample = std::vector<double>;
-+
-+ double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last);
-+
-+ template <typename Iterator>
-+ OutlierClassification classify_outliers(Iterator first, Iterator last) {
-+ std::vector<double> copy(first, last);
-+
-+ auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end());
-+ auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end());
-+ auto iqr = q3 - q1;
-+ auto los = q1 - (iqr * 3.);
-+ auto lom = q1 - (iqr * 1.5);
-+ auto him = q3 + (iqr * 1.5);
-+ auto his = q3 + (iqr * 3.);
-+
-+ OutlierClassification o;
-+ for (; first != last; ++first) {
-+ auto&& t = *first;
-+ if (t < los) ++o.low_severe;
-+ else if (t < lom) ++o.low_mild;
-+ else if (t > his) ++o.high_severe;
-+ else if (t > him) ++o.high_mild;
-+ ++o.samples_seen;
-+ }
-+ return o;
-+ }
-+
-+ template <typename Iterator>
-+ double mean(Iterator first, Iterator last) {
-+ auto count = last - first;
-+ double sum = std::accumulate(first, last, 0.);
-+ return sum / count;
-+ }
-+
-+ template <typename URng, typename Iterator, typename Estimator>
-+ sample resample(URng& rng, int resamples, Iterator first, Iterator last, Estimator& estimator) {
-+ auto n = last - first;
-+ std::uniform_int_distribution<decltype(n)> dist(0, n - 1);
-+
-+ sample out;
-+ out.reserve(resamples);
-+ std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] {
-+ std::vector<double> resampled;
-+ resampled.reserve(n);
-+ std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; });
-+ return estimator(resampled.begin(), resampled.end());
-+ });
-+ std::sort(out.begin(), out.end());
-+ return out;
-+ }
-+
-+ template <typename Estimator, typename Iterator>
-+ sample jackknife(Estimator&& estimator, Iterator first, Iterator last) {
-+ auto n = last - first;
-+ auto second = std::next(first);
-+ sample results;
-+ results.reserve(n);
-+
-+ for (auto it = first; it != last; ++it) {
-+ std::iter_swap(it, first);
-+ results.push_back(estimator(second, last));
-+ }
-+
-+ return results;
-+ }
-+
-+ inline double normal_cdf(double x) {
-+ return std::erfc(-x / std::sqrt(2.0)) / 2.0;
-+ }
-+
-+ double erfc_inv(double x);
-+
-+ double normal_quantile(double p);
-+
-+ template <typename Iterator, typename Estimator>
-+ Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& estimator) {
-+ auto n_samples = last - first;
-+
-+ double point = estimator(first, last);
-+ // Degenerate case with a single sample
-+ if (n_samples == 1) return { point, point, point, confidence_level };
-+
-+ sample jack = jackknife(estimator, first, last);
-+ double jack_mean = mean(jack.begin(), jack.end());
-+ double sum_squares, sum_cubes;
-+ std::tie(sum_squares, sum_cubes) = std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair<double, double> sqcb, double x) -> std::pair<double, double> {
-+ auto d = jack_mean - x;
-+ auto d2 = d * d;
-+ auto d3 = d2 * d;
-+ return { sqcb.first + d2, sqcb.second + d3 };
-+ });
-+
-+ double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
-+ int n = static_cast<int>(resample.size());
-+ double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / (double)n;
-+ // degenerate case with uniform samples
-+ if (prob_n == 0) return { point, point, point, confidence_level };
-+
-+ double bias = normal_quantile(prob_n);
-+ double z1 = normal_quantile((1. - confidence_level) / 2.);
-+
-+ auto cumn = [n](double x) -> int {
-+ return std::lround(normal_cdf(x) * n); };
-+ auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };
-+ double b1 = bias + z1;
-+ double b2 = bias - z1;
-+ double a1 = a(b1);
-+ double a2 = a(b2);
-+ auto lo = (std::max)(cumn(a1), 0);
-+ auto hi = (std::min)(cumn(a2), n - 1);
-+
-+ return { point, resample[lo], resample[hi], confidence_level };
-+ }
-+
-+ double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n);
-+
-+ struct bootstrap_analysis {
-+ Estimate<double> mean;
-+ Estimate<double> standard_deviation;
-+ double outlier_variance;
-+ };
-+
-+ bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last);
-+ } // namespace Detail
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_stats.hpp
-+#include <algorithm>
-+#include <iterator>
-+#include <tuple>
-+#include <vector>
-+#include <cmath>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ template <typename Clock>
-+ std::vector<double> resolution(int k) {
-+ std::vector<TimePoint<Clock>> times;
-+ times.reserve(k + 1);
-+ std::generate_n(std::back_inserter(times), k + 1, now<Clock>{});
-+
-+ std::vector<double> deltas;
-+ deltas.reserve(k);
-+ std::transform(std::next(times.begin()), times.end(), times.begin(),
-+ std::back_inserter(deltas),
-+ [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); });
-+
-+ return deltas;
-+ }
-+
-+ const auto warmup_iterations = 10000;
-+ const auto warmup_time = std::chrono::milliseconds(100);
-+ const auto minimum_ticks = 1000;
-+ const auto warmup_seed = 10000;
-+ const auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
-+ const auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
-+ const auto clock_cost_estimation_tick_limit = 100000;
-+ const auto clock_cost_estimation_time = std::chrono::milliseconds(10);
-+ const auto clock_cost_estimation_iterations = 10000;
-+
-+ template <typename Clock>
-+ int warmup() {
-+ return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>)
-+ .iterations;
-+ }
-+ template <typename Clock>
-+ EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) {
-+ auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>)
-+ .result;
-+ return {
-+ FloatDuration<Clock>(mean(r.begin(), r.end())),
-+ classify_outliers(r.begin(), r.end()),
-+ };
-+ }
-+ template <typename Clock>
-+ EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
-+ auto time_limit = (std::min)(
-+ resolution * clock_cost_estimation_tick_limit,
-+ FloatDuration<Clock>(clock_cost_estimation_time_limit));
-+ auto time_clock = [](int k) {
-+ return Detail::measure<Clock>([k] {
-+ for (int i = 0; i < k; ++i) {
-+ volatile auto ignored = Clock::now();
-+ (void)ignored;
-+ }
-+ }).elapsed;
-+ };
-+ time_clock(1);
-+ int iters = clock_cost_estimation_iterations;
-+ auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock);
-+ std::vector<double> times;
-+ int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
-+ times.reserve(nsamples);
-+ std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] {
-+ return static_cast<double>((time_clock(r.iterations) / r.iterations).count());
-+ });
-+ return {
-+ FloatDuration<Clock>(mean(times.begin(), times.end())),
-+ classify_outliers(times.begin(), times.end()),
-+ };
-+ }
-+
-+ template <typename Clock>
-+ Environment<FloatDuration<Clock>> measure_environment() {
-+ static Environment<FloatDuration<Clock>>* env = nullptr;
-+ if (env) {
-+ return *env;
-+ }
-+
-+ auto iters = Detail::warmup<Clock>();
-+ auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
-+ auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
-+
-+ env = new Environment<FloatDuration<Clock>>{ resolution, cost };
-+ return *env;
-+ }
-+ } // namespace Detail
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_estimate_clock.hpp
-+// start catch_analyse.hpp
-+
-+ // Run and analyse one benchmark
-+
-+
-+// start catch_sample_analysis.hpp
-+
-+// Benchmark results
-+
-+
-+#include <algorithm>
-+#include <vector>
-+#include <string>
-+#include <iterator>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ template <typename Duration>
-+ struct SampleAnalysis {
-+ std::vector<Duration> samples;
-+ Estimate<Duration> mean;
-+ Estimate<Duration> standard_deviation;
-+ OutlierClassification outliers;
-+ double outlier_variance;
-+
-+ template <typename Duration2>
-+ operator SampleAnalysis<Duration2>() const {
-+ std::vector<Duration2> samples2;
-+ samples2.reserve(samples.size());
-+ std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); });
-+ return {
-+ std::move(samples2),
-+ mean,
-+ standard_deviation,
-+ outliers,
-+ outlier_variance,
-+ };
-+ }
-+ };
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_sample_analysis.hpp
-+#include <algorithm>
-+#include <iterator>
-+#include <vector>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ template <typename Duration, typename Iterator>
-+ SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) {
-+ if (!cfg.benchmarkNoAnalysis()) {
-+ std::vector<double> samples;
-+ samples.reserve(last - first);
-+ std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); });
-+
-+ auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end());
-+ auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end());
-+
-+ auto wrap_estimate = [](Estimate<double> e) {
-+ return Estimate<Duration> {
-+ Duration(e.point),
-+ Duration(e.lower_bound),
-+ Duration(e.upper_bound),
-+ e.confidence_interval,
-+ };
-+ };
-+ std::vector<Duration> samples2;
-+ samples2.reserve(samples.size());
-+ std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); });
-+ return {
-+ std::move(samples2),
-+ wrap_estimate(analysis.mean),
-+ wrap_estimate(analysis.standard_deviation),
-+ outliers,
-+ analysis.outlier_variance,
-+ };
-+ } else {
-+ std::vector<Duration> samples;
-+ samples.reserve(last - first);
-+
-+ Duration mean = Duration(0);
-+ int i = 0;
-+ for (auto it = first; it < last; ++it, ++i) {
-+ samples.push_back(Duration(*it));
-+ mean += Duration(*it);
-+ }
-+ mean /= i;
-+
-+ return {
-+ std::move(samples),
-+ Estimate<Duration>{mean, mean, mean, 0.0},
-+ Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0},
-+ OutlierClassification{},
-+ 0.0
-+ };
-+ }
-+ }
-+ } // namespace Detail
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+// end catch_analyse.hpp
-+#include <algorithm>
-+#include <functional>
-+#include <string>
-+#include <vector>
-+#include <cmath>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ struct Benchmark {
-+ Benchmark(std::string &&name)
-+ : name(std::move(name)) {}
-+
-+ template <class FUN>
-+ Benchmark(std::string &&name, FUN &&func)
-+ : fun(std::move(func)), name(std::move(name)) {}
-+
-+ template <typename Clock>
-+ ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
-+ auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
-+ auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
-+ auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
-+ int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
-+ return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
-+ }
-+
-+ template <typename Clock = default_clock>
-+ void run() {
-+ IConfigPtr cfg = getCurrentContext().getConfig();
-+
-+ auto env = Detail::measure_environment<Clock>();
-+
-+ getResultCapture().benchmarkPreparing(name);
-+ CATCH_TRY{
-+ auto plan = user_code([&] {
-+ return prepare<Clock>(*cfg, env);
-+ });
-+
-+ BenchmarkInfo info {
-+ name,
-+ plan.estimated_duration.count(),
-+ plan.iterations_per_sample,
-+ cfg->benchmarkSamples(),
-+ cfg->benchmarkResamples(),
-+ env.clock_resolution.mean.count(),
-+ env.clock_cost.mean.count()
-+ };
-+
-+ getResultCapture().benchmarkStarting(info);
-+
-+ auto samples = user_code([&] {
-+ return plan.template run<Clock>(*cfg, env);
-+ });
-+
-+ auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
-+ BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
-+ getResultCapture().benchmarkEnded(stats);
-+
-+ } CATCH_CATCH_ALL{
-+ if (translateActiveException() != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow.
-+ std::rethrow_exception(std::current_exception());
-+ }
-+ }
-+
-+ // sets lambda to be used in fun *and* executes benchmark!
-+ template <typename Fun,
-+ typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0>
-+ Benchmark & operator=(Fun func) {
-+ fun = Detail::BenchmarkFunction(func);
-+ run();
-+ return *this;
-+ }
-+
-+ explicit operator bool() {
-+ return true;
-+ }
-+
-+ private:
-+ Detail::BenchmarkFunction fun;
-+ std::string name;
-+ };
-+ }
-+} // namespace Catch
-+
-+#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
-+#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
-+
-+#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
-+ if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
-+ BenchmarkName = [&](int benchmarkIndex)
-+
-+#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
-+ if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
-+ BenchmarkName = [&]
-+
-+// end catch_benchmark.hpp
-+// start catch_constructor.hpp
-+
-+// Constructor and destructor helpers
-+
-+
-+#include <type_traits>
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+ template <typename T, bool Destruct>
-+ struct ObjectStorage
-+ {
-+ using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
-+
-+ ObjectStorage() : data() {}
-+
-+ ObjectStorage(const ObjectStorage& other)
-+ {
-+ new(&data) T(other.stored_object());
-+ }
-+
-+ ObjectStorage(ObjectStorage&& other)
-+ {
-+ new(&data) T(std::move(other.stored_object()));
-+ }
-+
-+ ~ObjectStorage() { destruct_on_exit<T>(); }
-+
-+ template <typename... Args>
-+ void construct(Args&&... args)
-+ {
-+ new (&data) T(std::forward<Args>(args)...);
-+ }
-+
-+ template <bool AllowManualDestruction = !Destruct>
-+ typename std::enable_if<AllowManualDestruction>::type destruct()
-+ {
-+ stored_object().~T();
-+ }
-+
-+ private:
-+ // If this is a constructor benchmark, destruct the underlying object
-+ template <typename U>
-+ void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
-+ // Otherwise, don't
-+ template <typename U>
-+ void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
-+
-+ T& stored_object() {
-+ return *static_cast<T*>(static_cast<void*>(&data));
-+ }
-+
-+ T const& stored_object() const {
-+ return *static_cast<T*>(static_cast<void*>(&data));
-+ }
-+
-+ TStorage data;
-+ };
-+ }
-+
-+ template <typename T>
-+ using storage_for = Detail::ObjectStorage<T, true>;
-+
-+ template <typename T>
-+ using destructable_object = Detail::ObjectStorage<T, false>;
-+ }
-+}
-+
-+// end catch_constructor.hpp
-+// end catch_benchmarking_all.hpp
-+#endif
-+
- #endif // ! CATCH_CONFIG_IMPL_ONLY
-
- #ifdef CATCH_IMPL
-@@ -5158,23 +7480,37 @@
- SourceLineInfo location;
-
- NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
-+ friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
-+ return lhs.name == rhs.name
-+ && lhs.location == rhs.location;
-+ }
- };
-
-- struct ITracker;
-+ class ITracker;
-
- using ITrackerPtr = std::shared_ptr<ITracker>;
-
-- struct ITracker {
-- virtual ~ITracker();
-+ class ITracker {
-+ NameAndLocation m_nameAndLocation;
-+
-+ public:
-+ ITracker(NameAndLocation const& nameAndLoc) :
-+ m_nameAndLocation(nameAndLoc)
-+ {}
-
- // static queries
-- virtual NameAndLocation const& nameAndLocation() const = 0;
-+ NameAndLocation const& nameAndLocation() const {
-+ return m_nameAndLocation;
-+ }
-+
-+ virtual ~ITracker();
-
- // dynamic queries
- virtual bool isComplete() const = 0; // Successfully completed or failed
- virtual bool isSuccessfullyCompleted() const = 0;
- virtual bool isOpen() const = 0; // Started but not complete
- virtual bool hasChildren() const = 0;
-+ virtual bool hasStarted() const = 0;
-
- virtual ITracker& parent() = 0;
-
-@@ -5189,7 +7525,7 @@
-
- // Debug/ checking
- virtual bool isSectionTracker() const = 0;
-- virtual bool isIndexTracker() const = 0;
-+ virtual bool isGeneratorTracker() const = 0;
- };
-
- class TrackerContext {
-@@ -5206,8 +7542,6 @@
-
- public:
-
-- static TrackerContext& instance();
--
- ITracker& startRun();
- void endRun();
-
-@@ -5231,7 +7565,6 @@
- };
-
- using Children = std::vector<ITrackerPtr>;
-- NameAndLocation m_nameAndLocation;
- TrackerContext& m_ctx;
- ITracker* m_parent;
- Children m_children;
-@@ -5240,11 +7573,13 @@
- public:
- TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
-
-- NameAndLocation const& nameAndLocation() const override;
- bool isComplete() const override;
- bool isSuccessfullyCompleted() const override;
- bool isOpen() const override;
- bool hasChildren() const override;
-+ bool hasStarted() const override {
-+ return m_runState != NotStarted;
-+ }
-
- void addChild( ITrackerPtr const& child ) override;
-
-@@ -5254,7 +7589,7 @@
- void openChild() override;
-
- bool isSectionTracker() const override;
-- bool isIndexTracker() const override;
-+ bool isGeneratorTracker() const override;
-
- void open();
-
-@@ -5269,33 +7604,24 @@
-
- class SectionTracker : public TrackerBase {
- std::vector<std::string> m_filters;
-+ std::string m_trimmed_name;
- public:
- SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
-
- bool isSectionTracker() const override;
-
-+ bool isComplete() const override;
-+
- static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
-
- void tryOpen();
-
- void addInitialFilters( std::vector<std::string> const& filters );
- void addNextFilters( std::vector<std::string> const& filters );
-- };
--
-- class IndexTracker : public TrackerBase {
-- int m_size;
-- int m_index = -1;
-- public:
-- IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size );
--
-- bool isIndexTracker() const override;
-- void close() override;
--
-- static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size );
--
-- int index() const;
--
-- void moveNext();
-+ //! Returns filters active in this tracker
-+ std::vector<std::string> const& getFilters() const;
-+ //! Returns whitespace-trimmed name of the tracked section
-+ std::string const& trimmedName() const;
- };
-
- } // namespace TestCaseTracking
-@@ -5303,7 +7629,6 @@
- using TestCaseTracking::ITracker;
- using TestCaseTracking::TrackerContext;
- using TestCaseTracking::SectionTracker;
--using TestCaseTracking::IndexTracker;
-
- } // namespace Catch
-
-@@ -5321,6 +7646,217 @@
- }
- // end catch_leak_detector.h
- // Cpp files will be included in the single-header file here
-+// start catch_stats.cpp
-+
-+// Statistical analysis tools
-+
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+
-+#include <cassert>
-+#include <random>
-+
-+#if defined(CATCH_CONFIG_USE_ASYNC)
-+#include <future>
-+#endif
-+
-+namespace {
-+ double erf_inv(double x) {
-+ // Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2
-+ double w, p;
-+
-+ w = -log((1.0 - x) * (1.0 + x));
-+
-+ if (w < 6.250000) {
-+ w = w - 3.125000;
-+ p = -3.6444120640178196996e-21;
-+ p = -1.685059138182016589e-19 + p * w;
-+ p = 1.2858480715256400167e-18 + p * w;
-+ p = 1.115787767802518096e-17 + p * w;
-+ p = -1.333171662854620906e-16 + p * w;
-+ p = 2.0972767875968561637e-17 + p * w;
-+ p = 6.6376381343583238325e-15 + p * w;
-+ p = -4.0545662729752068639e-14 + p * w;
-+ p = -8.1519341976054721522e-14 + p * w;
-+ p = 2.6335093153082322977e-12 + p * w;
-+ p = -1.2975133253453532498e-11 + p * w;
-+ p = -5.4154120542946279317e-11 + p * w;
-+ p = 1.051212273321532285e-09 + p * w;
-+ p = -4.1126339803469836976e-09 + p * w;
-+ p = -2.9070369957882005086e-08 + p * w;
-+ p = 4.2347877827932403518e-07 + p * w;
-+ p = -1.3654692000834678645e-06 + p * w;
-+ p = -1.3882523362786468719e-05 + p * w;
-+ p = 0.0001867342080340571352 + p * w;
-+ p = -0.00074070253416626697512 + p * w;
-+ p = -0.0060336708714301490533 + p * w;
-+ p = 0.24015818242558961693 + p * w;
-+ p = 1.6536545626831027356 + p * w;
-+ } else if (w < 16.000000) {
-+ w = sqrt(w) - 3.250000;
-+ p = 2.2137376921775787049e-09;
-+ p = 9.0756561938885390979e-08 + p * w;
-+ p = -2.7517406297064545428e-07 + p * w;
-+ p = 1.8239629214389227755e-08 + p * w;
-+ p = 1.5027403968909827627e-06 + p * w;
-+ p = -4.013867526981545969e-06 + p * w;
-+ p = 2.9234449089955446044e-06 + p * w;
-+ p = 1.2475304481671778723e-05 + p * w;
-+ p = -4.7318229009055733981e-05 + p * w;
-+ p = 6.8284851459573175448e-05 + p * w;
-+ p = 2.4031110387097893999e-05 + p * w;
-+ p = -0.0003550375203628474796 + p * w;
-+ p = 0.00095328937973738049703 + p * w;
-+ p = -0.0016882755560235047313 + p * w;
-+ p = 0.0024914420961078508066 + p * w;
-+ p = -0.0037512085075692412107 + p * w;
-+ p = 0.005370914553590063617 + p * w;
-+ p = 1.0052589676941592334 + p * w;
-+ p = 3.0838856104922207635 + p * w;
-+ } else {
-+ w = sqrt(w) - 5.000000;
-+ p = -2.7109920616438573243e-11;
-+ p = -2.5556418169965252055e-10 + p * w;
-+ p = 1.5076572693500548083e-09 + p * w;
-+ p = -3.7894654401267369937e-09 + p * w;
-+ p = 7.6157012080783393804e-09 + p * w;
-+ p = -1.4960026627149240478e-08 + p * w;
-+ p = 2.9147953450901080826e-08 + p * w;
-+ p = -6.7711997758452339498e-08 + p * w;
-+ p = 2.2900482228026654717e-07 + p * w;
-+ p = -9.9298272942317002539e-07 + p * w;
-+ p = 4.5260625972231537039e-06 + p * w;
-+ p = -1.9681778105531670567e-05 + p * w;
-+ p = 7.5995277030017761139e-05 + p * w;
-+ p = -0.00021503011930044477347 + p * w;
-+ p = -0.00013871931833623122026 + p * w;
-+ p = 1.0103004648645343977 + p * w;
-+ p = 4.8499064014085844221 + p * w;
-+ }
-+ return p * x;
-+ }
-+
-+ double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) {
-+ auto m = Catch::Benchmark::Detail::mean(first, last);
-+ double variance = std::accumulate(first, last, 0., [m](double a, double b) {
-+ double diff = b - m;
-+ return a + diff * diff;
-+ }) / (last - first);
-+ return std::sqrt(variance);
-+ }
-+
-+}
-+
-+namespace Catch {
-+ namespace Benchmark {
-+ namespace Detail {
-+
-+ double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) {
-+ auto count = last - first;
-+ double idx = (count - 1) * k / static_cast<double>(q);
-+ int j = static_cast<int>(idx);
-+ double g = idx - j;
-+ std::nth_element(first, first + j, last);
-+ auto xj = first[j];
-+ if (g == 0) return xj;
-+
-+ auto xj1 = *std::min_element(first + (j + 1), last);
-+ return xj + g * (xj1 - xj);
-+ }
-+
-+ double erfc_inv(double x) {
-+ return erf_inv(1.0 - x);
-+ }
-+
-+ double normal_quantile(double p) {
-+ static const double ROOT_TWO = std::sqrt(2.0);
-+
-+ double result = 0.0;
-+ assert(p >= 0 && p <= 1);
-+ if (p < 0 || p > 1) {
-+ return result;
-+ }
-+
-+ result = -erfc_inv(2.0 * p);
-+ // result *= normal distribution standard deviation (1.0) * sqrt(2)
-+ result *= /*sd * */ ROOT_TWO;
-+ // result += normal disttribution mean (0)
-+ return result;
-+ }
-+
-+ double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n) {
-+ double sb = stddev.point;
-+ double mn = mean.point / n;
-+ double mg_min = mn / 2.;
-+ double sg = (std::min)(mg_min / 4., sb / std::sqrt(n));
-+ double sg2 = sg * sg;
-+ double sb2 = sb * sb;
-+
-+ auto c_max = [n, mn, sb2, sg2](double x) -> double {
-+ double k = mn - x;
-+ double d = k * k;
-+ double nd = n * d;
-+ double k0 = -n * nd;
-+ double k1 = sb2 - n * sg2 + nd;
-+ double det = k1 * k1 - 4 * sg2 * k0;
-+ return (int)(-2. * k0 / (k1 + std::sqrt(det)));
-+ };
-+
-+ auto var_out = [n, sb2, sg2](double c) {
-+ double nc = n - c;
-+ return (nc / n) * (sb2 - nc * sg2);
-+ };
-+
-+ return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2;
-+ }
-+
-+ bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {
-+ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
-+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
-+ static std::random_device entropy;
-+ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-+
-+ auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
-+
-+ auto mean = &Detail::mean<std::vector<double>::iterator>;
-+ auto stddev = &standard_deviation;
-+
-+#if defined(CATCH_CONFIG_USE_ASYNC)
-+ auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {
-+ auto seed = entropy();
-+ return std::async(std::launch::async, [=] {
-+ std::mt19937 rng(seed);
-+ auto resampled = resample(rng, n_resamples, first, last, f);
-+ return bootstrap(confidence_level, first, last, resampled, f);
-+ });
-+ };
-+
-+ auto mean_future = Estimate(mean);
-+ auto stddev_future = Estimate(stddev);
-+
-+ auto mean_estimate = mean_future.get();
-+ auto stddev_estimate = stddev_future.get();
-+#else
-+ auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {
-+ auto seed = entropy();
-+ std::mt19937 rng(seed);
-+ auto resampled = resample(rng, n_resamples, first, last, f);
-+ return bootstrap(confidence_level, first, last, resampled, f);
-+ };
-+
-+ auto mean_estimate = Estimate(mean);
-+ auto stddev_estimate = Estimate(stddev);
-+#endif // CATCH_USE_ASYNC
-+
-+ double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n);
-+
-+ return { mean_estimate, stddev_estimate, outlier_variance };
-+ }
-+ } // namespace Detail
-+ } // namespace Benchmark
-+} // namespace Catch
-+
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-+// end catch_stats.cpp
- // start catch_approx.cpp
-
- #include <cmath>
-@@ -5365,21 +7901,22 @@
- bool Approx::equalityComparisonImpl(const double other) const {
- // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
- // Thanks to Richard Harris for his help refining the scaled margin value
-- return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
-+ return marginComparison(m_value, other, m_margin)
-+ || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));
- }
-
-- void Approx::setMargin(double margin) {
-- CATCH_ENFORCE(margin >= 0,
-- "Invalid Approx::margin: " << margin << '.'
-+ void Approx::setMargin(double newMargin) {
-+ CATCH_ENFORCE(newMargin >= 0,
-+ "Invalid Approx::margin: " << newMargin << '.'
- << " Approx::Margin has to be non-negative.");
-- m_margin = margin;
-+ m_margin = newMargin;
- }
-
-- void Approx::setEpsilon(double epsilon) {
-- CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
-- "Invalid Approx::epsilon: " << epsilon << '.'
-+ void Approx::setEpsilon(double newEpsilon) {
-+ CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
-+ "Invalid Approx::epsilon: " << newEpsilon << '.'
- << " Approx::epsilon has to be in [0, 1]");
-- m_epsilon = epsilon;
-+ m_epsilon = newEpsilon;
- }
-
- } // end namespace Detail
-@@ -5401,58 +7938,6 @@
- // end catch_approx.cpp
- // start catch_assertionhandler.cpp
-
--// start catch_context.h
--
--#include <memory>
--
--namespace Catch {
--
-- struct IResultCapture;
-- struct IRunner;
-- struct IConfig;
-- struct IMutableContext;
--
-- using IConfigPtr = std::shared_ptr<IConfig const>;
--
-- struct IContext
-- {
-- virtual ~IContext();
--
-- virtual IResultCapture* getResultCapture() = 0;
-- virtual IRunner* getRunner() = 0;
-- virtual IConfigPtr const& getConfig() const = 0;
-- };
--
-- struct IMutableContext : IContext
-- {
-- virtual ~IMutableContext();
-- virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
-- virtual void setRunner( IRunner* runner ) = 0;
-- virtual void setConfig( IConfigPtr const& config ) = 0;
--
-- private:
-- static IMutableContext *currentContext;
-- friend IMutableContext& getCurrentMutableContext();
-- friend void cleanUpContext();
-- static void createContext();
-- };
--
-- inline IMutableContext& getCurrentMutableContext()
-- {
-- if( !IMutableContext::currentContext )
-- IMutableContext::createContext();
-- return *IMutableContext::currentContext;
-- }
--
-- inline IContext& getCurrentContext()
-- {
-- return getCurrentMutableContext();
-- }
--
-- void cleanUpContext();
--}
--
--// end catch_context.h
- // start catch_debugger.h
-
- namespace Catch {
-@@ -5461,7 +7946,24 @@
-
- #ifdef CATCH_PLATFORM_MAC
-
-- #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
-+ #if defined(__i386__) || defined(__x86_64__)
-+ #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
-+ #elif defined(__aarch64__)
-+ #define CATCH_TRAP() __asm__(".inst 0xd4200000")
-+ #endif
-+
-+#elif defined(CATCH_PLATFORM_IPHONE)
-+
-+ // use inline assembler
-+ #if defined(__i386__) || defined(__x86_64__)
-+ #define CATCH_TRAP() __asm__("int $3")
-+ #elif defined(__aarch64__)
-+ #define CATCH_TRAP() __asm__(".inst 0xd4200000")
-+ #elif defined(__arm__) && !defined(__thumb__)
-+ #define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
-+ #elif defined(__arm__) && defined(__thumb__)
-+ #define CATCH_TRAP() __asm__(".inst 0xde01")
-+ #endif
-
- #elif defined(CATCH_PLATFORM_LINUX)
- // If we can use inline assembler, do it because this allows us to break
-@@ -5481,13 +7983,12 @@
- #define CATCH_TRAP() DebugBreak()
- #endif
-
--#ifdef CATCH_TRAP
-- #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
--#else
-- namespace Catch {
-- inline void doNothing() {}
-- }
-- #define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
-+#ifndef CATCH_BREAK_INTO_DEBUGGER
-+ #ifdef CATCH_TRAP
-+ #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
-+ #else
-+ #define CATCH_BREAK_INTO_DEBUGGER() []{}()
-+ #endif
- #endif
-
- // end catch_debugger.h
-@@ -5495,86 +7996,58 @@
-
- // start catch_fatal_condition.h
-
--// start catch_windows_h_proxy.h
--
--
--#if defined(CATCH_PLATFORM_WINDOWS)
--
--#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
--# define CATCH_DEFINED_NOMINMAX
--# define NOMINMAX
--#endif
--#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
--# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
--# define WIN32_LEAN_AND_MEAN
--#endif
--
--#ifdef __AFXDLL
--#include <AfxWin.h>
--#else
--#include <windows.h>
--#endif
--
--#ifdef CATCH_DEFINED_NOMINMAX
--# undef NOMINMAX
--#endif
--#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
--# undef WIN32_LEAN_AND_MEAN
--#endif
--
--#endif // defined(CATCH_PLATFORM_WINDOWS)
--
--// end catch_windows_h_proxy.h
--#if defined( CATCH_CONFIG_WINDOWS_SEH )
-+#include <cassert>
-
- namespace Catch {
-
-- struct FatalConditionHandler {
--
-- static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
-+ // Wrapper for platform-specific fatal error (signals/SEH) handlers
-+ //
-+ // Tries to be cooperative with other handlers, and not step over
-+ // other handlers. This means that unknown structured exceptions
-+ // are passed on, previous signal handlers are called, and so on.
-+ //
-+ // Can only be instantiated once, and assumes that once a signal
-+ // is caught, the binary will end up terminating. Thus, there
-+ class FatalConditionHandler {
-+ bool m_started = false;
-+
-+ // Install/disengage implementation for specific platform.
-+ // Should be if-defed to work on current platform, can assume
-+ // engage-disengage 1:1 pairing.
-+ void engage_platform();
-+ void disengage_platform();
-+ public:
-+ // Should also have platform-specific implementations as needed
- FatalConditionHandler();
-- static void reset();
- ~FatalConditionHandler();
-
-- private:
-- static bool isSet;
-- static ULONG guaranteeSize;
-- static PVOID exceptionHandlerHandle;
-- };
--
--} // namespace Catch
--
--#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
--
--#include <signal.h>
--
--namespace Catch {
--
-- struct FatalConditionHandler {
--
-- static bool isSet;
-- static struct sigaction oldSigActions[];
-- static stack_t oldSigStack;
-- static char altStackMem[];
--
-- static void handleSignal( int sig );
-+ void engage() {
-+ assert(!m_started && "Handler cannot be installed twice.");
-+ m_started = true;
-+ engage_platform();
-+ }
-
-- FatalConditionHandler();
-- ~FatalConditionHandler();
-- static void reset();
-+ void disengage() {
-+ assert(m_started && "Handler cannot be uninstalled without being installed first");
-+ m_started = false;
-+ disengage_platform();
-+ }
- };
-
--} // namespace Catch
--
--#else
--
--namespace Catch {
-- struct FatalConditionHandler {
-- void reset();
-+ //! Simple RAII guard for (dis)engaging the FatalConditionHandler
-+ class FatalConditionHandlerGuard {
-+ FatalConditionHandler* m_handler;
-+ public:
-+ FatalConditionHandlerGuard(FatalConditionHandler* handler):
-+ m_handler(handler) {
-+ m_handler->engage();
-+ }
-+ ~FatalConditionHandlerGuard() {
-+ m_handler->disengage();
-+ }
- };
--}
-
--#endif
-+} // end namespace Catch
-
- // end catch_fatal_condition.h
- #include <string>
-@@ -5634,14 +8107,20 @@
- void sectionEnded( SectionEndInfo const& endInfo ) override;
- void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
-
-- auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
-+ auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ void benchmarkPreparing( std::string const& name ) override;
- void benchmarkStarting( BenchmarkInfo const& info ) override;
-- void benchmarkEnded( BenchmarkStats const& stats ) override;
-+ void benchmarkEnded( BenchmarkStats<> const& stats ) override;
-+ void benchmarkFailed( std::string const& error ) override;
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
- void pushScopedMessage( MessageInfo const& message ) override;
- void popScopedMessage( MessageInfo const& message ) override;
-
-+ void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
-+
- std::string getCurrentTestName() const override;
-
- const AssertionResult* getLastResult() const override;
-@@ -5682,22 +8161,26 @@
- TestRunInfo m_runInfo;
- IMutableContext& m_context;
- TestCase const* m_activeTestCase = nullptr;
-- ITracker* m_testCaseTracker;
-+ ITracker* m_testCaseTracker = nullptr;
- Option<AssertionResult> m_lastResult;
-
- IConfigPtr m_config;
- Totals m_totals;
- IStreamingReporterPtr m_reporter;
- std::vector<MessageInfo> m_messages;
-+ std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
- AssertionInfo m_lastAssertionInfo;
- std::vector<SectionEndInfo> m_unfinishedSections;
- std::vector<ITracker*> m_activeSections;
- TrackerContext m_trackerContext;
-+ FatalConditionHandler m_fatalConditionhandler;
- bool m_lastAssertionPassed = false;
- bool m_shouldReportUnexpected = true;
- bool m_includeSuccessfulResults;
- };
-
-+ void seedRng(IConfig const& config);
-+ unsigned int rngSeed();
- } // end namespace Catch
-
- // end catch_run_context.h
-@@ -5844,7 +8327,7 @@
- }
-
- bool AssertionResult::hasExpression() const {
-- return m_info.capturedExpression[0] != 0;
-+ return !m_info.capturedExpression.empty();
- }
-
- bool AssertionResult::hasMessage() const {
-@@ -5852,16 +8335,22 @@
- }
-
- std::string AssertionResult::getExpression() const {
-- if( isFalseTest( m_info.resultDisposition ) )
-- return "!(" + m_info.capturedExpression + ")";
-- else
-- return m_info.capturedExpression;
-+ // Possibly overallocating by 3 characters should be basically free
-+ std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
-+ if (isFalseTest(m_info.resultDisposition)) {
-+ expr += "!(";
-+ }
-+ expr += m_info.capturedExpression;
-+ if (isFalseTest(m_info.resultDisposition)) {
-+ expr += ')';
-+ }
-+ return expr;
- }
-
- std::string AssertionResult::getExpressionInMacro() const {
- std::string expr;
-- if( m_info.macroName[0] == 0 )
-- expr = m_info.capturedExpression;
-+ if( m_info.macroName.empty() )
-+ expr = static_cast<std::string>(m_info.capturedExpression);
- else {
- expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
- expr += m_info.macroName;
-@@ -5896,32 +8385,6 @@
-
- } // end namespace Catch
- // end catch_assertionresult.cpp
--// start catch_benchmark.cpp
--
--namespace Catch {
--
-- auto BenchmarkLooper::getResolution() -> uint64_t {
-- return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple();
-- }
--
-- void BenchmarkLooper::reportStart() {
-- getResultCapture().benchmarkStarting( { m_name } );
-- }
-- auto BenchmarkLooper::needsMoreIterations() -> bool {
-- auto elapsed = m_timer.getElapsedNanoseconds();
--
-- // Exponentially increasing iterations until we're confident in our timer resolution
-- if( elapsed < m_resolution ) {
-- m_iterationsToRun *= 10;
-- return true;
-- }
--
-- getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } );
-- return false;
-- }
--
--} // end namespace Catch
--// end catch_benchmark.cpp
- // start catch_capture_matchers.cpp
-
- namespace Catch {
-@@ -6067,6 +8530,9 @@
- m_suffix = false;
- auto width = m_column.m_width - indent();
- m_end = m_pos;
-+ if (line()[m_pos] == '\n') {
-+ ++m_end;
-+ }
- while (m_end < line().size() && line()[m_end] != '\n')
- ++m_end;
-
-@@ -6325,6 +8791,7 @@
- // ----------- end of #include from clara_textflow.hpp -----------
- // ........... back in clara.hpp
-
-+#include <cctype>
- #include <string>
- #include <memory>
- #include <set>
-@@ -6617,7 +9084,7 @@
- }
- inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
- std::string srcLC = source;
-- std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
-+ std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( unsigned char c ) { return static_cast<char>( std::tolower(c) ); } );
- if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
- target = true;
- else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
-@@ -7265,9 +9732,14 @@
- if( !line.empty() && !startsWith( line, '#' ) ) {
- if( !startsWith( line, '"' ) )
- line = '"' + line + '"';
-- config.testsOrTags.push_back( line + ',' );
-+ config.testsOrTags.push_back( line );
-+ config.testsOrTags.emplace_back( "," );
- }
- }
-+ //Remove comma in the end
-+ if(!config.testsOrTags.empty())
-+ config.testsOrTags.erase( config.testsOrTags.end()-1 );
-+
- return ParserResult::ok( ParseResultType::Matched );
- };
- auto const setTestOrder = [&]( std::string const& order ) {
-@@ -7302,14 +9774,16 @@
- };
- auto const setWaitForKeypress = [&]( std::string const& keypress ) {
- auto keypressLc = toLower( keypress );
-- if( keypressLc == "start" )
-+ if (keypressLc == "never")
-+ config.waitForKeypress = WaitForKeypress::Never;
-+ else if( keypressLc == "start" )
- config.waitForKeypress = WaitForKeypress::BeforeStart;
- else if( keypressLc == "exit" )
- config.waitForKeypress = WaitForKeypress::BeforeExit;
- else if( keypressLc == "both" )
- config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
- else
-- return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
-+ return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" );
- return ParserResult::ok( ParseResultType::Matched );
- };
- auto const setVerbosity = [&]( std::string const& verbosity ) {
-@@ -7379,6 +9853,9 @@
- | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
- ["-d"]["--durations"]
- ( "show test durations" )
-+ | Opt( config.minDuration, "seconds" )
-+ ["-D"]["--min-duration"]
-+ ( "show test durations for tests taking at least the given number of seconds" )
- | Opt( loadTestNamesFromFile, "filename" )
- ["-f"]["--input-file"]
- ( "load test names to run from a file" )
-@@ -7409,13 +9886,24 @@
- | Opt( config.libIdentify )
- ["--libidentify"]
- ( "report name and version according to libidentify standard" )
-- | Opt( setWaitForKeypress, "start|exit|both" )
-+ | Opt( setWaitForKeypress, "never|start|exit|both" )
- ["--wait-for-keypress"]
- ( "waits for a keypress before exiting" )
-- | Opt( config.benchmarkResolutionMultiple, "multiplier" )
-- ["--benchmark-resolution-multiple"]
-- ( "multiple of clock resolution to run benchmarks" )
--
-+ | Opt( config.benchmarkSamples, "samples" )
-+ ["--benchmark-samples"]
-+ ( "number of samples to collect (default: 100)" )
-+ | Opt( config.benchmarkResamples, "resamples" )
-+ ["--benchmark-resamples"]
-+ ( "number of resamples for the bootstrap (default: 100000)" )
-+ | Opt( config.benchmarkConfidenceInterval, "confidence interval" )
-+ ["--benchmark-confidence-interval"]
-+ ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" )
-+ | Opt( config.benchmarkNoAnalysis )
-+ ["--benchmark-no-analysis"]
-+ ( "perform only measurements; do not perform any analysis" )
-+ | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" )
-+ ["--benchmark-warmup-time"]
-+ ( "amount of time in milliseconds spent on warming up each test (default: 100)" )
- | Arg( config.testsOrTags, "test name|pattern|tags" )
- ( "which test or tests to use" );
-
-@@ -7431,9 +9919,6 @@
-
- namespace Catch {
-
-- bool SourceLineInfo::empty() const noexcept {
-- return file[0] == '\0';
-- }
- bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
- return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
- }
-@@ -7469,14 +9954,23 @@
- : m_data( data ),
- m_stream( openStream() )
- {
-- TestSpecParser parser(ITagAliasRegistry::get());
-- if (data.testsOrTags.empty()) {
-- parser.parse("~[.]"); // All not hidden tests
-+ // We need to trim filter specs to avoid trouble with superfluous
-+ // whitespace (esp. important for bdd macros, as those are manually
-+ // aligned with whitespace).
-+
-+ for (auto& elem : m_data.testsOrTags) {
-+ elem = trim(elem);
- }
-- else {
-+ for (auto& elem : m_data.sectionsToRun) {
-+ elem = trim(elem);
-+ }
-+
-+ TestSpecParser parser(ITagAliasRegistry::get());
-+ if (!m_data.testsOrTags.empty()) {
- m_hasTestFilters = true;
-- for( auto const& testOrTags : data.testsOrTags )
-- parser.parse( testOrTags );
-+ for (auto const& testOrTags : m_data.testsOrTags) {
-+ parser.parse(testOrTags);
-+ }
- }
- m_testSpec = parser.testSpec();
- }
-@@ -7509,15 +10003,21 @@
- bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); }
- bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
- ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
-+ double Config::minDuration() const { return m_data.minDuration; }
- RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
- unsigned int Config::rngSeed() const { return m_data.rngSeed; }
-- int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; }
- UseColour::YesOrNo Config::useColour() const { return m_data.useColour; }
- bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
- int Config::abortAfter() const { return m_data.abortAfter; }
- bool Config::showInvisibles() const { return m_data.showInvisibles; }
- Verbosity Config::verbosity() const { return m_data.verbosity; }
-
-+ bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; }
-+ int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
-+ double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
-+ unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
-+ std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
-+
- IStream const* Config::openStream() {
- return Catch::makeStream(m_data.outputFilename);
- }
-@@ -7546,6 +10046,36 @@
- }
-
- // end catch_errno_guard.h
-+// start catch_windows_h_proxy.h
-+
-+
-+#if defined(CATCH_PLATFORM_WINDOWS)
-+
-+#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
-+# define CATCH_DEFINED_NOMINMAX
-+# define NOMINMAX
-+#endif
-+#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
-+# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
-+# define WIN32_LEAN_AND_MEAN
-+#endif
-+
-+#ifdef __AFXDLL
-+#include <AfxWin.h>
-+#else
-+#include <windows.h>
-+#endif
-+
-+#ifdef CATCH_DEFINED_NOMINMAX
-+# undef NOMINMAX
-+#endif
-+#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
-+# undef WIN32_LEAN_AND_MEAN
-+#endif
-+
-+#endif // defined(CATCH_PLATFORM_WINDOWS)
-+
-+// end catch_windows_h_proxy.h
- #include <sstream>
-
- namespace Catch {
-@@ -7557,7 +10087,7 @@
- };
-
- struct NoColourImpl : IColourImpl {
-- void use( Colour::Code ) {}
-+ void use( Colour::Code ) override {}
-
- static IColourImpl* instance() {
- static NoColourImpl s_instance;
-@@ -7591,7 +10121,7 @@
- originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
- }
-
-- virtual void use( Colour::Code _colourCode ) override {
-+ void use( Colour::Code _colourCode ) override {
- switch( _colourCode ) {
- case Colour::None: return setTextAttribute( originalForegroundAttributes );
- case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
-@@ -7654,7 +10184,7 @@
- // https://github.com/philsquared/Catch/pull/131
- class PosixColourImpl : public IColourImpl {
- public:
-- virtual void use( Colour::Code _colourCode ) override {
-+ void use( Colour::Code _colourCode ) override {
- switch( _colourCode ) {
- case Colour::None:
- case Colour::White: return setColour( "[0m" );
-@@ -7682,13 +10212,14 @@
-
- private:
- void setColour( const char* _escapeCode ) {
-- Catch::cout() << '\033' << _escapeCode;
-+ getCurrentContext().getConfig()->stream()
-+ << '\033' << _escapeCode;
- }
- };
-
- bool useColourOnPlatform() {
- return
--#ifdef CATCH_PLATFORM_MAC
-+#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
- !isDebuggerActive() &&
- #endif
- #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
-@@ -7729,13 +10260,13 @@
- namespace Catch {
-
- Colour::Colour( Code _colourCode ) { use( _colourCode ); }
-- Colour::Colour( Colour&& rhs ) noexcept {
-- m_moved = rhs.m_moved;
-- rhs.m_moved = true;
-- }
-- Colour& Colour::operator=( Colour&& rhs ) noexcept {
-- m_moved = rhs.m_moved;
-- rhs.m_moved = true;
-+ Colour::Colour( Colour&& other ) noexcept {
-+ m_moved = other.m_moved;
-+ other.m_moved = true;
-+ }
-+ Colour& Colour::operator=( Colour&& other ) noexcept {
-+ m_moved = other.m_moved;
-+ other.m_moved = true;
- return *this;
- }
-
-@@ -7743,7 +10274,13 @@
-
- void Colour::use( Code _colourCode ) {
- static IColourImpl* impl = platformColourInstance();
-- impl->use( _colourCode );
-+ // Strictly speaking, this cannot possibly happen.
-+ // However, under some conditions it does happen (see #1626),
-+ // and this change is small enough that we can let practicality
-+ // triumph over purity in this case.
-+ if (impl != nullptr) {
-+ impl->use( _colourCode );
-+ }
- }
-
- std::ostream& operator << ( std::ostream& os, Colour const& ) {
-@@ -7764,27 +10301,27 @@
- class Context : public IMutableContext, NonCopyable {
-
- public: // IContext
-- virtual IResultCapture* getResultCapture() override {
-+ IResultCapture* getResultCapture() override {
- return m_resultCapture;
- }
-- virtual IRunner* getRunner() override {
-+ IRunner* getRunner() override {
- return m_runner;
- }
-
-- virtual IConfigPtr const& getConfig() const override {
-+ IConfigPtr const& getConfig() const override {
- return m_config;
- }
-
-- virtual ~Context() override;
-+ ~Context() override;
-
- public: // IMutableContext
-- virtual void setResultCapture( IResultCapture* resultCapture ) override {
-+ void setResultCapture( IResultCapture* resultCapture ) override {
- m_resultCapture = resultCapture;
- }
-- virtual void setRunner( IRunner* runner ) override {
-+ void setRunner( IRunner* runner ) override {
- m_runner = runner;
- }
-- virtual void setConfig( IConfigPtr const& config ) override {
-+ void setConfig( IConfigPtr const& config ) override {
- m_config = config;
- }
-
-@@ -7810,6 +10347,12 @@
- IContext::~IContext() = default;
- IMutableContext::~IMutableContext() = default;
- Context::~Context() = default;
-+
-+ SimplePcg32& rng() {
-+ static SimplePcg32 s_rng;
-+ return s_rng;
-+ }
-+
- }
- // end catch_context.cpp
- // start catch_debug_console.cpp
-@@ -7823,7 +10366,16 @@
- }
-
- // end catch_debug_console.h
--#ifdef CATCH_PLATFORM_WINDOWS
-+#if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
-+#include <android/log.h>
-+
-+ namespace Catch {
-+ void writeToDebugConsole( std::string const& text ) {
-+ __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
-+ }
-+ }
-+
-+#elif defined(CATCH_PLATFORM_WINDOWS)
-
- namespace Catch {
- void writeToDebugConsole( std::string const& text ) {
-@@ -7844,25 +10396,28 @@
- // end catch_debug_console.cpp
- // start catch_debugger.cpp
-
--#ifdef CATCH_PLATFORM_MAC
-+#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
-
--# include <assert.h>
--# include <stdbool.h>
-+# include <cassert>
- # include <sys/types.h>
- # include <unistd.h>
--# include <sys/sysctl.h>
- # include <cstddef>
- # include <ostream>
-
--namespace Catch {
-+#ifdef __apple_build_version__
-+ // These headers will only compile with AppleClang (XCode)
-+ // For other compilers (Clang, GCC, ... ) we need to exclude them
-+# include <sys/sysctl.h>
-+#endif
-
-+ namespace Catch {
-+ #ifdef __apple_build_version__
- // The following function is taken directly from the following technical note:
-- // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
-+ // https://developer.apple.com/library/archive/qa/qa1361/_index.html
-
- // Returns true if the current process is being debugged (either
- // running under the debugger or has a debugger attached post facto).
- bool isDebuggerActive(){
--
- int mib[4];
- struct kinfo_proc info;
- std::size_t size;
-@@ -7892,6 +10447,12 @@
-
- return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
- }
-+ #else
-+ bool isDebuggerActive() {
-+ // We need to find another way to determine this for non-appleclang compilers on macOS
-+ return false;
-+ }
-+ #endif
- } // namespace Catch
-
- #elif defined(CATCH_PLATFORM_LINUX)
-@@ -7962,6 +10523,8 @@
- // end catch_decomposer.cpp
- // start catch_enforce.cpp
-
-+#include <stdexcept>
-+
- namespace Catch {
- #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
- [[noreturn]]
-@@ -7971,8 +10534,116 @@
- std::terminate();
- }
- #endif
-+
-+ [[noreturn]]
-+ void throw_logic_error(std::string const& msg) {
-+ throw_exception(std::logic_error(msg));
-+ }
-+
-+ [[noreturn]]
-+ void throw_domain_error(std::string const& msg) {
-+ throw_exception(std::domain_error(msg));
-+ }
-+
-+ [[noreturn]]
-+ void throw_runtime_error(std::string const& msg) {
-+ throw_exception(std::runtime_error(msg));
-+ }
-+
- } // namespace Catch;
- // end catch_enforce.cpp
-+// start catch_enum_values_registry.cpp
-+// start catch_enum_values_registry.h
-+
-+#include <vector>
-+#include <memory>
-+
-+namespace Catch {
-+
-+ namespace Detail {
-+
-+ std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
-+
-+ class EnumValuesRegistry : public IMutableEnumValuesRegistry {
-+
-+ std::vector<std::unique_ptr<EnumInfo>> m_enumInfos;
-+
-+ EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override;
-+ };
-+
-+ std::vector<StringRef> parseEnums( StringRef enums );
-+
-+ } // Detail
-+
-+} // Catch
-+
-+// end catch_enum_values_registry.h
-+
-+#include <map>
-+#include <cassert>
-+
-+namespace Catch {
-+
-+ IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {}
-+
-+ namespace Detail {
-+
-+ namespace {
-+ // Extracts the actual name part of an enum instance
-+ // In other words, it returns the Blue part of Bikeshed::Colour::Blue
-+ StringRef extractInstanceName(StringRef enumInstance) {
-+ // Find last occurrence of ":"
-+ size_t name_start = enumInstance.size();
-+ while (name_start > 0 && enumInstance[name_start - 1] != ':') {
-+ --name_start;
-+ }
-+ return enumInstance.substr(name_start, enumInstance.size() - name_start);
-+ }
-+ }
-+
-+ std::vector<StringRef> parseEnums( StringRef enums ) {
-+ auto enumValues = splitStringRef( enums, ',' );
-+ std::vector<StringRef> parsed;
-+ parsed.reserve( enumValues.size() );
-+ for( auto const& enumValue : enumValues ) {
-+ parsed.push_back(trim(extractInstanceName(enumValue)));
-+ }
-+ return parsed;
-+ }
-+
-+ EnumInfo::~EnumInfo() {}
-+
-+ StringRef EnumInfo::lookup( int value ) const {
-+ for( auto const& valueToName : m_values ) {
-+ if( valueToName.first == value )
-+ return valueToName.second;
-+ }
-+ return "{** unexpected enum value **}"_sr;
-+ }
-+
-+ std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
-+ std::unique_ptr<EnumInfo> enumInfo( new EnumInfo );
-+ enumInfo->m_name = enumName;
-+ enumInfo->m_values.reserve( values.size() );
-+
-+ const auto valueNames = Catch::Detail::parseEnums( allValueNames );
-+ assert( valueNames.size() == values.size() );
-+ std::size_t i = 0;
-+ for( auto value : values )
-+ enumInfo->m_values.emplace_back(value, valueNames[i++]);
-+
-+ return enumInfo;
-+ }
-+
-+ EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
-+ m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
-+ return *m_enumInfos.back();
-+ }
-+
-+ } // Detail
-+} // Catch
-+
-+// end catch_enum_values_registry.cpp
- // start catch_errno_guard.cpp
-
- #include <cerrno>
-@@ -7996,7 +10667,7 @@
- public:
- ~ExceptionTranslatorRegistry();
- virtual void registerTranslator( const IExceptionTranslator* translator );
-- virtual std::string translateActiveException() const override;
-+ std::string translateActiveException() const override;
- std::string tryTranslators() const;
-
- private:
-@@ -8061,54 +10732,82 @@
- }
- }
-
-+ std::string ExceptionTranslatorRegistry::tryTranslators() const {
-+ if (m_translators.empty()) {
-+ std::rethrow_exception(std::current_exception());
-+ } else {
-+ return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
-+ }
-+ }
-+
- #else // ^^ Exceptions are enabled // Exceptions are disabled vv
- std::string ExceptionTranslatorRegistry::translateActiveException() const {
- CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
- }
--#endif
-
- std::string ExceptionTranslatorRegistry::tryTranslators() const {
-- if( m_translators.empty() )
-- std::rethrow_exception(std::current_exception());
-- else
-- return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
-+ CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
- }
-+#endif
-+
- }
- // end catch_exception_translator_registry.cpp
- // start catch_fatal_condition.cpp
-
--#if defined(__GNUC__)
--# pragma GCC diagnostic push
--# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
--#endif
-+#include <algorithm>
-+
-+#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
-+
-+namespace Catch {
-+
-+ // If neither SEH nor signal handling is required, the handler impls
-+ // do not have to do anything, and can be empty.
-+ void FatalConditionHandler::engage_platform() {}
-+ void FatalConditionHandler::disengage_platform() {}
-+ FatalConditionHandler::FatalConditionHandler() = default;
-+ FatalConditionHandler::~FatalConditionHandler() = default;
-+
-+} // end namespace Catch
-+
-+#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
-+
-+#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
-+#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
-+#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
-
- #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
-
- namespace {
-- // Report the error condition
-+ //! Signals fatal error message to the run context
- void reportFatal( char const * const message ) {
- Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
- }
--}
-
--#endif // signals/SEH handling
-+ //! Minimal size Catch2 needs for its own fatal error handling.
-+ //! Picked anecdotally, so it might not be sufficient on all
-+ //! platforms, and for all configurations.
-+ constexpr std::size_t minStackSizeForErrors = 32 * 1024;
-+} // end unnamed namespace
-+
-+#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
-
- #if defined( CATCH_CONFIG_WINDOWS_SEH )
-
- namespace Catch {
-+
- struct SignalDefs { DWORD id; const char* name; };
-
- // There is no 1-1 mapping between signals and windows exceptions.
- // Windows can easily distinguish between SO and SigSegV,
- // but SigInt, SigTerm, etc are handled differently.
- static SignalDefs signalDefs[] = {
-- { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
-- { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
-- { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
-- { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
-+ { static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" },
-+ { static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" },
-+ { static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" },
-+ { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
- };
-
-- LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
-+ static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
- for (auto const& def : signalDefs) {
- if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
- reportFatal(def.name);
-@@ -8119,38 +10818,50 @@
- return EXCEPTION_CONTINUE_SEARCH;
- }
-
-+ // Since we do not support multiple instantiations, we put these
-+ // into global variables and rely on cleaning them up in outlined
-+ // constructors/destructors
-+ static PVOID exceptionHandlerHandle = nullptr;
-+
-+ // For MSVC, we reserve part of the stack memory for handling
-+ // memory overflow structured exception.
- FatalConditionHandler::FatalConditionHandler() {
-- isSet = true;
-- // 32k seems enough for Catch to handle stack overflow,
-- // but the value was found experimentally, so there is no strong guarantee
-- guaranteeSize = 32 * 1024;
-- exceptionHandlerHandle = nullptr;
-+ ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
-+ if (!SetThreadStackGuarantee(&guaranteeSize)) {
-+ // We do not want to fully error out, because needing
-+ // the stack reserve should be rare enough anyway.
-+ Catch::cerr()
-+ << "Failed to reserve piece of stack."
-+ << " Stack overflows will not be reported successfully.";
-+ }
-+ }
-+
-+ // We do not attempt to unset the stack guarantee, because
-+ // Windows does not support lowering the stack size guarantee.
-+ FatalConditionHandler::~FatalConditionHandler() = default;
-+
-+ void FatalConditionHandler::engage_platform() {
- // Register as first handler in current chain
- exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
-- // Pass in guarantee size to be filled
-- SetThreadStackGuarantee(&guaranteeSize);
-+ if (!exceptionHandlerHandle) {
-+ CATCH_RUNTIME_ERROR("Could not register vectored exception handler");
-+ }
- }
-
-- void FatalConditionHandler::reset() {
-- if (isSet) {
-- RemoveVectoredExceptionHandler(exceptionHandlerHandle);
-- SetThreadStackGuarantee(&guaranteeSize);
-- exceptionHandlerHandle = nullptr;
-- isSet = false;
-+ void FatalConditionHandler::disengage_platform() {
-+ if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
-+ CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler");
- }
-+ exceptionHandlerHandle = nullptr;
- }
-
-- FatalConditionHandler::~FatalConditionHandler() {
-- reset();
-- }
-+} // end namespace Catch
-
--bool FatalConditionHandler::isSet = false;
--ULONG FatalConditionHandler::guaranteeSize = 0;
--PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
-+#endif // CATCH_CONFIG_WINDOWS_SEH
-
--} // namespace Catch
-+#if defined( CATCH_CONFIG_POSIX_SIGNALS )
-
--#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
-+#include <signal.h>
-
- namespace Catch {
-
-@@ -8159,10 +10870,6 @@
- const char* name;
- };
-
-- // 32kb for the alternate stack seems to be sufficient. However, this value
-- // is experimentally determined, so that's not guaranteed.
-- constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
--
- static SignalDefs signalDefs[] = {
- { SIGINT, "SIGINT - Terminal interrupt signal" },
- { SIGILL, "SIGILL - Illegal instruction signal" },
-@@ -8172,7 +10879,32 @@
- { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
- };
-
-- void FatalConditionHandler::handleSignal( int sig ) {
-+// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
-+// which is zero initialization, but not explicit. We want to avoid
-+// that.
-+#if defined(__GNUC__)
-+# pragma GCC diagnostic push
-+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
-+#endif
-+
-+ static char* altStackMem = nullptr;
-+ static std::size_t altStackSize = 0;
-+ static stack_t oldSigStack{};
-+ static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
-+
-+ static void restorePreviousSignalHandlers() {
-+ // We set signal handlers back to the previous ones. Hopefully
-+ // nobody overwrote them in the meantime, and doesn't expect
-+ // their signal handlers to live past ours given that they
-+ // installed them after ours..
-+ for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
-+ sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
-+ }
-+ // Return the old stack
-+ sigaltstack(&oldSigStack, nullptr);
-+ }
-+
-+ static void handleSignal( int sig ) {
- char const * name = "<unknown signal>";
- for (auto const& def : signalDefs) {
- if (sig == def.id) {
-@@ -8180,16 +10912,33 @@
- break;
- }
- }
-- reset();
-- reportFatal(name);
-+ // We need to restore previous signal handlers and let them do
-+ // their thing, so that the users can have the debugger break
-+ // when a signal is raised, and so on.
-+ restorePreviousSignalHandlers();
-+ reportFatal( name );
- raise( sig );
- }
-
- FatalConditionHandler::FatalConditionHandler() {
-- isSet = true;
-+ assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
-+ if (altStackSize == 0) {
-+ altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
-+ }
-+ altStackMem = new char[altStackSize]();
-+ }
-+
-+ FatalConditionHandler::~FatalConditionHandler() {
-+ delete[] altStackMem;
-+ // We signal that another instance can be constructed by zeroing
-+ // out the pointer.
-+ altStackMem = nullptr;
-+ }
-+
-+ void FatalConditionHandler::engage_platform() {
- stack_t sigStack;
- sigStack.ss_sp = altStackMem;
-- sigStack.ss_size = sigStackSize;
-+ sigStack.ss_size = altStackSize;
- sigStack.ss_flags = 0;
- sigaltstack(&sigStack, &oldSigStack);
- struct sigaction sa = { };
-@@ -8201,59 +10950,20 @@
- }
- }
-
-- FatalConditionHandler::~FatalConditionHandler() {
-- reset();
-- }
--
-- void FatalConditionHandler::reset() {
-- if( isSet ) {
-- // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
-- for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
-- sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
-- }
-- // Return the old stack
-- sigaltstack(&oldSigStack, nullptr);
-- isSet = false;
-- }
-- }
--
-- bool FatalConditionHandler::isSet = false;
-- struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
-- stack_t FatalConditionHandler::oldSigStack = {};
-- char FatalConditionHandler::altStackMem[sigStackSize] = {};
--
--} // namespace Catch
--
--#else
--
--namespace Catch {
-- void FatalConditionHandler::reset() {}
--}
--
--#endif // signals/SEH handling
--
- #if defined(__GNUC__)
- # pragma GCC diagnostic pop
- #endif
--// end catch_fatal_condition.cpp
--// start catch_generators.cpp
--
--// start catch_random_number_generator.h
--
--#include <algorithm>
--#include <random>
--
--namespace Catch {
-
-- struct IConfig;
-+ void FatalConditionHandler::disengage_platform() {
-+ restorePreviousSignalHandlers();
-+ }
-
-- std::mt19937& rng();
-- void seedRng( IConfig const& config );
-- unsigned int rngSeed();
-+} // end namespace Catch
-
--}
-+#endif // CATCH_CONFIG_POSIX_SIGNALS
-+// end catch_fatal_condition.cpp
-+// start catch_generators.cpp
-
--// end catch_random_number_generator.h
- #include <limits>
- #include <set>
-
-@@ -8261,34 +10971,16 @@
-
- IGeneratorTracker::~IGeneratorTracker() {}
-
--namespace Generators {
--
-- GeneratorBase::~GeneratorBase() {}
--
-- std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize ) {
--
-- assert( selectionSize <= sourceSize );
-- std::vector<size_t> indices;
-- indices.reserve( selectionSize );
-- std::uniform_int_distribution<size_t> uid( 0, sourceSize-1 );
-+const char* GeneratorException::what() const noexcept {
-+ return m_msg;
-+}
-
-- std::set<size_t> seen;
-- // !TBD: improve this algorithm
-- while( indices.size() < selectionSize ) {
-- auto index = uid( rng() );
-- if( seen.insert( index ).second )
-- indices.push_back( index );
-- }
-- return indices;
-- }
-+namespace Generators {
-
-- auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
-- return getResultCapture().acquireGeneratorTracker( lineInfo );
-- }
-+ GeneratorUntypedBase::~GeneratorUntypedBase() {}
-
-- template<>
-- auto all<int>() -> Generator<int> {
-- return range( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
-+ auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
-+ return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );
- }
-
- } // namespace Generators
-@@ -8344,10 +11036,16 @@
-
- void noMatchingTestCases( std::string const& spec ) override;
-
-+ void reportInvalidArguments(std::string const&arg) override;
-+
- static std::set<Verbosity> getSupportedVerbosities();
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ void benchmarkPreparing(std::string const& name) override;
- void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
-- void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override;
-+ void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
-+ void benchmarkFailed(std::string const&) override;
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
- void testRunStarting( TestRunInfo const& testRunInfo ) override;
- void testGroupStarting( GroupInfo const& groupInfo ) override;
-@@ -8538,7 +11236,7 @@
-
- std::size_t listReporters();
-
-- Option<std::size_t> list( Config const& config );
-+ Option<std::size_t> list( std::shared_ptr<Config> const& config );
-
- } // end namespace Catch
-
-@@ -8557,7 +11255,7 @@
- namespace Catch {
-
- std::size_t listTests( Config const& config ) {
-- TestSpec testSpec = config.testSpec();
-+ TestSpec const& testSpec = config.testSpec();
- if( config.hasTestFilters() )
- Catch::cout() << "Matching test cases:\n";
- else {
-@@ -8591,7 +11289,7 @@
- }
-
- std::size_t listTestsNamesOnly( Config const& config ) {
-- TestSpec testSpec = config.testSpec();
-+ TestSpec const& testSpec = config.testSpec();
- std::size_t matchedTests = 0;
- std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
- for( auto const& testCaseInfo : matchedTestCases ) {
-@@ -8613,14 +11311,23 @@
- }
-
- std::string TagInfo::all() const {
-- std::string out;
-- for( auto const& spelling : spellings )
-- out += "[" + spelling + "]";
-+ size_t size = 0;
-+ for (auto const& spelling : spellings) {
-+ // Add 2 for the brackes
-+ size += spelling.size() + 2;
-+ }
-+
-+ std::string out; out.reserve(size);
-+ for (auto const& spelling : spellings) {
-+ out += '[';
-+ out += spelling;
-+ out += ']';
-+ }
- return out;
- }
-
- std::size_t listTags( Config const& config ) {
-- TestSpec testSpec = config.testSpec();
-+ TestSpec const& testSpec = config.testSpec();
- if( config.hasTestFilters() )
- Catch::cout() << "Tags for matching test cases:\n";
- else {
-@@ -8676,15 +11383,16 @@
- return factories.size();
- }
-
-- Option<std::size_t> list( Config const& config ) {
-+ Option<std::size_t> list( std::shared_ptr<Config> const& config ) {
- Option<std::size_t> listedCount;
-- if( config.listTests() )
-- listedCount = listedCount.valueOr(0) + listTests( config );
-- if( config.listTestNamesOnly() )
-- listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
-- if( config.listTags() )
-- listedCount = listedCount.valueOr(0) + listTags( config );
-- if( config.listReporters() )
-+ getCurrentMutableContext().setConfig( config );
-+ if( config->listTests() )
-+ listedCount = listedCount.valueOr(0) + listTests( *config );
-+ if( config->listTestNamesOnly() )
-+ listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );
-+ if( config->listTags() )
-+ listedCount = listedCount.valueOr(0) + listTags( *config );
-+ if( config->listReporters() )
- listedCount = listedCount.valueOr(0) + listReporters();
- return listedCount;
- }
-@@ -8713,6 +11421,29 @@
-
- } // namespace Catch
- // end catch_matchers.cpp
-+// start catch_matchers_exception.cpp
-+
-+namespace Catch {
-+namespace Matchers {
-+namespace Exception {
-+
-+bool ExceptionMessageMatcher::match(std::exception const& ex) const {
-+ return ex.what() == m_message;
-+}
-+
-+std::string ExceptionMessageMatcher::describe() const {
-+ return "exception message matches \"" + m_message + "\"";
-+}
-+
-+}
-+Exception::ExceptionMessageMatcher Message(std::string const& message) {
-+ return Exception::ExceptionMessageMatcher(message);
-+}
-+
-+// namespace Exception
-+} // namespace Matchers
-+} // namespace Catch
-+// end catch_matchers_exception.cpp
- // start catch_matchers_floating.cpp
-
- // start catch_polyfills.hpp
-@@ -8741,74 +11472,101 @@
- } // end namespace Catch
-
- // end catch_to_string.hpp
-+#include <algorithm>
-+#include <cmath>
- #include <cstdlib>
- #include <cstdint>
- #include <cstring>
-+#include <sstream>
-+#include <type_traits>
-+#include <iomanip>
-+#include <limits>
-
- namespace Catch {
--namespace Matchers {
--namespace Floating {
--enum class FloatingPointKind : uint8_t {
-- Float,
-- Double
--};
--}
--}
--}
--
- namespace {
-
--template <typename T>
--struct Converter;
--
--template <>
--struct Converter<float> {
-- static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
-- Converter(float f) {
-+ int32_t convert(float f) {
-+ static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
-+ int32_t i;
- std::memcpy(&i, &f, sizeof(f));
-+ return i;
- }
-- int32_t i;
--};
-
--template <>
--struct Converter<double> {
-- static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
-- Converter(double d) {
-+ int64_t convert(double d) {
-+ static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
-+ int64_t i;
- std::memcpy(&i, &d, sizeof(d));
-+ return i;
- }
-- int64_t i;
--};
-
--template <typename T>
--auto convert(T t) -> Converter<T> {
-- return Converter<T>(t);
--}
-+ template <typename FP>
-+ bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) {
-+ // Comparison with NaN should always be false.
-+ // This way we can rule it out before getting into the ugly details
-+ if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
-+ return false;
-+ }
-
--template <typename FP>
--bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {
-- // Comparison with NaN should always be false.
-- // This way we can rule it out before getting into the ugly details
-- if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
-- return false;
-+ auto lc = convert(lhs);
-+ auto rc = convert(rhs);
-+
-+ if ((lc < 0) != (rc < 0)) {
-+ // Potentially we can have +0 and -0
-+ return lhs == rhs;
-+ }
-+
-+ // static cast as a workaround for IBM XLC
-+ auto ulpDiff = std::abs(static_cast<FP>(lc - rc));
-+ return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
- }
-
-- auto lc = convert(lhs);
-- auto rc = convert(rhs);
-+#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
-+
-+ float nextafter(float x, float y) {
-+ return ::nextafterf(x, y);
-+ }
-
-- if ((lc.i < 0) != (rc.i < 0)) {
-- // Potentially we can have +0 and -0
-- return lhs == rhs;
-+ double nextafter(double x, double y) {
-+ return ::nextafter(x, y);
- }
-
-- auto ulpDiff = std::abs(lc.i - rc.i);
-- return ulpDiff <= maxUlpDiff;
-+#endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^
-+
-+template <typename FP>
-+FP step(FP start, FP direction, uint64_t steps) {
-+ for (uint64_t i = 0; i < steps; ++i) {
-+#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
-+ start = Catch::nextafter(start, direction);
-+#else
-+ start = std::nextafter(start, direction);
-+#endif
-+ }
-+ return start;
-+}
-+
-+// Performs equivalent check of std::fabs(lhs - rhs) <= margin
-+// But without the subtraction to allow for INFINITY in comparison
-+bool marginComparison(double lhs, double rhs, double margin) {
-+ return (lhs + margin >= rhs) && (rhs + margin >= lhs);
- }
-
-+template <typename FloatingPoint>
-+void write(std::ostream& out, FloatingPoint num) {
-+ out << std::scientific
-+ << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)
-+ << num;
- }
-
--namespace Catch {
-+} // end anonymous namespace
-+
- namespace Matchers {
- namespace Floating {
-+
-+ enum class FloatingPointKind : uint8_t {
-+ Float,
-+ Double
-+ };
-+
- WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
- :m_target{ target }, m_margin{ margin } {
- CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
-@@ -8825,10 +11583,11 @@
- return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
- }
-
-- WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
-+ WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
- :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
-- CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.'
-- << " ULPs have to be non-negative.");
-+ CATCH_ENFORCE(m_type == FloatingPointKind::Double
-+ || m_ulps < (std::numeric_limits<uint32_t>::max)(),
-+ "Provided ULP is impossibly large for a float comparison.");
- }
-
- #if defined(__clang__)
-@@ -8853,16 +11612,59 @@
- #endif
-
- std::string WithinUlpsMatcher::describe() const {
-- return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
-+ std::stringstream ret;
-+
-+ ret << "is within " << m_ulps << " ULPs of ";
-+
-+ if (m_type == FloatingPointKind::Float) {
-+ write(ret, static_cast<float>(m_target));
-+ ret << 'f';
-+ } else {
-+ write(ret, m_target);
-+ }
-+
-+ ret << " ([";
-+ if (m_type == FloatingPointKind::Double) {
-+ write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
-+ ret << ", ";
-+ write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));
-+ } else {
-+ // We have to cast INFINITY to float because of MinGW, see #1782
-+ write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps));
-+ ret << ", ";
-+ write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps));
-+ }
-+ ret << "])";
-+
-+ return ret.str();
-+ }
-+
-+ WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
-+ m_target(target),
-+ m_epsilon(epsilon){
-+ CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon < 0 does not make sense.");
-+ CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not make sense.");
-+ }
-+
-+ bool WithinRelMatcher::match(double const& matchee) const {
-+ const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
-+ return marginComparison(matchee, m_target,
-+ std::isinf(relMargin)? 0 : relMargin);
-+ }
-+
-+ std::string WithinRelMatcher::describe() const {
-+ Catch::ReusableStringStream sstr;
-+ sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other";
-+ return sstr.str();
- }
-
- }// namespace Floating
-
--Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) {
-+Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
- return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
- }
-
--Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) {
-+Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
- return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
- }
-
-@@ -8870,9 +11672,24 @@
- return Floating::WithinAbsMatcher(target, margin);
- }
-
-+Floating::WithinRelMatcher WithinRel(double target, double eps) {
-+ return Floating::WithinRelMatcher(target, eps);
-+}
-+
-+Floating::WithinRelMatcher WithinRel(double target) {
-+ return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
-+}
-+
-+Floating::WithinRelMatcher WithinRel(float target, float eps) {
-+ return Floating::WithinRelMatcher(target, eps);
-+}
-+
-+Floating::WithinRelMatcher WithinRel(float target) {
-+ return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
-+}
-+
- } // namespace Matchers
- } // namespace Catch
--
- // end catch_matchers_floating.cpp
- // start catch_matchers_generic.cpp
-
-@@ -9030,28 +11847,43 @@
- ////////////////////////////////////////////////////////////////////////////
-
- ScopedMessage::ScopedMessage( MessageBuilder const& builder )
-- : m_info( builder.m_info )
-+ : m_info( builder.m_info ), m_moved()
- {
- m_info.message = builder.m_stream.str();
- getResultCapture().pushScopedMessage( m_info );
- }
-
-+ ScopedMessage::ScopedMessage( ScopedMessage&& old )
-+ : m_info( old.m_info ), m_moved()
-+ {
-+ old.m_moved = true;
-+ }
-+
- ScopedMessage::~ScopedMessage() {
-- if ( !uncaught_exceptions() ){
-+ if ( !uncaught_exceptions() && !m_moved ){
- getResultCapture().popScopedMessage(m_info);
- }
- }
-
- Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
- auto trimmed = [&] (size_t start, size_t end) {
-- while (names[start] == ',' || isspace(names[start])) {
-+ while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
- ++start;
- }
-- while (names[end] == ',' || isspace(names[end])) {
-+ while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {
- --end;
- }
- return names.substr(start, end - start + 1);
- };
-+ auto skipq = [&] (size_t start, char quote) {
-+ for (auto i = start + 1; i < names.size() ; ++i) {
-+ if (names[i] == quote)
-+ return i;
-+ if (names[i] == '\\')
-+ ++i;
-+ }
-+ CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");
-+ };
-
- size_t start = 0;
- std::stack<char> openings;
-@@ -9072,18 +11904,22 @@
- // case '>':
- openings.pop();
- break;
-+ case '"':
-+ case '\'':
-+ pos = skipq(pos, c);
-+ break;
- case ',':
-- if (start != pos && openings.size() == 0) {
-+ if (start != pos && openings.empty()) {
- m_messages.emplace_back(macroName, lineInfo, resultType);
-- m_messages.back().message = trimmed(start, pos);
-+ m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
- m_messages.back().message += " := ";
- start = pos;
- }
- }
- }
-- assert(openings.size() == 0 && "Mismatched openings");
-+ assert(openings.empty() && "Mismatched openings");
- m_messages.emplace_back(macroName, lineInfo, resultType);
-- m_messages.back().message = trimmed(start, names.size() - 1);
-+ m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
- m_messages.back().message += " := ";
- }
- Capturer::~Capturer() {
-@@ -9145,6 +11981,22 @@
- auto str() const -> std::string;
- };
-
-+ class RedirectedStreams {
-+ public:
-+ RedirectedStreams(RedirectedStreams const&) = delete;
-+ RedirectedStreams& operator=(RedirectedStreams const&) = delete;
-+ RedirectedStreams(RedirectedStreams&&) = delete;
-+ RedirectedStreams& operator=(RedirectedStreams&&) = delete;
-+
-+ RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
-+ ~RedirectedStreams();
-+ private:
-+ std::string& m_redirectedCout;
-+ std::string& m_redirectedCerr;
-+ RedirectedStdOut m_redirectedStdOut;
-+ RedirectedStdErr m_redirectedStdErr;
-+ };
-+
- #if defined(CATCH_CONFIG_NEW_CAPTURE)
-
- // Windows's implementation of std::tmpfile is terrible (it tries
-@@ -9236,6 +12088,16 @@
- {}
- auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
-
-+ RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
-+ : m_redirectedCout(redirectedCout),
-+ m_redirectedCerr(redirectedCerr)
-+ {}
-+
-+ RedirectedStreams::~RedirectedStreams() {
-+ m_redirectedCout += m_redirectedStdOut.str();
-+ m_redirectedCerr += m_redirectedStdErr.str();
-+ }
-+
- #if defined(CATCH_CONFIG_NEW_CAPTURE)
-
- #if defined(_MSC_VER)
-@@ -9243,12 +12105,12 @@
- if (tmpnam_s(m_buffer)) {
- CATCH_RUNTIME_ERROR("Could not get a temp filename");
- }
-- if (fopen_s(&m_file, m_buffer, "w")) {
-+ if (fopen_s(&m_file, m_buffer, "w+")) {
- char buffer[100];
- if (strerror_s(buffer, errno)) {
- CATCH_RUNTIME_ERROR("Could not translate errno to a string");
- }
-- CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer);
-+ CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);
- }
- }
- #else
-@@ -9351,20 +12213,61 @@
-
- namespace Catch {
-
-- std::mt19937& rng() {
-- static std::mt19937 s_rng;
-- return s_rng;
-+namespace {
-+
-+#if defined(_MSC_VER)
-+#pragma warning(push)
-+#pragma warning(disable:4146) // we negate uint32 during the rotate
-+#endif
-+ // Safe rotr implementation thanks to John Regehr
-+ uint32_t rotate_right(uint32_t val, uint32_t count) {
-+ const uint32_t mask = 31;
-+ count &= mask;
-+ return (val >> count) | (val << (-count & mask));
-+ }
-+
-+#if defined(_MSC_VER)
-+#pragma warning(pop)
-+#endif
-+
-+}
-+
-+ SimplePcg32::SimplePcg32(result_type seed_) {
-+ seed(seed_);
-+ }
-+
-+ void SimplePcg32::seed(result_type seed_) {
-+ m_state = 0;
-+ (*this)();
-+ m_state += seed_;
-+ (*this)();
- }
-
-- void seedRng( IConfig const& config ) {
-- if( config.rngSeed() != 0 ) {
-- std::srand( config.rngSeed() );
-- rng().seed( config.rngSeed() );
-+ void SimplePcg32::discard(uint64_t skip) {
-+ // We could implement this to run in O(log n) steps, but this
-+ // should suffice for our use case.
-+ for (uint64_t s = 0; s < skip; ++s) {
-+ static_cast<void>((*this)());
- }
- }
-
-- unsigned int rngSeed() {
-- return getCurrentContext().getConfig()->rngSeed();
-+ SimplePcg32::result_type SimplePcg32::operator()() {
-+ // prepare the output value
-+ const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
-+ const auto output = rotate_right(xorshifted, m_state >> 59u);
-+
-+ // advance state
-+ m_state = m_state * 6364136223846793005ULL + s_inc;
-+
-+ return output;
-+ }
-+
-+ bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
-+ return lhs.m_state == rhs.m_state;
-+ }
-+
-+ bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
-+ return lhs.m_state != rhs.m_state;
- }
- }
- // end catch_random_number_generator.cpp
-@@ -9383,6 +12286,8 @@
- struct IConfig;
-
- std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
-+
-+ bool isThrowSafe( TestCase const& testCase, IConfig const& config );
- bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
-
- void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
-@@ -9495,11 +12400,13 @@
- namespace Catch {
-
- class StartupExceptionRegistry {
-+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
- public:
- void add(std::exception_ptr const& exception) noexcept;
- std::vector<std::exception_ptr> const& getExceptions() const noexcept;
- private:
- std::vector<std::exception_ptr> m_exceptions;
-+#endif
- };
-
- } // end namespace Catch
-@@ -9582,7 +12489,14 @@
- m_tagAliasRegistry.add( alias, tag, lineInfo );
- }
- void registerStartupException() noexcept override {
-+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
- m_exceptionRegistry.add(std::current_exception());
-+#else
-+ CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
-+#endif
-+ }
-+ IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
-+ return m_enumValuesRegistry;
- }
-
- private:
-@@ -9591,6 +12505,7 @@
- ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
- TagAliasRegistry m_tagAliasRegistry;
- StartupExceptionRegistry m_exceptionRegistry;
-+ Detail::EnumValuesRegistry m_enumValuesRegistry;
- };
- }
-
-@@ -9671,7 +12586,6 @@
-
- namespace Generators {
- struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
-- size_t m_index = static_cast<size_t>( -1 );
- GeneratorBasePtr m_generator;
-
- GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
-@@ -9683,39 +12597,110 @@
- std::shared_ptr<GeneratorTracker> tracker;
-
- ITracker& currentTracker = ctx.currentTracker();
-- if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
-+ // Under specific circumstances, the generator we want
-+ // to acquire is also the current tracker. If this is
-+ // the case, we have to avoid looking through current
-+ // tracker's children, and instead return the current
-+ // tracker.
-+ // A case where this check is important is e.g.
-+ // for (int i = 0; i < 5; ++i) {
-+ // int n = GENERATE(1, 2);
-+ // }
-+ //
-+ // without it, the code above creates 5 nested generators.
-+ if (currentTracker.nameAndLocation() == nameAndLocation) {
-+ auto thisTracker = currentTracker.parent().findChild(nameAndLocation);
-+ assert(thisTracker);
-+ assert(thisTracker->isGeneratorTracker());
-+ tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker);
-+ } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
- assert( childTracker );
-- assert( childTracker->isIndexTracker() );
-+ assert( childTracker->isGeneratorTracker() );
- tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
-- }
-- else {
-+ } else {
- tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
- currentTracker.addChild( tracker );
- }
-
-- if( !ctx.completedCycle() && !tracker->isComplete() ) {
-- if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
-- tracker->moveNext();
-+ if( !tracker->isComplete() ) {
- tracker->open();
- }
-
- return *tracker;
- }
-
-- void moveNext() {
-- m_index++;
-- m_children.clear();
-- }
--
- // TrackerBase interface
-- bool isIndexTracker() const override { return true; }
-+ bool isGeneratorTracker() const override { return true; }
- auto hasGenerator() const -> bool override {
- return !!m_generator;
- }
- void close() override {
- TrackerBase::close();
-- if( m_runState == CompletedSuccessfully && m_index < m_generator->size()-1 )
-+ // If a generator has a child (it is followed by a section)
-+ // and none of its children have started, then we must wait
-+ // until later to start consuming its values.
-+ // This catches cases where `GENERATE` is placed between two
-+ // `SECTION`s.
-+ // **The check for m_children.empty cannot be removed**.
-+ // doing so would break `GENERATE` _not_ followed by `SECTION`s.
-+ const bool should_wait_for_child = [&]() {
-+ // No children -> nobody to wait for
-+ if ( m_children.empty() ) {
-+ return false;
-+ }
-+ // If at least one child started executing, don't wait
-+ if ( std::find_if(
-+ m_children.begin(),
-+ m_children.end(),
-+ []( TestCaseTracking::ITrackerPtr tracker ) {
-+ return tracker->hasStarted();
-+ } ) != m_children.end() ) {
-+ return false;
-+ }
-+
-+ // No children have started. We need to check if they _can_
-+ // start, and thus we should wait for them, or they cannot
-+ // start (due to filters), and we shouldn't wait for them
-+ auto* parent = m_parent;
-+ // This is safe: there is always at least one section
-+ // tracker in a test case tracking tree
-+ while ( !parent->isSectionTracker() ) {
-+ parent = &( parent->parent() );
-+ }
-+ assert( parent &&
-+ "Missing root (test case) level section" );
-+
-+ auto const& parentSection =
-+ static_cast<SectionTracker&>( *parent );
-+ auto const& filters = parentSection.getFilters();
-+ // No filters -> no restrictions on running sections
-+ if ( filters.empty() ) {
-+ return true;
-+ }
-+
-+ for ( auto const& child : m_children ) {
-+ if ( child->isSectionTracker() &&
-+ std::find( filters.begin(),
-+ filters.end(),
-+ static_cast<SectionTracker&>( *child )
-+ .trimmedName() ) !=
-+ filters.end() ) {
-+ return true;
-+ }
-+ }
-+ return false;
-+ }();
-+
-+ // This check is a bit tricky, because m_generator->next()
-+ // has a side-effect, where it consumes generator's current
-+ // value, but we do not want to invoke the side-effect if
-+ // this generator is still waiting for any child to start.
-+ if ( should_wait_for_child ||
-+ ( m_runState == CompletedSuccessfully &&
-+ m_generator->next() ) ) {
-+ m_children.clear();
- m_runState = Executing;
-+ }
- }
-
- // IGeneratorTracker interface
-@@ -9725,9 +12710,6 @@
- void setGenerator( GeneratorBasePtr&& generator ) override {
- m_generator = std::move( generator );
- }
-- auto getIndex() const -> size_t override {
-- return m_index;
-- }
- };
- GeneratorTracker::~GeneratorTracker() {}
- }
-@@ -9825,6 +12807,9 @@
- // and should be let to clear themselves out.
- static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
-
-+ if (result.getResultType() != ResultWas::Warning)
-+ m_messageScopes.clear();
-+
- // Reset working state
- resetAssertionInfo();
- m_lastResult = result;
-@@ -9848,10 +12833,10 @@
-
- return true;
- }
-- auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
-+ auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
- using namespace Generators;
-- GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) );
-- assert( tracker.isOpen() );
-+ GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext,
-+ TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) );
- m_lastAssertionInfo.lineInfo = lineInfo;
- return tracker;
- }
-@@ -9879,6 +12864,7 @@
-
- m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
- m_messages.clear();
-+ m_messageScopes.clear();
- }
-
- void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
-@@ -9890,12 +12876,21 @@
-
- m_unfinishedSections.push_back(endInfo);
- }
-+
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ void RunContext::benchmarkPreparing(std::string const& name) {
-+ m_reporter->benchmarkPreparing(name);
-+ }
- void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
- m_reporter->benchmarkStarting( info );
- }
-- void RunContext::benchmarkEnded( BenchmarkStats const& stats ) {
-+ void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
- m_reporter->benchmarkEnded( stats );
- }
-+ void RunContext::benchmarkFailed(std::string const & error) {
-+ m_reporter->benchmarkFailed(error);
-+ }
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
- void RunContext::pushScopedMessage(MessageInfo const & message) {
- m_messages.push_back(message);
-@@ -9905,6 +12900,10 @@
- m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
- }
-
-+ void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
-+ m_messageScopes.emplace_back( builder );
-+ }
-+
- std::string RunContext::getCurrentTestName() const {
- return m_activeTestCase
- ? m_activeTestCase->getTestCaseInfo().name
-@@ -9926,7 +12925,7 @@
- // Don't rebuild the result -- the stringification itself can cause more fatal errors
- // Instead, fake a result data.
- AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
-- tempResult.message = message;
-+ tempResult.message = static_cast<std::string>(message);
- AssertionResult result(m_lastAssertionInfo, tempResult);
-
- assertionEnded(result);
-@@ -9965,6 +12964,7 @@
- m_lastAssertionPassed = true;
- ++m_totals.assertions.passed;
- resetAssertionInfo();
-+ m_messageScopes.clear();
- }
-
- bool RunContext::aborting() const {
-@@ -9986,13 +12986,10 @@
- CATCH_TRY {
- if (m_reporter->getPreferences().shouldRedirectStdOut) {
- #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
-- RedirectedStdOut redirectedStdOut;
-- RedirectedStdErr redirectedStdErr;
-+ RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
-
- timer.start();
- invokeActiveTestCase();
-- redirectedCout += redirectedStdOut.str();
-- redirectedCerr += redirectedStdErr.str();
- #else
- OutputRedirect r(redirectedCout, redirectedCerr);
- timer.start();
-@@ -10019,15 +13016,15 @@
- m_testCaseTracker->close();
- handleUnfinishedSections();
- m_messages.clear();
-+ m_messageScopes.clear();
-
- SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
- m_reporter->sectionEnded(testCaseSectionStats);
- }
-
- void RunContext::invokeActiveTestCase() {
-- FatalConditionHandler fatalConditionHandler; // Handle signals
-+ FatalConditionHandlerGuard _(&m_fatalConditionhandler);
- m_activeTestCase->invoke();
-- fatalConditionHandler.reset();
- }
-
- void RunContext::handleUnfinishedSections() {
-@@ -10090,7 +13087,7 @@
- m_lastAssertionInfo = info;
-
- AssertionResultData data( resultType, LazyExpression( false ) );
-- data.message = message;
-+ data.message = static_cast<std::string>(message);
- AssertionResult assertionResult{ m_lastAssertionInfo, data };
- assertionEnded( assertionResult );
- if( !assertionResult.isOk() )
-@@ -10153,6 +13150,18 @@
- else
- CATCH_INTERNAL_ERROR("No result capture instance");
- }
-+
-+ void seedRng(IConfig const& config) {
-+ if (config.rngSeed() != 0) {
-+ std::srand(config.rngSeed());
-+ rng().seed(config.rngSeed());
-+ }
-+ }
-+
-+ unsigned int rngSeed() {
-+ return getCurrentContext().getConfig()->rngSeed();
-+ }
-+
- }
- // end catch_run_context.cpp
- // start catch_section.cpp
-@@ -10214,7 +13223,7 @@
- void libIdentify();
-
- int applyCommandLine( int argc, char const * const * argv );
-- #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
-+ #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
- int applyCommandLine( int argc, wchar_t const * const * argv );
- #endif
-
-@@ -10281,6 +13290,8 @@
- // end catch_version.h
- #include <cstdlib>
- #include <iomanip>
-+#include <set>
-+#include <iterator>
-
- namespace Catch {
-
-@@ -10299,52 +13310,76 @@
- return createReporter(config->getReporterName(), config);
- }
-
-- auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter);
--
-+ // On older platforms, returning std::unique_ptr<ListeningReporter>
-+ // when the return type is std::unique_ptr<IStreamingReporter>
-+ // doesn't compile without a std::move call. However, this causes
-+ // a warning on newer platforms. Thus, we have to work around
-+ // it a bit and downcast the pointer manually.
-+ auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);
-+ auto& multi = static_cast<ListeningReporter&>(*ret);
- auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
- for (auto const& listener : listeners) {
-- multi->addListener(listener->create(Catch::ReporterConfig(config)));
-+ multi.addListener(listener->create(Catch::ReporterConfig(config)));
- }
-- multi->addReporter(createReporter(config->getReporterName(), config));
-- return std::move(multi);
-+ multi.addReporter(createReporter(config->getReporterName(), config));
-+ return ret;
- }
-
-- Catch::Totals runTests(std::shared_ptr<Config> const& config) {
-- auto reporter = makeReporter(config);
--
-- RunContext context(config, std::move(reporter));
--
-- Totals totals;
--
-- context.testGroupStarting(config->name(), 1, 1);
--
-- TestSpec testSpec = config->testSpec();
--
-- auto const& allTestCases = getAllTestCasesSorted(*config);
-- for (auto const& testCase : allTestCases) {
-- if (!context.aborting() && matchTest(testCase, testSpec, *config))
-- totals += context.runTest(testCase);
-- else
-- context.reporter().skipTest(testCase);
-+ class TestGroup {
-+ public:
-+ explicit TestGroup(std::shared_ptr<Config> const& config)
-+ : m_config{config}
-+ , m_context{config, makeReporter(config)}
-+ {
-+ auto const& allTestCases = getAllTestCasesSorted(*m_config);
-+ m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
-+ auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
-+
-+ if (m_matches.empty() && invalidArgs.empty()) {
-+ for (auto const& test : allTestCases)
-+ if (!test.isHidden())
-+ m_tests.emplace(&test);
-+ } else {
-+ for (auto const& match : m_matches)
-+ m_tests.insert(match.tests.begin(), match.tests.end());
-+ }
- }
-
-- if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
-- ReusableStringStream testConfig;
-+ Totals execute() {
-+ auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
-+ Totals totals;
-+ m_context.testGroupStarting(m_config->name(), 1, 1);
-+ for (auto const& testCase : m_tests) {
-+ if (!m_context.aborting())
-+ totals += m_context.runTest(*testCase);
-+ else
-+ m_context.reporter().skipTest(*testCase);
-+ }
-
-- bool first = true;
-- for (const auto& input : config->getTestsOrTags()) {
-- if (!first) { testConfig << ' '; }
-- first = false;
-- testConfig << input;
-+ for (auto const& match : m_matches) {
-+ if (match.tests.empty()) {
-+ m_context.reporter().noMatchingTestCases(match.name);
-+ totals.error = -1;
-+ }
- }
-
-- context.reporter().noMatchingTestCases(testConfig.str());
-- totals.error = -1;
-+ if (!invalidArgs.empty()) {
-+ for (auto const& invalidArg: invalidArgs)
-+ m_context.reporter().reportInvalidArguments(invalidArg);
-+ }
-+
-+ m_context.testGroupEnded(m_config->name(), totals, 1, 1);
-+ return totals;
- }
-
-- context.testGroupEnded(config->name(), totals, 1, 1);
-- return totals;
-- }
-+ private:
-+ using Tests = std::set<TestCase const*>;
-+
-+ std::shared_ptr<Config> m_config;
-+ RunContext m_context;
-+ Tests m_tests;
-+ TestSpec::Matches m_matches;
-+ };
-
- void applyFilenamesAsTags(Catch::IConfig const& config) {
- auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
-@@ -10381,6 +13416,9 @@
- #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
- const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
- if ( !exceptions.empty() ) {
-+ config();
-+ getCurrentMutableContext().setConfig(m_config);
-+
- m_startupExceptions = true;
- Colour colourGuard( Colour::Red );
- Catch::cerr() << "Errors occurred during startup!" << '\n';
-@@ -10410,7 +13448,7 @@
- }
- void Session::libIdentify() {
- Catch::cout()
-- << std::left << std::setw(16) << "description: " << "A Catch test executable\n"
-+ << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"
- << std::left << std::setw(16) << "category: " << "testframework\n"
- << std::left << std::setw(16) << "framework: " << "Catch Test\n"
- << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
-@@ -10422,6 +13460,8 @@
-
- auto result = m_cli.parse( clara::Args( argc, argv ) );
- if( !result ) {
-+ config();
-+ getCurrentMutableContext().setConfig(m_config);
- Catch::cerr()
- << Colour( Colour::Red )
- << "\nError(s) in input:\n"
-@@ -10439,17 +13479,17 @@
- return 0;
- }
-
--#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
-+#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
- int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
-
- char **utf8Argv = new char *[ argc ];
-
- for ( int i = 0; i < argc; ++i ) {
-- int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
-+ int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );
-
- utf8Argv[ i ] = new char[ bufSize ];
-
-- WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
-+ WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );
- }
-
- int returnCode = applyCommandLine( argc, utf8Argv );
-@@ -10513,10 +13553,15 @@
- applyFilenamesAsTags( *m_config );
-
- // Handle list request
-- if( Option<std::size_t> listed = list( config() ) )
-+ if( Option<std::size_t> listed = list( m_config ) )
- return static_cast<int>( *listed );
-
-- auto totals = runTests( m_config );
-+ TestGroup tests { m_config };
-+ auto const totals = tests.execute();
-+
-+ if( m_config->warnAboutNoTests() && totals.error == -1 )
-+ return 2;
-+
- // Note that on unices only the lower 8 bits are usually used, clamping
- // the return value to 255 prevents false negative when some multiple
- // of 256 tests has failed
-@@ -10564,6 +13609,7 @@
- // end catch_singletons.cpp
- // start catch_startup_exception_registry.cpp
-
-+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
- namespace Catch {
- void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
- CATCH_TRY {
-@@ -10579,6 +13625,7 @@
- }
-
- } // end namespace Catch
-+#endif
- // end catch_startup_exception_registry.cpp
- // start catch_stream.cpp
-
-@@ -10593,7 +13640,7 @@
-
- Catch::IStream::~IStream() = default;
-
-- namespace detail { namespace {
-+ namespace Detail { namespace {
- template<typename WriterF, std::size_t bufferSize=256>
- class StreamBufImpl : public std::streambuf {
- char data[bufferSize];
-@@ -10692,15 +13739,15 @@
-
- auto makeStream( StringRef const &filename ) -> IStream const* {
- if( filename.empty() )
-- return new detail::CoutStream();
-+ return new Detail::CoutStream();
- else if( filename[0] == '%' ) {
- if( filename == "%debug" )
-- return new detail::DebugOutStream();
-+ return new Detail::DebugOutStream();
- else
- CATCH_ERROR( "Unrecognised stream: '" << filename << "'" );
- }
- else
-- return new detail::FileStream( filename );
-+ return new Detail::FileStream( filename );
- }
-
- // This class encapsulates the idea of a pool of ostringstreams that can be reused.
-@@ -10757,12 +13804,13 @@
- #include <ostream>
- #include <cstring>
- #include <cctype>
-+#include <vector>
-
- namespace Catch {
-
- namespace {
- char toLowerCh(char c) {
-- return static_cast<char>( std::tolower( c ) );
-+ return static_cast<char>( std::tolower( static_cast<unsigned char>(c) ) );
- }
- }
-
-@@ -10797,6 +13845,18 @@
- return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
- }
-
-+ StringRef trim(StringRef ref) {
-+ const auto is_ws = [](char c) {
-+ return c == ' ' || c == '\t' || c == '\n' || c == '\r';
-+ };
-+ size_t real_begin = 0;
-+ while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; }
-+ size_t real_end = ref.size();
-+ while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; }
-+
-+ return ref.substr(real_begin, real_end - real_begin);
-+ }
-+
- bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
- bool replaced = false;
- std::size_t i = str.find( replaceThis );
-@@ -10811,6 +13871,21 @@
- return replaced;
- }
-
-+ std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) {
-+ std::vector<StringRef> subStrings;
-+ std::size_t start = 0;
-+ for(std::size_t pos = 0; pos < str.size(); ++pos ) {
-+ if( str[pos] == delimiter ) {
-+ if( pos - start > 1 )
-+ subStrings.push_back( str.substr( start, pos-start ) );
-+ start = pos+1;
-+ }
-+ }
-+ if( start < str.size() )
-+ subStrings.push_back( str.substr( start, str.size()-start ) );
-+ return subStrings;
-+ }
-+
- pluralise::pluralise( std::size_t count, std::string const& label )
- : m_count( count ),
- m_label( label )
-@@ -10827,123 +13902,46 @@
- // end catch_string_manip.cpp
- // start catch_stringref.cpp
-
--#if defined(__clang__)
--# pragma clang diagnostic push
--# pragma clang diagnostic ignored "-Wexit-time-destructors"
--#endif
--
-+#include <algorithm>
- #include <ostream>
- #include <cstring>
- #include <cstdint>
-
--namespace {
-- const uint32_t byte_2_lead = 0xC0;
-- const uint32_t byte_3_lead = 0xE0;
-- const uint32_t byte_4_lead = 0xF0;
--}
--
- namespace Catch {
- StringRef::StringRef( char const* rawChars ) noexcept
- : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
- {}
-
-- StringRef::operator std::string() const {
-- return std::string( m_start, m_size );
-- }
--
-- void StringRef::swap( StringRef& other ) noexcept {
-- std::swap( m_start, other.m_start );
-- std::swap( m_size, other.m_size );
-- std::swap( m_data, other.m_data );
-- }
--
- auto StringRef::c_str() const -> char const* {
-- if( isSubstring() )
-- const_cast<StringRef*>( this )->takeOwnership();
-+ CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance");
- return m_start;
- }
-- auto StringRef::currentData() const noexcept -> char const* {
-+ auto StringRef::data() const noexcept -> char const* {
- return m_start;
- }
-
-- auto StringRef::isOwned() const noexcept -> bool {
-- return m_data != nullptr;
-- }
-- auto StringRef::isSubstring() const noexcept -> bool {
-- return m_start[m_size] != '\0';
-- }
--
-- void StringRef::takeOwnership() {
-- if( !isOwned() ) {
-- m_data = new char[m_size+1];
-- memcpy( m_data, m_start, m_size );
-- m_data[m_size] = '\0';
-- m_start = m_data;
-- }
-- }
- auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {
-- if( start < m_size )
-- return StringRef( m_start+start, size );
-- else
-+ if (start < m_size) {
-+ return StringRef(m_start + start, (std::min)(m_size - start, size));
-+ } else {
- return StringRef();
-- }
-- auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
-- return
-- size() == other.size() &&
-- (std::strncmp( m_start, other.m_start, size() ) == 0);
-- }
-- auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool {
-- return !operator==( other );
-- }
--
-- auto StringRef::operator[](size_type index) const noexcept -> char {
-- return m_start[index];
-- }
--
-- auto StringRef::numberOfCharacters() const noexcept -> size_type {
-- size_type noChars = m_size;
-- // Make adjustments for uft encodings
-- for( size_type i=0; i < m_size; ++i ) {
-- char c = m_start[i];
-- if( ( c & byte_2_lead ) == byte_2_lead ) {
-- noChars--;
-- if (( c & byte_3_lead ) == byte_3_lead )
-- noChars--;
-- if( ( c & byte_4_lead ) == byte_4_lead )
-- noChars--;
-- }
- }
-- return noChars;
- }
--
-- auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string {
-- std::string str;
-- str.reserve( lhs.size() + rhs.size() );
-- str += lhs;
-- str += rhs;
-- return str;
-- }
-- auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string {
-- return std::string( lhs ) + std::string( rhs );
-- }
-- auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string {
-- return std::string( lhs ) + std::string( rhs );
-+ auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
-+ return m_size == other.m_size
-+ && (std::memcmp( m_start, other.m_start, m_size ) == 0);
- }
-
- auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
-- return os.write(str.currentData(), str.size());
-+ return os.write(str.data(), str.size());
- }
-
- auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
-- lhs.append(rhs.currentData(), rhs.size());
-+ lhs.append(rhs.data(), rhs.size());
- return lhs;
- }
-
- } // namespace Catch
--
--#if defined(__clang__)
--# pragma clang diagnostic pop
--#endif
- // end catch_stringref.cpp
- // start catch_tag_alias.cpp
-
-@@ -11046,7 +14044,7 @@
- void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
- CATCH_ENFORCE( !isReservedTag(tag),
- "Tag name: [" << tag << "] is not allowed.\n"
-- << "Tag names starting with non alpha-numeric characters are reserved\n"
-+ << "Tag names starting with non alphanumeric characters are reserved\n"
- << _lineInfo );
- }
- }
-@@ -11062,8 +14060,7 @@
- std::vector<std::string> tags;
- std::string desc, tag;
- bool inTag = false;
-- std::string _descOrTags = nameAndTags.tags;
-- for (char c : _descOrTags) {
-+ for (char c : nameAndTags.tags) {
- if( !inTag ) {
- if( c == '[' )
- inTag = true;
-@@ -11078,6 +14075,12 @@
- else if( prop == TestCaseInfo::None )
- enforceNotReservedTag( tag, _lineInfo );
-
-+ // Merged hide tags like `[.approvals]` should be added as
-+ // `[.][approvals]`. The `[.]` is added at later point, so
-+ // we only strip the prefix
-+ if (startsWith(tag, '.') && tag.size() > 1) {
-+ tag.erase(0, 1);
-+ }
- tags.push_back( tag );
- tag.clear();
- inTag = false;
-@@ -11087,10 +14090,11 @@
- }
- }
- if( isHidden ) {
-- tags.push_back( "." );
-+ // Add all "hidden" tags to make them behave identically
-+ tags.insert( tags.end(), { ".", "!hide" } );
- }
-
-- TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
-+ TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo );
- return TestCase( _testCase, std::move(info) );
- }
-
-@@ -11182,30 +14186,89 @@
- // end catch_test_case_info.cpp
- // start catch_test_case_registry_impl.cpp
-
-+#include <algorithm>
- #include <sstream>
-
- namespace Catch {
-
-- std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
-+ namespace {
-+ struct TestHasher {
-+ using hash_t = uint64_t;
-
-- std::vector<TestCase> sorted = unsortedTestCases;
-+ explicit TestHasher( hash_t hashSuffix ):
-+ m_hashSuffix{ hashSuffix } {}
-+
-+ uint32_t operator()( TestCase const& t ) const {
-+ // FNV-1a hash with multiplication fold.
-+ const hash_t prime = 1099511628211u;
-+ hash_t hash = 14695981039346656037u;
-+ for ( const char c : t.name ) {
-+ hash ^= c;
-+ hash *= prime;
-+ }
-+ hash ^= m_hashSuffix;
-+ hash *= prime;
-+ const uint32_t low{ static_cast<uint32_t>( hash ) };
-+ const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
-+ return low * high;
-+ }
-+
-+ private:
-+ hash_t m_hashSuffix;
-+ };
-+ } // end unnamed namespace
-
-+ std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
- switch( config.runOrder() ) {
-- case RunTests::InLexicographicalOrder:
-- std::sort( sorted.begin(), sorted.end() );
-- break;
-- case RunTests::InRandomOrder:
-- seedRng( config );
-- std::shuffle( sorted.begin(), sorted.end(), rng() );
-- break;
- case RunTests::InDeclarationOrder:
- // already in declaration order
- break;
-+
-+ case RunTests::InLexicographicalOrder: {
-+ std::vector<TestCase> sorted = unsortedTestCases;
-+ std::sort( sorted.begin(), sorted.end() );
-+ return sorted;
-+ }
-+
-+ case RunTests::InRandomOrder: {
-+ seedRng( config );
-+ TestHasher h{ config.rngSeed() };
-+
-+ using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>;
-+ std::vector<hashedTest> indexed_tests;
-+ indexed_tests.reserve( unsortedTestCases.size() );
-+
-+ for (auto const& testCase : unsortedTestCases) {
-+ indexed_tests.emplace_back(h(testCase), &testCase);
-+ }
-+
-+ std::sort(indexed_tests.begin(), indexed_tests.end(),
-+ [](hashedTest const& lhs, hashedTest const& rhs) {
-+ if (lhs.first == rhs.first) {
-+ return lhs.second->name < rhs.second->name;
-+ }
-+ return lhs.first < rhs.first;
-+ });
-+
-+ std::vector<TestCase> sorted;
-+ sorted.reserve( indexed_tests.size() );
-+
-+ for (auto const& hashed : indexed_tests) {
-+ sorted.emplace_back(*hashed.second);
-+ }
-+
-+ return sorted;
-+ }
- }
-- return sorted;
-+ return unsortedTestCases;
-+ }
-+
-+ bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {
-+ return !testCase.throws() || config.allowThrows();
- }
-+
- bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
-- return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
-+ return testSpec.matches( testCase ) && isThrowSafe( testCase, config );
- }
-
- void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
-@@ -11222,9 +14285,12 @@
- std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
- std::vector<TestCase> filtered;
- filtered.reserve( testCases.size() );
-- for( auto const& testCase : testCases )
-- if( matchTest( testCase, testSpec, config ) )
-- filtered.push_back( testCase );
-+ for (auto const& testCase : testCases) {
-+ if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
-+ (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
-+ filtered.push_back(testCase);
-+ }
-+ }
- return filtered;
- }
- std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
-@@ -11263,7 +14329,7 @@
- }
-
- std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
-- std::string className = classOrQualifiedMethodName;
-+ std::string className(classOrQualifiedMethodName);
- if( startsWith( className, '&' ) )
- {
- std::size_t lastColons = className.rfind( "::" );
-@@ -11300,11 +14366,6 @@
-
- ITracker::~ITracker() = default;
-
-- TrackerContext& TrackerContext::instance() {
-- static TrackerContext s_instance;
-- return s_instance;
-- }
--
- ITracker& TrackerContext::startRun() {
- m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
- m_currentTracker = nullptr;
-@@ -11336,15 +14397,12 @@
- m_currentTracker = tracker;
- }
-
-- TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
-- : m_nameAndLocation( nameAndLocation ),
-+ TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
-+ ITracker(nameAndLocation),
- m_ctx( ctx ),
- m_parent( parent )
- {}
-
-- NameAndLocation const& TrackerBase::nameAndLocation() const {
-- return m_nameAndLocation;
-- }
- bool TrackerBase::isComplete() const {
- return m_runState == CompletedSuccessfully || m_runState == Failed;
- }
-@@ -11387,7 +14445,7 @@
- }
-
- bool TrackerBase::isSectionTracker() const { return false; }
-- bool TrackerBase::isIndexTracker() const { return false; }
-+ bool TrackerBase::isGeneratorTracker() const { return false; }
-
- void TrackerBase::open() {
- m_runState = Executing;
-@@ -11410,7 +14468,7 @@
- m_runState = CompletedSuccessfully;
- break;
- case ExecutingChildren:
-- if( m_children.empty() || m_children.back()->isComplete() )
-+ if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) )
- m_runState = CompletedSuccessfully;
- break;
-
-@@ -11445,7 +14503,8 @@
- }
-
- SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
-- : TrackerBase( nameAndLocation, ctx, parent )
-+ : TrackerBase( nameAndLocation, ctx, parent ),
-+ m_trimmed_name(trim(nameAndLocation.name))
- {
- if( parent ) {
- while( !parent->isSectionTracker() )
-@@ -11456,6 +14515,17 @@
- }
- }
-
-+ bool SectionTracker::isComplete() const {
-+ bool complete = true;
-+
-+ if (m_filters.empty()
-+ || m_filters[0] == ""
-+ || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
-+ complete = TrackerBase::isComplete();
-+ }
-+ return complete;
-+ }
-+
- bool SectionTracker::isSectionTracker() const { return true; }
-
- SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
-@@ -11477,63 +14547,29 @@
- }
-
- void SectionTracker::tryOpen() {
-- if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
-+ if( !isComplete() )
- open();
- }
-
- void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
- if( !filters.empty() ) {
-- m_filters.push_back(""); // Root - should never be consulted
-- m_filters.push_back(""); // Test Case - not a section filter
-+ m_filters.reserve( m_filters.size() + filters.size() + 2 );
-+ m_filters.emplace_back(""); // Root - should never be consulted
-+ m_filters.emplace_back(""); // Test Case - not a section filter
- m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
- }
- }
- void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {
- if( filters.size() > 1 )
-- m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
-- }
--
-- IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
-- : TrackerBase( nameAndLocation, ctx, parent ),
-- m_size( size )
-- {}
--
-- bool IndexTracker::isIndexTracker() const { return true; }
--
-- IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
-- std::shared_ptr<IndexTracker> tracker;
--
-- ITracker& currentTracker = ctx.currentTracker();
-- if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
-- assert( childTracker );
-- assert( childTracker->isIndexTracker() );
-- tracker = std::static_pointer_cast<IndexTracker>( childTracker );
-- }
-- else {
-- tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, &currentTracker, size );
-- currentTracker.addChild( tracker );
-- }
--
-- if( !ctx.completedCycle() && !tracker->isComplete() ) {
-- if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
-- tracker->moveNext();
-- tracker->open();
-- }
--
-- return *tracker;
-+ m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
- }
-
-- int IndexTracker::index() const { return m_index; }
--
-- void IndexTracker::moveNext() {
-- m_index++;
-- m_children.clear();
-+ std::vector<std::string> const& SectionTracker::getFilters() const {
-+ return m_filters;
- }
-
-- void IndexTracker::close() {
-- TrackerBase::close();
-- if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
-- m_runState = Executing;
-+ std::string const& SectionTracker::trimmedName() const {
-+ return m_trimmed_name;
- }
-
- } // namespace TestCaseTracking
-@@ -11541,7 +14577,6 @@
- using TestCaseTracking::ITracker;
- using TestCaseTracking::TrackerContext;
- using TestCaseTracking::SectionTracker;
--using TestCaseTracking::IndexTracker;
-
- } // namespace Catch
-
-@@ -11586,47 +14621,81 @@
-
- namespace Catch {
-
-+ TestSpec::Pattern::Pattern( std::string const& name )
-+ : m_name( name )
-+ {}
-+
- TestSpec::Pattern::~Pattern() = default;
-- TestSpec::NamePattern::~NamePattern() = default;
-- TestSpec::TagPattern::~TagPattern() = default;
-- TestSpec::ExcludedPattern::~ExcludedPattern() = default;
-
-- TestSpec::NamePattern::NamePattern( std::string const& name )
-- : m_wildcardPattern( toLower( name ), CaseSensitive::No )
-+ std::string const& TestSpec::Pattern::name() const {
-+ return m_name;
-+ }
-+
-+ TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
-+ : Pattern( filterString )
-+ , m_wildcardPattern( toLower( name ), CaseSensitive::No )
- {}
-+
- bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
-- return m_wildcardPattern.matches( toLower( testCase.name ) );
-+ return m_wildcardPattern.matches( testCase.name );
- }
-
-- TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
-+ TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
-+ : Pattern( filterString )
-+ , m_tag( toLower( tag ) )
-+ {}
-+
- bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
- return std::find(begin(testCase.lcaseTags),
- end(testCase.lcaseTags),
- m_tag) != end(testCase.lcaseTags);
- }
-
-- TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
-- bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
-+ TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern )
-+ : Pattern( underlyingPattern->name() )
-+ , m_underlyingPattern( underlyingPattern )
-+ {}
-+
-+ bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const {
-+ return !m_underlyingPattern->matches( testCase );
-+ }
-
- bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
-- // All patterns in a filter must match for the filter to be a match
-- for( auto const& pattern : m_patterns ) {
-- if( !pattern->matches( testCase ) )
-- return false;
-- }
-- return true;
-+ return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } );
-+ }
-+
-+ std::string TestSpec::Filter::name() const {
-+ std::string name;
-+ for( auto const& p : m_patterns )
-+ name += p->name();
-+ return name;
- }
-
- bool TestSpec::hasFilters() const {
- return !m_filters.empty();
- }
-+
- bool TestSpec::matches( TestCaseInfo const& testCase ) const {
-- // A TestSpec matches if any filter matches
-- for( auto const& filter : m_filters )
-- if( filter.matches( testCase ) )
-- return true;
-- return false;
-+ return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
-+ }
-+
-+ TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const
-+ {
-+ Matches matches( m_filters.size() );
-+ std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){
-+ std::vector<TestCase const*> currentMatches;
-+ for( auto const& test : testCases )
-+ if( isThrowSafe( test, config ) && filter.matches( test ) )
-+ currentMatches.emplace_back( &test );
-+ return FilterMatch{ filter.name(), currentMatches };
-+ } );
-+ return matches;
-+ }
-+
-+ const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{
-+ return (m_invalidArgs);
- }
-+
- }
- // end catch_test_spec.cpp
- // start catch_test_spec_parser.cpp
-@@ -11638,64 +14707,136 @@
- TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
- m_mode = None;
- m_exclusion = false;
-- m_start = std::string::npos;
- m_arg = m_tagAliases->expandAliases( arg );
- m_escapeChars.clear();
-+ m_substring.reserve(m_arg.size());
-+ m_patternName.reserve(m_arg.size());
-+ m_realPatternPos = 0;
-+
- for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
-- visitChar( m_arg[m_pos] );
-- if( m_mode == Name )
-- addPattern<TestSpec::NamePattern>();
-+ //if visitChar fails
-+ if( !visitChar( m_arg[m_pos] ) ){
-+ m_testSpec.m_invalidArgs.push_back(arg);
-+ break;
-+ }
-+ endMode();
- return *this;
- }
- TestSpec TestSpecParser::testSpec() {
- addFilter();
- return m_testSpec;
- }
-+ bool TestSpecParser::visitChar( char c ) {
-+ if( (m_mode != EscapedName) && (c == '\\') ) {
-+ escape();
-+ addCharToPattern(c);
-+ return true;
-+ }else if((m_mode != EscapedName) && (c == ',') ) {
-+ return separate();
-+ }
-
-- void TestSpecParser::visitChar( char c ) {
-- if( m_mode == None ) {
-- switch( c ) {
-- case ' ': return;
-- case '~': m_exclusion = true; return;
-- case '[': return startNewMode( Tag, ++m_pos );
-- case '"': return startNewMode( QuotedName, ++m_pos );
-- case '\\': return escape();
-- default: startNewMode( Name, m_pos ); break;
-- }
-- }
-- if( m_mode == Name ) {
-- if( c == ',' ) {
-- addPattern<TestSpec::NamePattern>();
-- addFilter();
-- }
-- else if( c == '[' ) {
-- if( subString() == "exclude:" )
-- m_exclusion = true;
-- else
-- addPattern<TestSpec::NamePattern>();
-- startNewMode( Tag, ++m_pos );
-- }
-- else if( c == '\\' )
-- escape();
-+ switch( m_mode ) {
-+ case None:
-+ if( processNoneChar( c ) )
-+ return true;
-+ break;
-+ case Name:
-+ processNameChar( c );
-+ break;
-+ case EscapedName:
-+ endMode();
-+ addCharToPattern(c);
-+ return true;
-+ default:
-+ case Tag:
-+ case QuotedName:
-+ if( processOtherChar( c ) )
-+ return true;
-+ break;
-+ }
-+
-+ m_substring += c;
-+ if( !isControlChar( c ) ) {
-+ m_patternName += c;
-+ m_realPatternPos++;
-+ }
-+ return true;
-+ }
-+ // Two of the processing methods return true to signal the caller to return
-+ // without adding the given character to the current pattern strings
-+ bool TestSpecParser::processNoneChar( char c ) {
-+ switch( c ) {
-+ case ' ':
-+ return true;
-+ case '~':
-+ m_exclusion = true;
-+ return false;
-+ case '[':
-+ startNewMode( Tag );
-+ return false;
-+ case '"':
-+ startNewMode( QuotedName );
-+ return false;
-+ default:
-+ startNewMode( Name );
-+ return false;
-+ }
-+ }
-+ void TestSpecParser::processNameChar( char c ) {
-+ if( c == '[' ) {
-+ if( m_substring == "exclude:" )
-+ m_exclusion = true;
-+ else
-+ endMode();
-+ startNewMode( Tag );
- }
-- else if( m_mode == EscapedName )
-- m_mode = Name;
-- else if( m_mode == QuotedName && c == '"' )
-- addPattern<TestSpec::NamePattern>();
-- else if( m_mode == Tag && c == ']' )
-- addPattern<TestSpec::TagPattern>();
- }
-- void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
-+ bool TestSpecParser::processOtherChar( char c ) {
-+ if( !isControlChar( c ) )
-+ return false;
-+ m_substring += c;
-+ endMode();
-+ return true;
-+ }
-+ void TestSpecParser::startNewMode( Mode mode ) {
- m_mode = mode;
-- m_start = start;
-+ }
-+ void TestSpecParser::endMode() {
-+ switch( m_mode ) {
-+ case Name:
-+ case QuotedName:
-+ return addNamePattern();
-+ case Tag:
-+ return addTagPattern();
-+ case EscapedName:
-+ revertBackToLastMode();
-+ return;
-+ case None:
-+ default:
-+ return startNewMode( None );
-+ }
- }
- void TestSpecParser::escape() {
-- if( m_mode == None )
-- m_start = m_pos;
-+ saveLastMode();
- m_mode = EscapedName;
-- m_escapeChars.push_back( m_pos );
-+ m_escapeChars.push_back(m_realPatternPos);
-+ }
-+ bool TestSpecParser::isControlChar( char c ) const {
-+ switch( m_mode ) {
-+ default:
-+ return false;
-+ case None:
-+ return c == '~';
-+ case Name:
-+ return c == '[';
-+ case EscapedName:
-+ return true;
-+ case QuotedName:
-+ return c == '"';
-+ case Tag:
-+ return c == '[' || c == ']';
-+ }
- }
-- std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
-
- void TestSpecParser::addFilter() {
- if( !m_currentFilter.m_patterns.empty() ) {
-@@ -11704,6 +14845,86 @@
- }
- }
-
-+ void TestSpecParser::saveLastMode() {
-+ lastMode = m_mode;
-+ }
-+
-+ void TestSpecParser::revertBackToLastMode() {
-+ m_mode = lastMode;
-+ }
-+
-+ bool TestSpecParser::separate() {
-+ if( (m_mode==QuotedName) || (m_mode==Tag) ){
-+ //invalid argument, signal failure to previous scope.
-+ m_mode = None;
-+ m_pos = m_arg.size();
-+ m_substring.clear();
-+ m_patternName.clear();
-+ m_realPatternPos = 0;
-+ return false;
-+ }
-+ endMode();
-+ addFilter();
-+ return true; //success
-+ }
-+
-+ std::string TestSpecParser::preprocessPattern() {
-+ std::string token = m_patternName;
-+ for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
-+ token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
-+ m_escapeChars.clear();
-+ if (startsWith(token, "exclude:")) {
-+ m_exclusion = true;
-+ token = token.substr(8);
-+ }
-+
-+ m_patternName.clear();
-+ m_realPatternPos = 0;
-+
-+ return token;
-+ }
-+
-+ void TestSpecParser::addNamePattern() {
-+ auto token = preprocessPattern();
-+
-+ if (!token.empty()) {
-+ TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring);
-+ if (m_exclusion)
-+ pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
-+ m_currentFilter.m_patterns.push_back(pattern);
-+ }
-+ m_substring.clear();
-+ m_exclusion = false;
-+ m_mode = None;
-+ }
-+
-+ void TestSpecParser::addTagPattern() {
-+ auto token = preprocessPattern();
-+
-+ if (!token.empty()) {
-+ // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
-+ // we have to create a separate hide tag and shorten the real one
-+ if (token.size() > 1 && token[0] == '.') {
-+ token.erase(token.begin());
-+ TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring);
-+ if (m_exclusion) {
-+ pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
-+ }
-+ m_currentFilter.m_patterns.push_back(pattern);
-+ }
-+
-+ TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring);
-+
-+ if (m_exclusion) {
-+ pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
-+ }
-+ m_currentFilter.m_patterns.push_back(pattern);
-+ }
-+ m_substring.clear();
-+ m_exclusion = false;
-+ m_mode = None;
-+ }
-+
- TestSpec parseTestSpec( std::string const& arg ) {
- return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
- }
-@@ -11744,7 +14965,7 @@
- // is terrible and we should move on.
- // TBD: How to signal that the measured resolution is probably wrong?
- if (ticks > startTime + 3 * nanosecondsInSecond) {
-- return sum / i;
-+ return sum / ( i + 1u );
- }
- }
-
-@@ -11805,13 +15026,11 @@
- enum Arch { Big, Little };
-
- static Arch which() {
-- union _{
-- int asInt;
-- char asChar[sizeof (int)];
-- } u;
--
-- u.asInt = 1;
-- return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
-+ int one = 1;
-+ // If the lowest byte we read is non-zero, we can assume
-+ // that little endian format is used.
-+ auto value = *reinterpret_cast<char*>(&one);
-+ return value ? Little : Big;
- }
- };
- }
-@@ -11935,6 +15154,13 @@
- }
- #endif
-
-+#if defined(CATCH_CONFIG_CPP17_BYTE)
-+#include <cstddef>
-+std::string StringMaker<std::byte>::convert(std::byte value) {
-+ return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));
-+}
-+#endif // defined(CATCH_CONFIG_CPP17_BYTE)
-+
- std::string StringMaker<int>::convert(int value) {
- return ::Catch::Detail::stringify(static_cast<long long>(value));
- }
-@@ -11997,11 +15223,16 @@
- return "nullptr";
- }
-
-+int StringMaker<float>::precision = 5;
-+
- std::string StringMaker<float>::convert(float value) {
-- return fpToString(value, 5) + 'f';
-+ return fpToString(value, precision) + 'f';
- }
-+
-+int StringMaker<double>::precision = 10;
-+
- std::string StringMaker<double>::convert(double value) {
-- return fpToString(value, 10);
-+ return fpToString(value, precision);
- }
-
- std::string ratio_string<std::atto>::symbol() { return "a"; }
-@@ -12075,11 +15306,48 @@
- // end catch_totals.cpp
- // start catch_uncaught_exceptions.cpp
-
-+// start catch_config_uncaught_exceptions.hpp
-+
-+// Copyright Catch2 Authors
-+// Distributed under the Boost Software License, Version 1.0.
-+// (See accompanying file LICENSE_1_0.txt or copy at
-+// https://www.boost.org/LICENSE_1_0.txt)
-+
-+// SPDX-License-Identifier: BSL-1.0
-+
-+#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
-+#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
-+
-+#if defined(_MSC_VER)
-+# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
-+# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
-+# endif
-+#endif
-+
-+#include <exception>
-+
-+#if defined(__cpp_lib_uncaught_exceptions) \
-+ && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
-+
-+# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
-+#endif // __cpp_lib_uncaught_exceptions
-+
-+#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
-+ && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
-+ && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
-+
-+# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
-+#endif
-+
-+#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
-+// end catch_config_uncaught_exceptions.hpp
- #include <exception>
-
- namespace Catch {
- bool uncaught_exceptions() {
--#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
-+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
-+ return false;
-+#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
- return std::uncaught_exceptions() > 0;
- #else
- return std::uncaught_exception();
-@@ -12119,7 +15387,7 @@
- }
-
- Version const& libraryVersion() {
-- static Version version( 2, 5, 0, "", 0 );
-+ static Version version( 2, 13, 8, "", 0 );
- return version;
- }
-
-@@ -12127,14 +15395,12 @@
- // end catch_version.cpp
- // start catch_wildcard_pattern.cpp
-
--#include <sstream>
--
- namespace Catch {
-
- WildcardPattern::WildcardPattern( std::string const& pattern,
- CaseSensitive::Choice caseSensitivity )
- : m_caseSensitivity( caseSensitivity ),
-- m_pattern( adjustCase( pattern ) )
-+ m_pattern( normaliseString( pattern ) )
- {
- if( startsWith( m_pattern, '*' ) ) {
- m_pattern = m_pattern.substr( 1 );
-@@ -12149,28 +15415,27 @@
- bool WildcardPattern::matches( std::string const& str ) const {
- switch( m_wildcard ) {
- case NoWildcard:
-- return m_pattern == adjustCase( str );
-+ return m_pattern == normaliseString( str );
- case WildcardAtStart:
-- return endsWith( adjustCase( str ), m_pattern );
-+ return endsWith( normaliseString( str ), m_pattern );
- case WildcardAtEnd:
-- return startsWith( adjustCase( str ), m_pattern );
-+ return startsWith( normaliseString( str ), m_pattern );
- case WildcardAtBothEnds:
-- return contains( adjustCase( str ), m_pattern );
-+ return contains( normaliseString( str ), m_pattern );
- default:
- CATCH_INTERNAL_ERROR( "Unknown enum" );
- }
- }
-
-- std::string WildcardPattern::adjustCase( std::string const& str ) const {
-- return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
-+ std::string WildcardPattern::normaliseString( std::string const& str ) const {
-+ return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str );
- }
- }
- // end catch_wildcard_pattern.cpp
- // start catch_xmlwriter.cpp
-
- #include <iomanip>
--
--using uchar = unsigned char;
-+#include <type_traits>
-
- namespace Catch {
-
-@@ -12203,13 +15468,37 @@
- }
-
- void hexEscapeChar(std::ostream& os, unsigned char c) {
-+ std::ios_base::fmtflags f(os.flags());
- os << "\\x"
- << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
- << static_cast<int>(c);
-+ os.flags(f);
-+ }
-+
-+ bool shouldNewline(XmlFormatting fmt) {
-+ return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline));
-+ }
-+
-+ bool shouldIndent(XmlFormatting fmt) {
-+ return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent));
- }
-
- } // anonymous namespace
-
-+ XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) {
-+ return static_cast<XmlFormatting>(
-+ static_cast<std::underlying_type<XmlFormatting>::type>(lhs) |
-+ static_cast<std::underlying_type<XmlFormatting>::type>(rhs)
-+ );
-+ }
-+
-+ XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) {
-+ return static_cast<XmlFormatting>(
-+ static_cast<std::underlying_type<XmlFormatting>::type>(lhs) &
-+ static_cast<std::underlying_type<XmlFormatting>::type>(rhs)
-+ );
-+ }
-+
- XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
- : m_str( str ),
- m_forWhat( forWhat )
-@@ -12220,7 +15509,7 @@
- // (see: http://www.w3.org/TR/xml/#syntax)
-
- for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
-- uchar c = m_str[idx];
-+ unsigned char c = m_str[idx];
- switch (c) {
- case '<': os << "&lt;"; break;
- case '&': os << "&amp;"; break;
-@@ -12280,7 +15569,7 @@
- bool valid = true;
- uint32_t value = headerValue(c);
- for (std::size_t n = 1; n < encBytes; ++n) {
-- uchar nc = m_str[idx + n];
-+ unsigned char nc = m_str[idx + n];
- valid &= ((nc & 0xC0) == 0x80);
- value = (value << 6) | (nc & 0x3F);
- }
-@@ -12314,13 +15603,17 @@
- return os;
- }
-
-- XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
-- : m_writer( writer )
-+ XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt )
-+ : m_writer( writer ),
-+ m_fmt(fmt)
- {}
-
- XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
-- : m_writer( other.m_writer ){
-+ : m_writer( other.m_writer ),
-+ m_fmt(other.m_fmt)
-+ {
- other.m_writer = nullptr;
-+ other.m_fmt = XmlFormatting::None;
- }
- XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
- if ( m_writer ) {
-@@ -12328,16 +15621,19 @@
- }
- m_writer = other.m_writer;
- other.m_writer = nullptr;
-+ m_fmt = other.m_fmt;
-+ other.m_fmt = XmlFormatting::None;
- return *this;
- }
-
- XmlWriter::ScopedElement::~ScopedElement() {
-- if( m_writer )
-- m_writer->endElement();
-+ if (m_writer) {
-+ m_writer->endElement(m_fmt);
-+ }
- }
-
-- XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
-- m_writer->writeText( text, indent );
-+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) {
-+ m_writer->writeText( text, fmt );
- return *this;
- }
-
-@@ -12347,37 +15643,47 @@
- }
-
- XmlWriter::~XmlWriter() {
-- while( !m_tags.empty() )
-+ while (!m_tags.empty()) {
- endElement();
-+ }
-+ newlineIfNecessary();
- }
-
-- XmlWriter& XmlWriter::startElement( std::string const& name ) {
-+ XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) {
- ensureTagClosed();
- newlineIfNecessary();
-- m_os << m_indent << '<' << name;
-+ if (shouldIndent(fmt)) {
-+ m_os << m_indent;
-+ m_indent += " ";
-+ }
-+ m_os << '<' << name;
- m_tags.push_back( name );
-- m_indent += " ";
- m_tagIsOpen = true;
-+ applyFormatting(fmt);
- return *this;
- }
-
-- XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
-- ScopedElement scoped( this );
-- startElement( name );
-+ XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) {
-+ ScopedElement scoped( this, fmt );
-+ startElement( name, fmt );
- return scoped;
- }
-
-- XmlWriter& XmlWriter::endElement() {
-- newlineIfNecessary();
-- m_indent = m_indent.substr( 0, m_indent.size()-2 );
-+ XmlWriter& XmlWriter::endElement(XmlFormatting fmt) {
-+ m_indent = m_indent.substr(0, m_indent.size() - 2);
-+
- if( m_tagIsOpen ) {
- m_os << "/>";
- m_tagIsOpen = false;
-+ } else {
-+ newlineIfNecessary();
-+ if (shouldIndent(fmt)) {
-+ m_os << m_indent;
-+ }
-+ m_os << "</" << m_tags.back() << ">";
- }
-- else {
-- m_os << m_indent << "</" << m_tags.back() << ">";
-- }
-- m_os << std::endl;
-+ m_os << std::flush;
-+ applyFormatting(fmt);
- m_tags.pop_back();
- return *this;
- }
-@@ -12393,22 +15699,26 @@
- return *this;
- }
-
-- XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
-+ XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) {
- if( !text.empty() ){
- bool tagWasOpen = m_tagIsOpen;
- ensureTagClosed();
-- if( tagWasOpen && indent )
-+ if (tagWasOpen && shouldIndent(fmt)) {
- m_os << m_indent;
-+ }
- m_os << XmlEncode( text );
-- m_needsNewline = true;
-+ applyFormatting(fmt);
- }
- return *this;
- }
-
-- XmlWriter& XmlWriter::writeComment( std::string const& text ) {
-+ XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) {
- ensureTagClosed();
-- m_os << m_indent << "<!--" << text << "-->";
-- m_needsNewline = true;
-+ if (shouldIndent(fmt)) {
-+ m_os << m_indent;
-+ }
-+ m_os << "<!--" << text << "-->";
-+ applyFormatting(fmt);
- return *this;
- }
-
-@@ -12424,11 +15734,16 @@
-
- void XmlWriter::ensureTagClosed() {
- if( m_tagIsOpen ) {
-- m_os << ">" << std::endl;
-+ m_os << '>' << std::flush;
-+ newlineIfNecessary();
- m_tagIsOpen = false;
- }
- }
-
-+ void XmlWriter::applyFormatting(XmlFormatting fmt) {
-+ m_needsNewline = shouldNewline(fmt);
-+ }
-+
- void XmlWriter::writeDeclaration() {
- m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
- }
-@@ -12469,11 +15784,37 @@
- #ifdef _MSC_VER
- sprintf_s(buffer, "%.3f", duration);
- #else
-- sprintf(buffer, "%.3f", duration);
-+ std::sprintf(buffer, "%.3f", duration);
- #endif
- return std::string(buffer);
- }
-
-+ bool shouldShowDuration( IConfig const& config, double duration ) {
-+ if ( config.showDurations() == ShowDurations::Always ) {
-+ return true;
-+ }
-+ if ( config.showDurations() == ShowDurations::Never ) {
-+ return false;
-+ }
-+ const double min = config.minDuration();
-+ return min >= 0 && duration >= min;
-+ }
-+
-+ std::string serializeFilters( std::vector<std::string> const& container ) {
-+ ReusableStringStream oss;
-+ bool first = true;
-+ for (auto&& filter : container)
-+ {
-+ if (!first)
-+ oss << ' ';
-+ else
-+ first = false;
-+
-+ oss << filter;
-+ }
-+ return oss.str();
-+ }
-+
- TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
- :StreamingReporterBase(_config) {}
-
-@@ -12689,24 +16030,25 @@
- if (itMessage == messages.end())
- return;
-
-- // using messages.end() directly yields (or auto) compilation error:
-- std::vector<MessageInfo>::const_iterator itEnd = messages.end();
-- const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
-+ const auto itEnd = messages.cend();
-+ const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
-
- {
- Colour colourGuard(colour);
- stream << " with " << pluralise(N, "message") << ':';
- }
-
-- for (; itMessage != itEnd; ) {
-+ while (itMessage != itEnd) {
- // If this assertion is a warning ignore any INFO messages
- if (printInfoMessages || itMessage->type != ResultWas::Info) {
-- stream << " '" << itMessage->message << '\'';
-- if (++itMessage != itEnd) {
-+ printMessage();
-+ if (itMessage != itEnd) {
- Colour colourGuard(dimColour());
- stream << " and";
- }
-+ continue;
- }
-+ ++itMessage;
- }
- }
-
-@@ -12724,10 +16066,6 @@
- return "Reports test results on a single line, suitable for IDEs";
- }
-
-- ReporterPreferences CompactReporter::getPreferences() const {
-- return m_reporterPrefs;
-- }
--
- void CompactReporter::noMatchingTestCases( std::string const& spec ) {
- stream << "No test cases matched '" << spec << '\'' << std::endl;
- }
-@@ -12754,8 +16092,9 @@
- }
-
- void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
-- if (m_config->showDurations() == ShowDurations::Always) {
-- stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
-+ double dur = _sectionStats.durationInSeconds;
-+ if ( shouldShowDuration( *m_config, dur ) ) {
-+ stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl;
- }
- }
-
-@@ -12779,8 +16118,13 @@
- #if defined(_MSC_VER)
- #pragma warning(push)
- #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
-- // Note that 4062 (not all labels are handled
-- // and default is missing) is enabled
-+ // Note that 4062 (not all labels are handled and default is missing) is enabled
-+#endif
-+
-+#if defined(__clang__)
-+# pragma clang diagnostic push
-+// For simplicity, benchmarking-only helpers are always enabled
-+# pragma clang diagnostic ignored "-Wunused-function"
- #endif
-
- namespace Catch {
-@@ -12962,11 +16306,11 @@
- static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
- static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
-
-- uint64_t m_inNanoseconds;
-+ double m_inNanoseconds;
- Unit m_units;
-
- public:
-- explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
-+ explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
- : m_inNanoseconds(inNanoseconds),
- m_units(units) {
- if (m_units == Unit::Auto) {
-@@ -12995,7 +16339,7 @@
- case Unit::Minutes:
- return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
- default:
-- return static_cast<double>(m_inNanoseconds);
-+ return m_inNanoseconds;
- }
- }
- auto unitsAsString() const -> std::string {
-@@ -13003,7 +16347,7 @@
- case Unit::Nanoseconds:
- return "ns";
- case Unit::Microseconds:
-- return "µs";
-+ return "us";
- case Unit::Milliseconds:
- return "ms";
- case Unit::Seconds:
-@@ -13016,7 +16360,7 @@
-
- }
- friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
-- return os << duration.value() << " " << duration.unitsAsString();
-+ return os << duration.value() << ' ' << duration.unitsAsString();
- }
- };
- } // end anon namespace
-@@ -13041,10 +16385,16 @@
- if (!m_isOpen) {
- m_isOpen = true;
- *this << RowBreak();
-- for (auto const& info : m_columnInfos)
-- *this << info.name << ColumnBreak();
-- *this << RowBreak();
-- m_os << Catch::getLineOfChars<'-'>() << "\n";
-+
-+ Columns headerCols;
-+ Spacer spacer(2);
-+ for (auto const& info : m_columnInfos) {
-+ headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2));
-+ headerCols += spacer;
-+ }
-+ m_os << headerCols << '\n';
-+
-+ m_os << Catch::getLineOfChars<'-'>() << '\n';
- }
- }
- void close() {
-@@ -13063,30 +16413,29 @@
-
- friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {
- auto colStr = tp.m_oss.str();
-- // This takes account of utf8 encodings
-- auto strSize = Catch::StringRef(colStr).numberOfCharacters();
-+ const auto strSize = colStr.size();
- tp.m_oss.str("");
- tp.open();
- if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
- tp.m_currentColumn = -1;
-- tp.m_os << "\n";
-+ tp.m_os << '\n';
- }
- tp.m_currentColumn++;
-
- auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
-- auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))
-- ? std::string(colInfo.width - (strSize + 2), ' ')
-+ auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width))
-+ ? std::string(colInfo.width - (strSize + 1), ' ')
- : std::string();
- if (colInfo.justification == ColumnInfo::Left)
-- tp.m_os << colStr << padding << " ";
-+ tp.m_os << colStr << padding << ' ';
- else
-- tp.m_os << padding << colStr << " ";
-+ tp.m_os << padding << colStr << ' ';
- return tp;
- }
-
- friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {
- if (tp.m_currentColumn > 0) {
-- tp.m_os << "\n";
-+ tp.m_os << '\n';
- tp.m_currentColumn = -1;
- }
- return tp;
-@@ -13096,12 +16445,26 @@
- ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
- : StreamingReporterBase(config),
- m_tablePrinter(new TablePrinter(config.stream(),
-- {
-- { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
-- { "iters", 8, ColumnInfo::Right },
-- { "elapsed ns", 14, ColumnInfo::Right },
-- { "average", 14, ColumnInfo::Right }
-- })) {}
-+ [&config]() -> std::vector<ColumnInfo> {
-+ if (config.fullConfig()->benchmarkNoAnalysis())
-+ {
-+ return{
-+ { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
-+ { " samples", 14, ColumnInfo::Right },
-+ { " iterations", 14, ColumnInfo::Right },
-+ { " mean", 14, ColumnInfo::Right }
-+ };
-+ }
-+ else
-+ {
-+ return{
-+ { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
-+ { "samples mean std dev", 14, ColumnInfo::Right },
-+ { "iterations low mean low std dev", 14, ColumnInfo::Right },
-+ { "estimated high mean high std dev", 14, ColumnInfo::Right }
-+ };
-+ }
-+ }())) {}
- ConsoleReporter::~ConsoleReporter() = default;
-
- std::string ConsoleReporter::getDescription() {
-@@ -13112,6 +16475,10 @@
- stream << "No test cases matched '" << spec << '\'' << std::endl;
- }
-
-+void ConsoleReporter::reportInvalidArguments(std::string const&arg){
-+ stream << "Invalid Filter: " << arg << std::endl;
-+}
-+
- void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
-
- bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
-@@ -13132,6 +16499,7 @@
- }
-
- void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {
-+ m_tablePrinter->close();
- m_headerPrinted = false;
- StreamingReporterBase::sectionStarting(_sectionInfo);
- }
-@@ -13146,8 +16514,9 @@
- stream << "\nNo assertions in test case";
- stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
- }
-- if (m_config->showDurations() == ShowDurations::Always) {
-- stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
-+ double dur = _sectionStats.durationInSeconds;
-+ if (shouldShowDuration(*m_config, dur)) {
-+ stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl;
- }
- if (m_headerPrinted) {
- m_headerPrinted = false;
-@@ -13155,28 +16524,53 @@
- StreamingReporterBase::sectionEnded(_sectionStats);
- }
-
--void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
-- lazyPrintWithoutClosingBenchmarkTable();
--
-- auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+void ConsoleReporter::benchmarkPreparing(std::string const& name) {
-+ lazyPrintWithoutClosingBenchmarkTable();
-+
-+ auto nameCol = Column(name).width(static_cast<std::size_t>(m_tablePrinter->columnInfos()[0].width - 2));
-+
-+ bool firstLine = true;
-+ for (auto line : nameCol) {
-+ if (!firstLine)
-+ (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
-+ else
-+ firstLine = false;
-
-- bool firstLine = true;
-- for (auto line : nameCol) {
-- if (!firstLine)
-- (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
-- else
-- firstLine = false;
-+ (*m_tablePrinter) << line << ColumnBreak();
-+ }
-+}
-
-- (*m_tablePrinter) << line << ColumnBreak();
-+void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
-+ (*m_tablePrinter) << info.samples << ColumnBreak()
-+ << info.iterations << ColumnBreak();
-+ if (!m_config->benchmarkNoAnalysis())
-+ (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak();
-+}
-+void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
-+ if (m_config->benchmarkNoAnalysis())
-+ {
-+ (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
-+ }
-+ else
-+ {
-+ (*m_tablePrinter) << ColumnBreak()
-+ << Duration(stats.mean.point.count()) << ColumnBreak()
-+ << Duration(stats.mean.lower_bound.count()) << ColumnBreak()
-+ << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
-+ << Duration(stats.standardDeviation.point.count()) << ColumnBreak()
-+ << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
-+ << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
- }
- }
--void ConsoleReporter::benchmarkEnded(BenchmarkStats const& stats) {
-- Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
-+
-+void ConsoleReporter::benchmarkFailed(std::string const& error) {
-+ Colour colour(Colour::Red);
- (*m_tablePrinter)
-- << stats.iterations << ColumnBreak()
-- << stats.elapsedTimeInNanoseconds << ColumnBreak()
-- << average << ColumnBreak();
-+ << "Benchmark failed (" << error << ')'
-+ << ColumnBreak() << RowBreak();
- }
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-
- void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
- m_tablePrinter->close();
-@@ -13198,6 +16592,10 @@
- stream << std::endl;
- StreamingReporterBase::testRunEnded(_testRunStats);
- }
-+void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) {
-+ StreamingReporterBase::testRunStarting(_testInfo);
-+ printTestFilters();
-+}
-
- void ConsoleReporter::lazyPrint() {
-
-@@ -13251,11 +16649,9 @@
-
- SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
-
-- if (!lineInfo.empty()) {
-- stream << getLineOfChars<'-'>() << '\n';
-- Colour colourGuard(Colour::FileName);
-- stream << lineInfo << '\n';
-- }
-+ stream << getLineOfChars<'-'>() << '\n';
-+ Colour colourGuard(Colour::FileName);
-+ stream << lineInfo << '\n';
- stream << getLineOfChars<'.'>() << '\n' << std::endl;
- }
-
-@@ -13379,6 +16775,13 @@
- stream << getLineOfChars<'-'>() << '\n';
- }
-
-+void ConsoleReporter::printTestFilters() {
-+ if (m_config->testSpec().hasFilters()) {
-+ Colour guard(Colour::BrightYellow);
-+ stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n';
-+ }
-+}
-+
- CATCH_REGISTER_REPORTER("console", ConsoleReporter)
-
- } // end namespace Catch
-@@ -13386,6 +16789,10 @@
- #if defined(_MSC_VER)
- #pragma warning(pop)
- #endif
-+
-+#if defined(__clang__)
-+# pragma clang diagnostic pop
-+#endif
- // end catch_reporter_console.cpp
- // start catch_reporter_junit.cpp
-
-@@ -13393,6 +16800,7 @@
- #include <sstream>
- #include <ctime>
- #include <algorithm>
-+#include <iomanip>
-
- namespace Catch {
-
-@@ -13420,7 +16828,7 @@
- #else
- std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
- #endif
-- return std::string(timeStamp);
-+ return std::string(timeStamp, timeStampSize-1);
- }
-
- std::string fileNameTag(const std::vector<std::string> &tags) {
-@@ -13431,6 +16839,17 @@
- return it->substr(1);
- return std::string();
- }
-+
-+ // Formats the duration in seconds to 3 decimal places.
-+ // This is done because some genius defined Maven Surefire schema
-+ // in a way that only accepts 3 decimal places, and tools like
-+ // Jenkins use that schema for validation JUnit reporter output.
-+ std::string formatDuration( double seconds ) {
-+ ReusableStringStream rss;
-+ rss << std::fixed << std::setprecision( 3 ) << seconds;
-+ return rss.str();
-+ }
-+
- } // anonymous namespace
-
- JunitReporter::JunitReporter( ReporterConfig const& _config )
-@@ -13490,6 +16909,7 @@
-
- void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
- XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
-+
- TestGroupStats const& stats = groupNode.value;
- xml.writeAttribute( "name", stats.groupInfo.name );
- xml.writeAttribute( "errors", unexpectedExceptions );
-@@ -13499,15 +16919,30 @@
- if( m_config->showDurations() == ShowDurations::Never )
- xml.writeAttribute( "time", "" );
- else
-- xml.writeAttribute( "time", suiteTime );
-+ xml.writeAttribute( "time", formatDuration( suiteTime ) );
- xml.writeAttribute( "timestamp", getCurrentTimestamp() );
-
-+ // Write properties if there are any
-+ if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {
-+ auto properties = xml.scopedElement("properties");
-+ if (m_config->hasTestFilters()) {
-+ xml.scopedElement("property")
-+ .writeAttribute("name", "filters")
-+ .writeAttribute("value", serializeFilters(m_config->getTestsOrTags()));
-+ }
-+ if (m_config->rngSeed() != 0) {
-+ xml.scopedElement("property")
-+ .writeAttribute("name", "random-seed")
-+ .writeAttribute("value", m_config->rngSeed());
-+ }
-+ }
-+
- // Write test cases
- for( auto const& child : groupNode.children )
- writeTestCase( *child );
-
-- xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false );
-- xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false );
-+ xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline );
-+ xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline );
- }
-
- void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
-@@ -13529,12 +16964,13 @@
- if ( !m_config->name().empty() )
- className = m_config->name() + "." + className;
-
-- writeSection( className, "", rootSection );
-+ writeSection( className, "", rootSection, stats.testInfo.okToFail() );
- }
-
-- void JunitReporter::writeSection( std::string const& className,
-- std::string const& rootName,
-- SectionNode const& sectionNode ) {
-+ void JunitReporter::writeSection( std::string const& className,
-+ std::string const& rootName,
-+ SectionNode const& sectionNode,
-+ bool testOkToFail) {
- std::string name = trim( sectionNode.stats.sectionInfo.name );
- if( !rootName.empty() )
- name = rootName + '/' + name;
-@@ -13551,20 +16987,30 @@
- xml.writeAttribute( "classname", className );
- xml.writeAttribute( "name", name );
- }
-- xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
-+ xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) );
-+ // This is not ideal, but it should be enough to mimic gtest's
-+ // junit output.
-+ // Ideally the JUnit reporter would also handle `skipTest`
-+ // events and write those out appropriately.
-+ xml.writeAttribute( "status", "run" );
-+
-+ if (sectionNode.stats.assertions.failedButOk) {
-+ xml.scopedElement("skipped")
-+ .writeAttribute("message", "TEST_CASE tagged with !mayfail");
-+ }
-
- writeAssertions( sectionNode );
-
- if( !sectionNode.stdOut.empty() )
-- xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
-+ xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );
- if( !sectionNode.stdErr.empty() )
-- xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
-+ xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline );
- }
- for( auto const& childNode : sectionNode.childSections )
- if( className.empty() )
-- writeSection( name, "", *childNode );
-+ writeSection( name, "", *childNode, testOkToFail );
- else
-- writeSection( className, name, *childNode );
-+ writeSection( className, name, *childNode, testOkToFail );
- }
-
- void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
-@@ -13582,11 +17028,7 @@
- elementName = "error";
- break;
- case ResultWas::ExplicitFailure:
-- elementName = "failure";
-- break;
- case ResultWas::ExpressionFailed:
-- elementName = "failure";
-- break;
- case ResultWas::DidntThrowException:
- elementName = "failure";
- break;
-@@ -13604,10 +17046,25 @@
-
- XmlWriter::ScopedElement e = xml.scopedElement( elementName );
-
-- xml.writeAttribute( "message", result.getExpandedExpression() );
-+ xml.writeAttribute( "message", result.getExpression() );
- xml.writeAttribute( "type", result.getTestMacroName() );
-
- ReusableStringStream rss;
-+ if (stats.totals.assertions.total() > 0) {
-+ rss << "FAILED" << ":\n";
-+ if (result.hasExpression()) {
-+ rss << " ";
-+ rss << result.getExpressionInMacro();
-+ rss << '\n';
-+ }
-+ if (result.hasExpandedExpression()) {
-+ rss << "with expansion:\n";
-+ rss << Column(result.getExpandedExpression()).indent(2) << '\n';
-+ }
-+ } else {
-+ rss << '\n';
-+ }
-+
- if( !result.getMessage().empty() )
- rss << result.getMessage() << '\n';
- for( auto const& msg : stats.infoMessages )
-@@ -13615,7 +17072,7 @@
- rss << msg.message << '\n';
-
- rss << "at " << result.getSourceInfo();
-- xml.writeText( rss.str(), false );
-+ xml.writeText( rss.str(), XmlFormatting::Newline );
- }
- }
-
-@@ -13659,19 +17116,41 @@
- m_reporter->noMatchingTestCases( spec );
- }
-
-+ void ListeningReporter::reportInvalidArguments(std::string const&arg){
-+ for ( auto const& listener : m_listeners ) {
-+ listener->reportInvalidArguments( arg );
-+ }
-+ m_reporter->reportInvalidArguments( arg );
-+ }
-+
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ void ListeningReporter::benchmarkPreparing( std::string const& name ) {
-+ for (auto const& listener : m_listeners) {
-+ listener->benchmarkPreparing(name);
-+ }
-+ m_reporter->benchmarkPreparing(name);
-+ }
- void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
- for ( auto const& listener : m_listeners ) {
- listener->benchmarkStarting( benchmarkInfo );
- }
- m_reporter->benchmarkStarting( benchmarkInfo );
- }
-- void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
-+ void ListeningReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) {
- for ( auto const& listener : m_listeners ) {
- listener->benchmarkEnded( benchmarkStats );
- }
- m_reporter->benchmarkEnded( benchmarkStats );
- }
-
-+ void ListeningReporter::benchmarkFailed( std::string const& error ) {
-+ for (auto const& listener : m_listeners) {
-+ listener->benchmarkFailed(error);
-+ }
-+ m_reporter->benchmarkFailed(error);
-+ }
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-+
- void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
- for ( auto const& listener : m_listeners ) {
- listener->testRunStarting( testRunInfo );
-@@ -13802,6 +17281,8 @@
- m_xml.startElement( "Catch" );
- if( !m_config->name().empty() )
- m_xml.writeAttribute( "name", m_config->name() );
-+ if (m_config->testSpec().hasFilters())
-+ m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) );
- if( m_config->rngSeed() != 0 )
- m_xml.scopedElement( "Randomness" )
- .writeAttribute( "seed", m_config->rngSeed() );
-@@ -13937,9 +17418,9 @@
- e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
-
- if( !testCaseStats.stdOut.empty() )
-- m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
-+ m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline );
- if( !testCaseStats.stdErr.empty() )
-- m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
-+ m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline );
-
- m_xml.endElement();
- }
-@@ -13951,6 +17432,10 @@
- .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
- .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
- .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
-+ m_xml.scopedElement( "OverallResultsCases")
-+ .writeAttribute( "successes", testGroupStats.totals.testCases.passed )
-+ .writeAttribute( "failures", testGroupStats.totals.testCases.failed )
-+ .writeAttribute( "expectedFailures", testGroupStats.totals.testCases.failedButOk );
- m_xml.endElement();
- }
-
-@@ -13960,9 +17445,58 @@
- .writeAttribute( "successes", testRunStats.totals.assertions.passed )
- .writeAttribute( "failures", testRunStats.totals.assertions.failed )
- .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
-+ m_xml.scopedElement( "OverallResultsCases")
-+ .writeAttribute( "successes", testRunStats.totals.testCases.passed )
-+ .writeAttribute( "failures", testRunStats.totals.testCases.failed )
-+ .writeAttribute( "expectedFailures", testRunStats.totals.testCases.failedButOk );
-+ m_xml.endElement();
-+ }
-+
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+ void XmlReporter::benchmarkPreparing(std::string const& name) {
-+ m_xml.startElement("BenchmarkResults")
-+ .writeAttribute("name", name);
-+ }
-+
-+ void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
-+ m_xml.writeAttribute("samples", info.samples)
-+ .writeAttribute("resamples", info.resamples)
-+ .writeAttribute("iterations", info.iterations)
-+ .writeAttribute("clockResolution", info.clockResolution)
-+ .writeAttribute("estimatedDuration", info.estimatedDuration)
-+ .writeComment("All values in nano seconds");
-+ }
-+
-+ void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
-+ m_xml.startElement("mean")
-+ .writeAttribute("value", benchmarkStats.mean.point.count())
-+ .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count())
-+ .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count())
-+ .writeAttribute("ci", benchmarkStats.mean.confidence_interval);
-+ m_xml.endElement();
-+ m_xml.startElement("standardDeviation")
-+ .writeAttribute("value", benchmarkStats.standardDeviation.point.count())
-+ .writeAttribute("lowerBound", benchmarkStats.standardDeviation.lower_bound.count())
-+ .writeAttribute("upperBound", benchmarkStats.standardDeviation.upper_bound.count())
-+ .writeAttribute("ci", benchmarkStats.standardDeviation.confidence_interval);
-+ m_xml.endElement();
-+ m_xml.startElement("outliers")
-+ .writeAttribute("variance", benchmarkStats.outlierVariance)
-+ .writeAttribute("lowMild", benchmarkStats.outliers.low_mild)
-+ .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe)
-+ .writeAttribute("highMild", benchmarkStats.outliers.high_mild)
-+ .writeAttribute("highSevere", benchmarkStats.outliers.high_severe);
-+ m_xml.endElement();
- m_xml.endElement();
- }
-
-+ void XmlReporter::benchmarkFailed(std::string const &error) {
-+ m_xml.scopedElement("failed").
-+ writeAttribute("message", error);
-+ m_xml.endElement();
-+ }
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-+
- CATCH_REGISTER_REPORTER( "xml", XmlReporter )
-
- } // end namespace Catch
-@@ -13988,7 +17522,7 @@
-
- #ifndef __OBJC__
-
--#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
-+#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
- // Standard C/C++ Win32 Unicode wmain entry point
- extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
- #else
-@@ -14036,7 +17570,7 @@
- #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
- #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
-
--#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
-+#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
- #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
- #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
- #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
-@@ -14050,7 +17584,7 @@
- #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
- #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
-
--#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
-+#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
- #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
- #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
- #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
-@@ -14065,6 +17599,7 @@
- #endif // CATCH_CONFIG_DISABLE_MATCHERS
-
- #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
-+#define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
- #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
- #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
-
-@@ -14082,10 +17617,22 @@
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
- #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
-+#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
- #else
- #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
-+#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
- #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
-+#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
- #endif
-
- #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
-@@ -14106,6 +17653,13 @@
- #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
- #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+#define CATCH_BENCHMARK(...) \
-+ INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
-+#define CATCH_BENCHMARK_ADVANCED(name) \
-+ INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name)
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-+
- // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
- #else
-
-@@ -14141,6 +17695,7 @@
- #endif // CATCH_CONFIG_DISABLE_MATCHERS
-
- #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
-+#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
- #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
- #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
-
-@@ -14157,10 +17712,26 @@
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
- #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
-+#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
-+#define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
-+#define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
- #else
- #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
-+#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
- #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
-+#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
-+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
-+#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
-+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
-+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
-+#define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
-+#define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
- #endif
-
- #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
-@@ -14186,6 +17757,13 @@
- #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
- #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
-
-+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-+#define BENCHMARK(...) \
-+ INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
-+#define BENCHMARK_ADVANCED(name) \
-+ INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name)
-+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
-+
- using Catch::Detail::Approx;
-
- #else // CATCH_CONFIG_DISABLE
-@@ -14225,12 +17803,13 @@
- #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
- #endif // CATCH_CONFIG_DISABLE_MATCHERS
-
--#define CATCH_INFO( msg ) (void)(0)
--#define CATCH_WARN( msg ) (void)(0)
--#define CATCH_CAPTURE( msg ) (void)(0)
-+#define CATCH_INFO( msg ) (void)(0)
-+#define CATCH_UNSCOPED_INFO( msg ) (void)(0)
-+#define CATCH_WARN( msg ) (void)(0)
-+#define CATCH_CAPTURE( msg ) (void)(0)
-
--#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
--#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
-+#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
-+#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
- #define CATCH_METHOD_AS_TEST_CASE( method, ... )
- #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
- #define CATCH_SECTION( ... )
-@@ -14239,19 +17818,31 @@
- #define CATCH_FAIL_CHECK( ... ) (void)(0)
- #define CATCH_SUCCEED( ... ) (void)(0)
-
--#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
-+#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
--#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
--#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
-+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
-+#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
-+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
-+#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
- #else
--#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
--#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
-+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
-+#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
-+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
-+#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
-+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
- #endif
-
- // "BDD-style" convenience wrappers
--#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
--#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
-+#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
-+#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className )
- #define CATCH_GIVEN( desc )
- #define CATCH_AND_GIVEN( desc )
- #define CATCH_WHEN( desc )
-@@ -14297,11 +17888,12 @@
- #endif // CATCH_CONFIG_DISABLE_MATCHERS
-
- #define INFO( msg ) (void)(0)
-+#define UNSCOPED_INFO( msg ) (void)(0)
- #define WARN( msg ) (void)(0)
- #define CAPTURE( msg ) (void)(0)
-
--#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
--#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
-+#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
-+#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
- #define METHOD_AS_TEST_CASE( method, ... )
- #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
- #define SECTION( ... )
-@@ -14309,14 +17901,26 @@
- #define FAIL( ... ) (void)(0)
- #define FAIL_CHECK( ... ) (void)(0)
- #define SUCCEED( ... ) (void)(0)
--#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
-+#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
--#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
--#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
-+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
-+#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
-+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
-+#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
- #else
--#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
--#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
-+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
-+#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
-+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
-+#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
-+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
-+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
- #endif
-
- #define STATIC_REQUIRE( ... ) (void)(0)
-@@ -14327,8 +17931,8 @@
- #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
-
- // "BDD-style" convenience wrappers
--#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
--#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
-+#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ) )
-+#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className )
-
- #define GIVEN( desc )
- #define AND_GIVEN( desc )
diff --git a/debian/patches/use-packaged-streamvbyte.patch b/debian/patches/use-packaged-streamvbyte.patch
index 5586f96..7e6428b 100644
--- a/debian/patches/use-packaged-streamvbyte.patch
+++ b/debian/patches/use-packaged-streamvbyte.patch
@@ -2,9 +2,9 @@ Description: Use packaged streamvbyte instead of third_party
Author: Nilesh Patra <nilesh@debian.org>
Forwarded: not-needed
Last-Update: 2021-05-22
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -138,34 +138,8 @@
+--- libvbz-hdf-plugin.orig/CMakeLists.txt
++++ libvbz-hdf-plugin/CMakeLists.txt
+@@ -145,34 +145,8 @@
find_package(HDF5 1.8.16)
find_package(zstd 1.3.1 REQUIRED)
find_package(Sanitizers)
@@ -41,8 +41,8 @@ Last-Update: 2021-05-22
########################################################################
#
---- a/vbz/CMakeLists.txt
-+++ b/vbz/CMakeLists.txt
+--- libvbz-hdf-plugin.orig/vbz/CMakeLists.txt
++++ libvbz-hdf-plugin/vbz/CMakeLists.txt
@@ -22,14 +22,16 @@
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
@@ -62,9 +62,9 @@ Last-Update: 2021-05-22
- streamvbyte
-)
- if (WIN32 OR APPLE OR "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86_64")
- if(NOT MSVC)
-@@ -37,12 +39,6 @@
+ if (WIN32 OR
+ (APPLE AND NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm64") OR
+@@ -39,12 +41,6 @@
endif()
endif()
diff --git a/debian/rules b/debian/rules
index 916af7f..2092f08 100755
--- a/debian/rules
+++ b/debian/rules
@@ -2,6 +2,7 @@
# DH_VERBOSE := 1
export LC_ALL=C.UTF-8
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
include /usr/share/dpkg/default.mk
diff --git a/python/test/requirements_1.10.txt b/python/test/requirements_1.10.txt
index 0146f57..e1195fe 100644
--- a/python/test/requirements_1.10.txt
+++ b/python/test/requirements_1.10.txt
@@ -1 +1,4 @@
-h5py==2.9.0 \ No newline at end of file
+# h5py 2 support was dropped in Python 3.9
+h5py==2.10.0
+# numpy 1.18.5 is the last version that supports Python 3.5
+numpy==1.18.5
diff --git a/python/test/requirements_1.12.txt b/python/test/requirements_1.12.txt
new file mode 100644
index 0000000..b46db0d
--- /dev/null
+++ b/python/test/requirements_1.12.txt
@@ -0,0 +1,2 @@
+# Originally built against Python 3.9
+h5py==3.6.0
diff --git a/third_party/gsl-disable-gsl-suppress.patch b/third_party/gsl-disable-gsl-suppress.patch
new file mode 100644
index 0000000..fb1a126
--- /dev/null
+++ b/third_party/gsl-disable-gsl-suppress.patch
@@ -0,0 +1,11 @@
+--- a/include/gsl/gsl-lite.hpp
++++ b/include/gsl/gsl-lite.hpp
+@@ -1081,7 +1081,7 @@ namespace __cxxabiv1 { struct __cxa_eh_globals; extern "C" __cxa_eh_globals * __
+ // MSVC warning suppression macros:
+
+ #if gsl_COMPILER_MSVC_VERSION >= 140 && ! gsl_COMPILER_NVCC_VERSION
+-# define gsl_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
++# define gsl_SUPPRESS_MSGSL_WARNING(expr) /* Pimm: note disabled for intel [[gsl::suppress(expr)]]*/
+ # define gsl_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) )
+ # define gsl_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
+ # define gsl_RESTORE_MSVC_WARNINGS() __pragma(warning(pop ))
diff --git a/third_party/gsl.h b/third_party/gsl.h
index 0d79484..1bfa97f 100755..100644
--- a/third_party/gsl.h
+++ b/third_party/gsl.h
@@ -1,6 +1,6 @@
//
-// gsl-lite is based on GSL: Guideline Support Library.
-// For more information see https://github.com/martinmoene/gsl-lite
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
//
// Copyright (c) 2015 Martin Moene
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
@@ -17,11 +17,11 @@
// mimic MS include hierarchy
-#pragma once
-
#ifndef GSL_GSL_H_INCLUDED
#define GSL_GSL_H_INCLUDED
-#include "gsl/gsl-lite.h"
+#pragma message ("gsl.h is deprecated since version 0.27.0, use gsl/gsl-lite.hpp instead.")
+
+#include "gsl/gsl-lite.hpp"
#endif // GSL_GSL_H_INCLUDED
diff --git a/third_party/gsl/gsl b/third_party/gsl/gsl
index 339bd31..7ef52ac 100755..100644
--- a/third_party/gsl/gsl
+++ b/third_party/gsl/gsl
@@ -1,5 +1,5 @@
//
-// gsl-lite is based on GSL: Guideline Support Library.
+// gsl-lite is based on GSL: Guidelines Support Library.
// For more information see https://github.com/martinmoene/gsl-lite
//
// Copyright (c) 2015 Martin Moene
@@ -22,6 +22,8 @@
#ifndef GSL_GSL_H_INCLUDED
#define GSL_GSL_H_INCLUDED
-#include "gsl-lite.h"
+#pragma message ("gsl/gsl is deprecated since version 0.38.1, use gsl/gsl-lite.hpp instead.")
+
+#include "gsl-lite.hpp"
#endif // GSL_GSL_H_INCLUDED
diff --git a/third_party/gsl/gsl-lite-vc6.h b/third_party/gsl/gsl-lite-vc6.hpp
index 96b1904..3579336 100755..100644
--- a/third_party/gsl/gsl-lite-vc6.h
+++ b/third_party/gsl/gsl-lite-vc6.hpp
@@ -1,6 +1,6 @@
//
-// gsl-lite-vc6 is based on GSL: Guideline Support Library,
-// For more information see https://github.com/martinmoene/gsl-lite
+// gsl-lite-vc6 is based on GSL: Guidelines Support Library,
+// For more information see https://github.com/gsl-lite/gsl-lite
//
// Copyright (c) 2015 Martin Moene
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
@@ -33,20 +33,20 @@
// Configuration:
-#ifndef gsl_FEATURE_HAVE_IMPLICIT_MACRO
-# define gsl_FEATURE_HAVE_IMPLICIT_MACRO 1
+#ifndef gsl_FEATURE_IMPLICIT_MACRO
+# define gsl_FEATURE_IMPLICIT_MACRO 1
#endif
-#ifndef gsl_FEATURE_HAVE_OWNER_MACRO
-# define gsl_FEATURE_HAVE_OWNER_MACRO 1
+#ifndef gsl_FEATURE_OWNER_MACRO
+# define gsl_FEATURE_OWNER_MACRO 1
#endif
-#ifndef gsl_FEATURE_HAVE_SHARED_PTR
-# define gsl_FEATURE_HAVE_SHARED_PTR 0
+#ifndef gsl_FEATURE_SHARED_PTR
+# define gsl_FEATURE_SHARED_PTR 0
#endif
-#ifndef gsl_FEATURE_HAVE_UNIQUE_PTR
-# define gsl_FEATURE_HAVE_UNIQUE_PTR 0
+#ifndef gsl_FEATURE_UNIQUE_PTR
+# define gsl_FEATURE_UNIQUE_PTR 0
#endif
#ifndef gsl_CONFIG_THROWS_FOR_TESTING
@@ -75,35 +75,37 @@
// Compiler detection:
-#if defined(_MSC_VER)
-# define gsl_COMPILER_MSVC_VERSION (_MSC_VER / 100 - 5 - (_MSC_VER < 1900))
+#if defined(_MSC_VER ) && !defined(__clang__)
+# define gsl_COMPILER_MSVC_VER (_MSC_VER )
+# define gsl_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
#else
+# define gsl_COMPILER_MSVC_VER 0
# define gsl_COMPILER_MSVC_VERSION 0
# define gsl_COMPILER_NON_MSVC 1
#endif
-#if gsl_COMPILER_MSVC_VERSION != 6
+#if gsl_COMPILER_MSVC_VERSION != 60
# error GSL Lite: this header is for Visual C++ 6
#endif
// half-open range [lo..hi):
-#define gsl_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
+#define gsl_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
// Presence of C++ language features:
// C++ feature usage:
-#if gsl_FEATURE_HAVE_IMPLICIT_MACRO
+#if gsl_FEATURE_IMPLICIT_MACRO
# define implicit
#endif
#define gsl_DIMENSION_OF( a ) ( sizeof(a) / sizeof(0[a]) )
-#if gsl_FEATURE_HAVE_SHARED_PTR
+#if gsl_FEATURE_SHARED_PTR
# include gsl_CONFIG_SHARED_PTR_INCLUDE
#endif
-#if gsl_FEATURE_HAVE_UNIQUE_PTR
+#if gsl_FEATURE_UNIQUE_PTR
# include gsl_CONFIG_UNIQUE_PTR_INCLUDE
#endif
@@ -113,10 +115,10 @@ namespace gsl {
// GSL.owner: ownership pointers
//
// ToDo:
-#if gsl_FEATURE_HAVE_SHARED_PTR
+#if gsl_FEATURE_SHARED_PTR
using gsl_CONFIG_SHARED_PTR_DECL;
#endif
-#if gsl_FEATURE_HAVE_UNIQUE_PTR
+#if gsl_FEATURE_UNIQUE_PTR
using gsl_CONFIG_UNIQUE_PTR_DECL;
#endif
@@ -124,7 +126,7 @@ template< class T > struct owner { typedef T type; };
#define gsl_HAVE_OWNER_TEMPLATE 0
-#if gsl_FEATURE_HAVE_OWNER_MACRO
+#if gsl_FEATURE_OWNER_MACRO
# define Owner(t) ::gsl::owner<t>::type
#endif
@@ -177,15 +179,15 @@ inline void fail_fast_assert( bool cond, char const * const )
// GSL.util: utilities
//
-class final_act
+class final_action
{
public:
typedef void (*Action)();
- final_act( Action action )
+ final_action( Action action )
: action_( action ) {}
- ~final_act()
+ ~final_action()
{
action_();
}
@@ -195,9 +197,9 @@ private:
};
template< class Fn >
-final_act finally( Fn const & f )
+final_action finally( Fn const & f )
{
- return final_act(( f ));
+ return final_action(( f ));
}
template< class T, class U >
@@ -655,7 +657,7 @@ namespace detail {
template<class T, class SizeType, const T Sentinel>
struct ensure
{
- static span<T> sentinel( T * seq, SizeType max = std::numeric_limits<SizeType>::max() )
+ static span<T> sentinel( T * seq, SizeType max = (std::numeric_limits<SizeType>::max)() )
{
typedef T * pointer;
typedef typename std::iterator_traits<pointer>::difference_type difference_type;
@@ -679,7 +681,7 @@ struct ensure
//
template< typename T >
-span<T> ensure_z( T * sz, size_t max = std::numeric_limits<size_t>::max() )
+span<T> ensure_z( T * sz, size_t max = (std::numeric_limits<size_t>::max)() )
{
return detail::ensure<T, size_t, 0>::sentinel( sz, max );
}
diff --git a/third_party/gsl/gsl-lite.h b/third_party/gsl/gsl-lite.h
index aae4b3e..a738253 100755..100644
--- a/third_party/gsl/gsl-lite.h
+++ b/third_party/gsl/gsl-lite.h
@@ -1,2251 +1,27 @@
//
-// gsl-lite is based on GSL: Guideline Support Library.
-// For more information see https://github.com/martinmoene/gsl-lite
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
//
// Copyright (c) 2015 Martin Moene
-// 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.
-
-#pragma once
+// 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.
+
+// mimic MS include hierarchy
#ifndef GSL_GSL_LITE_H_INCLUDED
#define GSL_GSL_LITE_H_INCLUDED
-#include <exception>
-#include <iterator>
-#include <limits>
-#include <memory>
-#include <ostream>
-#include <stdexcept>
-#include <string>
-#include <utility>
-#include <vector>
-
-#define gsl_lite_VERSION "0.22.0"
-
-// gsl-lite backward compatibility:
-
-#ifdef gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR
-# define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR
-# pragma message ("gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR is deprecated since gsl-lite 0.7.0; replace with gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR, or consider span(with_container, cont).")
-#endif
-
-// M-GSL compatibility:
-
-#if defined( GSL_THROW_ON_CONTRACT_VIOLATION )
-# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS 1
-#endif
-
-#if defined( GSL_TERMINATE_ON_CONTRACT_VIOLATION )
-# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS 0
-#endif
-
-#if defined( GSL_UNENFORCED_ON_CONTRACT_VIOLATION )
-# define gsl_CONFIG_CONTRACT_LEVEL_OFF 1
-#endif
-
-// Configuration:
-
-#ifndef gsl_FEATURE_HAVE_IMPLICIT_MACRO
-# define gsl_FEATURE_HAVE_IMPLICIT_MACRO 1
-#endif
-
-#ifndef gsl_FEATURE_HAVE_OWNER_MACRO
-# define gsl_FEATURE_HAVE_OWNER_MACRO 1
-#endif
-
-#ifndef gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD
-# define gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD 0
-#endif
-
-#ifndef gsl_CONFIG_SPAN_INDEX_TYPE
-# define gsl_CONFIG_SPAN_INDEX_TYPE size_t
-#endif
-
-#ifndef gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS
-# define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS 0
-#endif
-
-#ifndef gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
-# define gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON 1
-#endif
-
-#ifndef gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR
-# define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR 0
-#endif
-
-#if defined( gsl_CONFIG_CONTRACT_LEVEL_ON )
-# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x11
-#elif defined( gsl_CONFIG_CONTRACT_LEVEL_OFF )
-# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x00
-#elif defined( gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY )
-# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x01
-#elif defined( gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY )
-# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x10
-#else
-# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x11
-#endif
-
-#if !defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && \
- !defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES )
-# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V 0
-#elif defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && \
- !defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES )
-# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V 1
-#elif !defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && \
- defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES )
-# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V 0
-#else
-# error only one of gsl_CONFIG_CONTRACT_VIOLATION_THROWS and gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES may be defined.
-#endif
-
-// Compiler detection (C++17 is speculative):
-
-#define gsl_CPP11_OR_GREATER ( __cplusplus >= 201103L )
-#define gsl_CPP14_OR_GREATER ( __cplusplus >= 201402L )
-#define gsl_CPP17_OR_GREATER ( __cplusplus >= 201700L )
-
-// half-open range [lo..hi):
-#define gsl_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
-
-#if defined(_MSC_VER) && !defined(__clang__)
-# define gsl_COMPILER_MSVC_VERSION (_MSC_VER / 100 - 5 - (_MSC_VER < 1900))
-#else
-# define gsl_COMPILER_MSVC_VERSION 0
-# define gsl_COMPILER_NON_MSVC 1
-#endif
-
-// Note: simplistic version computation; works for GCC versions on http://godbolt.org/
-#if defined(__GNUC__) && !defined(__clang__)
-# define gsl_COMPILER_GCC_VERSION ( 10 * (10 *__GNUC__ + __GNUC_MINOR__) + __GNUC_PATCHLEVEL__)
-#else
-# define gsl_COMPILER_GCC_VERSION 0
-#endif
-
-// Presence of C++11 language features:
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 10
-# define gsl_HAVE_AUTO 1
-# define gsl_HAVE_NULLPTR 1
-#endif
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 12
-# define gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG 1
-#endif
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 14
-# define gsl_HAVE_ALIAS_TEMPLATE 1
-# define gsl_HAVE_CONSTEXPR_11 1
-# define gsl_HAVE_ENUM_CLASS 1
-# define gsl_HAVE_EXPLICIT_CONVERSION 1
-# define gsl_HAVE_INITIALIZER_LIST 1
-# define gsl_HAVE_IS_DEFAULT 1
-# define gsl_HAVE_IS_DELETE 1
-# define gsl_HAVE_NOEXCEPT 1
-#endif
-
-#if gsl_CPP11_OR_GREATER
-// see above
-#endif
-
-// Presence of C++14 language features:
-
-#if gsl_CPP14_OR_GREATER
-# define gsl_HAVE_CONSTEXPR_14 1
-#endif
-
-// Presence of C++17 language features:
-
-#if gsl_CPP17_OR_GREATER
-# define gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE 1
-#endif
-
-// Presence of C++ library features:
-
-#if gsl_COMPILER_GCC_VERSION
-# define gsl_HAVE_TR1_TYPE_TRAITS 1
-#endif
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 11
-# define gsl_HAVE_ARRAY 1
-# define gsl_HAVE_TR1_TYPE_TRAITS 1
-#endif
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 14 || (gsl_COMPILER_MSVC_VERSION >= 9 && _HAS_CPP0X)
-# define gsl_HAVE_CONTAINER_DATA_METHOD 1
-#endif
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 14
-# define gsl_HAVE_SIZED_TYPES 1
-#endif
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 14 || (gsl_COMPILER_MSVC_VERSION >= 10 && _HAS_CPP0X)
-# define gsl_HAVE_SHARED_PTR 1
-# define gsl_HAVE_UNIQUE_PTR 1
-#endif
-
-#if gsl_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 12
-# define gsl_HAVE_MAKE_UNIQUE 1
-#endif
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 11
-# define gsl_HAVE_TYPE_TRAITS 1
-#endif
-
-#if gsl_HAVE_TYPE_TRAITS
-# define gsl_HAVE_ADD_CONST 1
-# define gsl_HAVE_INTEGRAL_CONSTANT 1
-# define gsl_HAVE_REMOVE_REFERENCE 1
-#elif gsl_HAVE_TR1_TYPE_TRAITS
-# define gsl_HAVE_TR1_ADD_CONST 1
-# define gsl_HAVE_TR1_INTEGRAL_CONSTANT 1
-# define gsl_HAVE_TR1_REMOVE_REFERENCE 1
-#endif
-
-// For the rest, consider VC12, VC14 as C++11 for GSL Lite:
-
-#if gsl_COMPILER_MSVC_VERSION >= 12
-# undef gsl_CPP11_OR_GREATER
-# define gsl_CPP11_OR_GREATER 1
-#endif
-
-// C++ feature usage:
-
-#if gsl_HAVE_CONSTEXPR_11
-# define gsl_constexpr constexpr
-#else
-# define gsl_constexpr /*constexpr*/
-#endif
-
-#if gsl_HAVE_CONSTEXPR_14
-# define gsl_constexpr14 constexpr
-#else
-# define gsl_constexpr14 /*constexpr*/
-#endif
-
-#if gsl_HAVE_EXPLICIT_CONVERSION
-# define gsl_explicit explicit
-#else
-# define gsl_explicit /*explicit*/
-#endif
-
-#if gsl_FEATURE_HAVE_IMPLICIT_MACRO
-# define implicit /*implicit*/
-#endif
-
-#if !gsl_HAVE_NOEXCEPT || gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V
-# define gsl_noexcept /*noexcept*/
-#else
-# define gsl_noexcept noexcept
-#endif
-
-#if gsl_HAVE_NULLPTR
-# define gsl_nullptr nullptr
-#else
-# define gsl_nullptr NULL
-#endif
-
-#define gsl_DIMENSION_OF( a ) ( sizeof(a) / sizeof(0[a]) )
-
-// Other features:
-
-#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG && gsl_HAVE_CONTAINER_DATA_METHOD
-# define gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR 1
-#endif
-
-// Note: !defined(__NVCC__) doesn't work with nvcc here:
-#define gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR \
- ( gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR && (__NVCC__== 0) )
-
-// GSL API (e.g. for CUDA platform):
-
-#ifndef gsl_api
-# ifdef __CUDACC__
-# define gsl_api __host__ __device__
-# else
-# define gsl_api /*gsl_api*/
-# endif
-#endif
-
-// additional includes:
-
-#if gsl_HAVE_ARRAY
-# include <array>
-#endif
-
-#if gsl_HAVE_TYPE_TRAITS
-# include <type_traits>
-#elif gsl_HAVE_TR1_TYPE_TRAITS
-# include <tr1/type_traits>
-#endif
-
-#if gsl_HAVE_SIZED_TYPES
-# include <cstdint>
-#endif
-
-namespace gsl {
-
-namespace detail {
-
-// C++11 emulation:
-
-#if gsl_HAVE_ADD_CONST
-
-using std::add_const;
-
-#elif gsl_HAVE_TR1_ADD_CONST
-
-using std::tr1::add_const;
-
-#else
-
-template< class T > struct add_const { typedef const T type; };
-
-#endif // gsl_HAVE_ADD_CONST
-
-#if gsl_HAVE_REMOVE_CONST
-
-using std::remove_cv;
-using std::remove_const;
-using std::remove_volatile;
-
-#elif gsl_HAVE_TR1_REMOVE_CONST
-
-using std::tr1::remove_cv;
-using std::tr1::remove_const;
-using std::tr1::remove_volatile;
-
-#else
-
-template< class T > struct remove_const { typedef T type; };
-template< class T > struct remove_const<T const> { typedef T type; };
-
-template< class T > struct remove_volatile { typedef T type; };
-template< class T > struct remove_volatile<T volatile> { typedef T type; };
-
-template< class T >
-struct remove_cv
-{
- typedef typename detail::remove_volatile<typename detail::remove_const<T>::type>::type type;
-};
-
-#endif // gsl_HAVE_REMOVE_CONST
-
-#if gsl_HAVE_INTEGRAL_CONSTANT
-
-using std::integral_constant;
-using std::true_type;
-using std::false_type;
-
-#elif gsl_HAVE_TR1_INTEGRAL_CONSTANT
-
-using std::tr1::integral_constant;
-using std::tr1::true_type;
-using std::tr1::false_type;
-
-#else
-
-template< int v > struct integral_constant { enum { value = v }; };
-typedef integral_constant< true > true_type;
-typedef integral_constant< false > false_type;
-
-#endif
-
-#if gsl_HAVE_ARRAY
-
-template< class T >
-struct is_std_array_oracle : false_type {};
-
-template< class T, std::size_t N >
-struct is_std_array_oracle< std::array<T, N> > : true_type {};
-
-template< class T >
-struct is_std_array : is_std_array_oracle< typename remove_cv<T>::type > {};
-
-#endif
-
-} // namespace detail
-
-//
-// GSL.owner: ownership pointers
-//
-#if gsl_HAVE_SHARED_PTR
- using std::unique_ptr;
- using std::shared_ptr;
- using std::make_shared;
-# if gsl_HAVE_MAKE_UNIQUE
- using std::make_unique;
-# endif
-#endif
-
-#if gsl_HAVE_ALIAS_TEMPLATE
- template< class T > using owner = T;
-#else
- template< class T > struct owner { typedef T type; };
-#endif
-
-#define gsl_HAVE_OWNER_TEMPLATE gsl_HAVE_ALIAS_TEMPLATE
-
-#if gsl_FEATURE_HAVE_OWNER_MACRO
-# if gsl_HAVE_OWNER_TEMPLATE
-# define Owner(t) ::gsl::owner<t>
-# else
-# define Owner(t) ::gsl::owner<t>::type
-# endif
-#endif
-
-//
-// GSL.assert: assertions
-//
-
-#define gsl_ELIDE_CONTRACT_EXPECTS ( 0 == ( gsl_CONFIG_CONTRACT_LEVEL_MASK & 0x01 ) )
-#define gsl_ELIDE_CONTRACT_ENSURES ( 0 == ( gsl_CONFIG_CONTRACT_LEVEL_MASK & 0x10 ) )
-
-#if gsl_ELIDE_CONTRACT_EXPECTS
-# define Expects( x ) /* Expects elided */
-#elif gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V
-# define Expects( x ) ::gsl::fail_fast_assert( (x), "GSL: Precondition failure at " __FILE__ ": " gsl_STRINGIFY(__LINE__) );
-#else
-# define Expects( x ) ::gsl::fail_fast_assert( (x) )
-#endif
-
-#if gsl_ELIDE_CONTRACT_ENSURES
-# define Ensures( x ) /* Ensures elided */
-#elif gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V
-# define Ensures( x ) ::gsl::fail_fast_assert( (x), "GSL: Postcondition failure at " __FILE__ ": " gsl_STRINGIFY(__LINE__) );
-#else
-# define Ensures( x ) ::gsl::fail_fast_assert( (x) )
-#endif
-
-#define gsl_STRINGIFY( x ) gsl_STRINGIFY_( x )
-#define gsl_STRINGIFY_( x ) #x
-
-struct fail_fast : public std::logic_error
-{
- gsl_api explicit fail_fast( char const * const message )
- : std::logic_error( message ) {}
-};
-
-// workaround for gcc 5 throw/terminate constexpr bug:
-
-#if gsl_BETWEEN( gsl_COMPILER_GCC_VERSION, 430, 600 ) && gsl_HAVE_CONSTEXPR_14
-
-# if gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V
-
-gsl_api inline gsl_constexpr14 auto fail_fast_assert( bool cond, char const * const message ) -> void
-{
- !cond ? throw fail_fast( message ) : 0;
-}
-
-# else
-
-gsl_api inline gsl_constexpr14 auto fail_fast_assert( bool cond ) -> void
-{
- struct F { static gsl_constexpr14 void f(){}; };
-
- !cond ? std::terminate() : F::f();
-}
-
-# endif
-
-#else // workaround
-
-# if gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V
-
-gsl_api inline gsl_constexpr14 void fail_fast_assert( bool cond, char const * const message )
-{
- if ( !cond )
- throw fail_fast( message );
-}
-
-# else
-
-gsl_api inline gsl_constexpr14 void fail_fast_assert( bool cond )
-{
- if ( !cond )
- std::terminate();
-}
-
-# endif
-#endif // workaround
-
-//
-// GSL.util: utilities
-//
-
-#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION == 11
-
-template< class F >
-class final_act
-{
-public:
- gsl_api explicit final_act( F action ) gsl_noexcept
- : action_( std::move( action ) )
- , invoke_( true )
- {}
-
- gsl_api final_act( final_act && other ) gsl_noexcept
- : action_( std::move( other.action_ ) )
- , invoke_( other.invoke_ )
- {
- other.invoke_ = false;
- }
-
-#if gsl_HAVE_IS_DELETE
- gsl_api final_act( final_act const & ) = delete;
- gsl_api final_act & operator=( final_act const & ) = delete;
-#else
-private:
- gsl_api final_act( final_act const & );
- gsl_api final_act & operator=( final_act const & );
-public:
-#endif
-
- gsl_api virtual ~final_act() gsl_noexcept
- {
- if ( invoke_ )
- action_();
- }
-
-protected:
- gsl_api void dismiss() gsl_noexcept
- {
- invoke_ = false;
- }
-
-#if gsl_CPP17_OR_GREATER
- gsl_api int uncaught_exceptions() gsl_noexcept
- {
- return std::uncaught_exceptions();
- }
-#else
- gsl_api int uncaught_exceptions()
- {
- return std::uncaught_exception() ? 1 : 0;
- }
-#endif
-
-private:
- F action_;
- bool invoke_;
-};
-
-template< class F >
-gsl_api inline final_act<F> finally( F const & action ) gsl_noexcept
-{
- return final_act<F>( action );
-}
-
-template< class F >
-gsl_api inline final_act<F> finally( F && action ) gsl_noexcept
-{
- return final_act<F>( std::forward<F>( action ) );
-}
-
-#if gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD
-
-template< class F >
-class final_act_return : public final_act<F>
-{
-public:
- gsl_api explicit final_act_return( F && action ) gsl_noexcept
- : final_act<F>( std::move( action ) )
- {}
-
- gsl_api final_act_return( final_act_return && other ) gsl_noexcept
- : final_act<F>( std::move( other ) )
- {}
-
-#if gsl_HAVE_IS_DELETE
- gsl_api final_act_return( final_act_return const & ) = delete;
- gsl_api final_act_return & operator=( final_act_return const & ) = delete;
-#else
-private:
- gsl_api final_act_return( final_act_return const & );
- gsl_api final_act_return & operator=( final_act_return const & );
-public:
-#endif
-
- gsl_api ~final_act_return() override
- {
- if ( this->uncaught_exceptions() )
- this->dismiss();
- }
-};
-
-template< class F >
-gsl_api inline final_act_return<F> on_return( F const & action ) gsl_noexcept
-{
- return final_act_return<F>( action );
-}
-
-template< class F >
-gsl_api inline final_act_return<F> on_return( F && action ) gsl_noexcept
-{
- return final_act_return<F>( std::forward<F>( action ) );
-}
-
-template< class F >
-class final_act_error : public final_act<F>
-{
-public:
- gsl_api explicit final_act_error( F && action ) gsl_noexcept
- : final_act<F>( std::move( action ) )
- {}
-
- gsl_api final_act_error( final_act_error && other ) gsl_noexcept
- : final_act<F>( std::move( other ) )
- {}
-
-#if gsl_HAVE_IS_DELETE
- gsl_api final_act_error( final_act_error const & ) = delete;
- gsl_api final_act_error & operator=( final_act_error const & ) = delete;
-#else
-private:
- gsl_api final_act_error( final_act_error const & );
- gsl_api final_act_error & operator=( final_act_error const & );
-public:
-#endif
-
- gsl_api ~final_act_error() override
- {
- if ( ! this->uncaught_exceptions() )
- this->dismiss();
- }
-};
-
-template< class F >
-gsl_api inline final_act_error<F> on_error( F const & action ) gsl_noexcept
-{
- return final_act_error<F>( action );
-}
-
-template< class F >
-gsl_api inline final_act_error<F> on_error( F && action ) gsl_noexcept
-{
- return final_act_error<F>( std::forward<F>( action ) );
-}
-
-#endif // gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD
-
-#else // gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION == 11
-
-class final_act
-{
-public:
- typedef void (*Action)();
-
- gsl_api final_act( Action action )
- : action_( action )
- , invoke_( true )
- {}
-
- gsl_api final_act( final_act const & other )
- : action_( other.action_ )
- , invoke_( other.invoke_ )
- {
- other.invoke_ = false;
- }
-
- gsl_api virtual ~final_act()
- {
- if ( invoke_ )
- action_();
- }
-
-protected:
- gsl_api void dismiss()
- {
- invoke_ = false;
- }
-
- gsl_api int uncaught_exceptions()
- {
- return std::uncaught_exception() ? 1 : 0;
- }
-
-private:
- gsl_api final_act & operator=( final_act const & );
-
-private:
- Action action_;
- mutable bool invoke_;
-};
-
-template< class F >
-gsl_api inline final_act finally( F const & f )
-{
- return final_act(( f ));
-}
-
-#if gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD
-
-class final_act_return : public final_act
-{
-public:
- gsl_api explicit final_act_return( Action action )
- : final_act( action )
- {}
-
- gsl_api ~final_act_return()
- {
- if ( this->uncaught_exceptions() )
- this->dismiss();
- }
-
-private:
- gsl_api final_act_return & operator=( final_act_return const & );
-};
-
-template< class F >
-gsl_api inline final_act_return on_return( F const & action )
-{
- return final_act_return( action );
-}
-
-class final_act_error : public final_act
-{
-public:
- gsl_api explicit final_act_error( Action action )
- : final_act( action )
- {}
-
- gsl_api ~final_act_error()
- {
- if ( ! this->uncaught_exceptions() )
- this->dismiss();
- }
-
-private:
- gsl_api final_act_error & operator=( final_act_error const & );
-};
-
-template< class F >
-gsl_api inline final_act_error on_error( F const & action )
-{
- return final_act_error( action );
-}
-
-#endif // gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD
-
-#endif // gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION == 11
-
-#if gsl_CPP11_OR_GREATER
-
-template< class T, class U >
-gsl_api inline gsl_constexpr T narrow_cast( U && u ) gsl_noexcept
-{
- return static_cast<T>( std::forward<U>( u ) );
-}
-
-#else
-
-template< class T, class U >
-gsl_api inline T narrow_cast( U u ) gsl_noexcept
-{
- return static_cast<T>( u );
-}
-
-#endif // gsl_CPP11_OR_GREATER
-
-struct narrowing_error : public std::exception {};
-
-#if gsl_HAVE_TYPE_TRAITS
-
-namespace details
-{
- template< class T, class U >
- struct is_same_signedness : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
- {};
-}
-#endif
-
-template< class T, class U >
-gsl_api inline T narrow( U u )
-{
- T t = narrow_cast<T>( u );
-
- if ( static_cast<U>( t ) != u )
- {
-#if gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V
- throw narrowing_error();
-#else
- std::terminate();
-#endif
- }
-
-#if gsl_HAVE_TYPE_TRAITS
- if ( ! details::is_same_signedness<T, U>::value && ( ( t < T() ) != ( u < U() ) ) )
-#else
- // Don't assume T() works:
- if ( ( t < 0 ) != ( u < 0 ) )
-#endif
- {
-#if gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V
- throw narrowing_error();
-#else
- std::terminate();
-#endif
- }
- return t;
-}
-
-//
-// at() - Bounds-checked way of accessing static arrays, std::array, std::vector.
-//
-
-template< class T, size_t N >
-gsl_api inline gsl_constexpr14 T & at( T(&arr)[N], size_t index )
-{
- Expects( index < N );
- return arr[index];
-}
-
-#if gsl_HAVE_ARRAY
-
-template< class T, size_t N >
-gsl_api inline gsl_constexpr14 T & at( std::array<T, N> & arr, size_t index )
-{
- Expects( index < N );
- return arr[index];
-}
-#endif
-
-template< class Cont >
-gsl_api inline gsl_constexpr14 typename Cont::value_type & at( Cont & cont, size_t index )
-{
- Expects( index < cont.size() );
- return cont[index];
-}
-
-#if gsl_HAVE_INITIALIZER_LIST
-
-template< class T >
-gsl_api inline const gsl_constexpr14 T & at( std::initializer_list<T> cont, size_t index )
-{
- Expects( index < cont.size() );
- return *( cont.begin() + index );
-}
-#endif
-
-template< class T >
-class span;
-
-template< class T >
-gsl_api inline gsl_constexpr14 T & at( span<T> s, size_t index )
-{
- return s.at( index );
-}
-
-//
-// GSL.views: views
-//
-
-//
-// not_null<> - Wrap any indirection and enforce non-null.
-//
-template< class T >
-class not_null
-{
-public:
- gsl_api not_null( T t ) : ptr_ ( t ){ Expects( ptr_ != gsl_nullptr ); }
- gsl_api not_null & operator=( T const & t ) { ptr_ = t ; Expects( ptr_ != gsl_nullptr ); return *this; }
-
- gsl_api not_null( not_null const & other ) : ptr_ ( other.ptr_ ) {}
- gsl_api not_null & operator=( not_null const & other ) { ptr_ = other.ptr_; return *this; }
-
-#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
-
- template< class U, class Dummy =
- typename std::enable_if<std::is_convertible<U, T>::value, void>::type >
- gsl_api not_null( not_null<U> const & other ) : ptr_( other.get() ) {}
-
- template< class U, class Dummy =
- typename std::enable_if<std::is_convertible<U, T>::value, void>::type >
- gsl_api not_null & operator=( not_null<U> const & other )
- {
- ptr_ = other.get();
- return *this;
- }
-
-#else
-
- template< class U >
- gsl_api not_null( not_null<U> const & other ) : ptr_( other.get() ) {}
-
- template< class U >
- gsl_api not_null & operator=( not_null<U> const & other )
- {
- ptr_ = other.get();
- return *this;
- }
-#endif
-
-private:
- // Prevent compilation when initialized with a nullptr or literal 0:
-#if gsl_HAVE_NULLPTR
- gsl_api not_null( std::nullptr_t );
- gsl_api not_null & operator=( std::nullptr_t );
-#endif
- gsl_api not_null( int );
- gsl_api not_null & operator=( int );
-
-public:
- gsl_api T get() const
- {
-#if gsl_HAVE_NULLPTR && gsl_COMPILER_MSVC_VERSION > 0
- // The assume() should help the optimizer:
- __assume( ptr_ != nullptr );
-#endif
- return ptr_;
- }
-
- gsl_api operator T() const { return get(); }
- gsl_api T operator->() const { return get(); }
-
- gsl_api bool operator==(T const & rhs) const { return ptr_ == rhs; }
- gsl_api bool operator!=(T const & rhs) const { return !(*this == rhs); }
-
-private:
- T ptr_;
-
- gsl_api not_null & operator++();
- gsl_api not_null & operator--();
- gsl_api not_null operator++( int );
- gsl_api not_null operator--( int );
- gsl_api not_null & operator+ ( size_t );
- gsl_api not_null & operator+=( size_t );
- gsl_api not_null & operator- ( size_t );
- gsl_api not_null & operator-=( size_t );
-};
-
-//
-// Byte-specific type.
-//
-#if gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
- enum class byte : unsigned char {};
-#else
- struct byte { typedef unsigned char type; type v; };
-#endif
-
-#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
-# define gsl_ENABLE_IF_INTEGRAL_T(T) \
- , class = typename std::enable_if<std::is_integral<T>::value>::type
-#else
-# define gsl_ENABLE_IF_INTEGRAL_T(T)
-#endif
-
-template< class T >
-gsl_api inline gsl_constexpr byte to_byte( T v ) gsl_noexcept
-{
-#if gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
- static_assert( false, "Implement to_byte() using conversion from underlying type." );
-#elif gsl_HAVE_CONSTEXPR_11
- return { static_cast<typename byte::type>( v ) };
-#else
- byte b = { static_cast<typename byte::type>( v ) }; return b;
-#endif
-}
-
-template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) >
-gsl_api inline gsl_constexpr IntegerType to_integer( byte b ) gsl_noexcept
-{
-#if gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
- static_assert( false, "Implement to_integer() using conversion from underlying type." );
-#else
- return b.v;
-#endif
-}
-
-gsl_api inline gsl_constexpr unsigned char to_uchar( byte b ) gsl_noexcept
-{
- return to_integer<unsigned char>( b );
-}
-
-gsl_api inline gsl_constexpr unsigned char to_uchar( int i ) gsl_noexcept
-{
- return static_cast<unsigned char>( i );
-}
-
-#if ! gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
-
-gsl_api inline gsl_constexpr bool operator==( byte l, byte r ) gsl_noexcept
-{
- return l.v == r.v;
-}
-
-gsl_api inline gsl_constexpr bool operator!=( byte l, byte r ) gsl_noexcept
-{
- return !( l == r );
-}
-
-gsl_api inline gsl_constexpr bool operator< ( byte l, byte r ) gsl_noexcept
-{
- return l.v < r.v;
-}
-
-gsl_api inline gsl_constexpr bool operator<=( byte l, byte r ) gsl_noexcept
-{
- return !( r < l );
-}
-
-gsl_api inline gsl_constexpr bool operator> ( byte l, byte r ) gsl_noexcept
-{
- return ( r < l );
-}
-
-gsl_api inline gsl_constexpr bool operator>=( byte l, byte r ) gsl_noexcept
-{
- return !( l < r );
-}
-#endif
-
-template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) >
-gsl_api inline gsl_constexpr14 byte & operator<<=( byte & b, IntegerType shift ) gsl_noexcept
-{
-#if gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
- return b = to_byte( to_uchar( b ) << shift );
-#else
- b.v = to_uchar( b.v << shift ); return b;
-#endif
-}
-
-template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) >
-gsl_api inline gsl_constexpr byte operator<<( byte b, IntegerType shift ) gsl_noexcept
-{
- return to_byte( to_uchar( b ) << shift );
-}
-
-template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) >
-gsl_api inline gsl_constexpr14 byte & operator>>=( byte & b, IntegerType shift ) gsl_noexcept
-{
-#if gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
- return b = to_byte( to_uchar( b ) >> shift );
-#else
- b.v = to_uchar( b.v >> shift ); return b;
-#endif
-}
-
-template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) >
-gsl_api inline gsl_constexpr byte operator>>( byte b, IntegerType shift ) gsl_noexcept
-{
- return to_byte( to_uchar( b ) >> shift );
-}
-
-gsl_api inline gsl_constexpr14 byte & operator|=( byte & l, byte r ) gsl_noexcept
-{
-#if gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
- return l = to_byte( to_uchar( l ) | to_uchar( r ) );
-#else
- l.v = to_uchar( l ) | to_uchar( r ); return l;
-#endif
-}
-
-gsl_api inline gsl_constexpr byte operator|( byte l, byte r ) gsl_noexcept
-{
- return to_byte( to_uchar( l ) | to_uchar( r ) );
-}
-
-gsl_api inline gsl_constexpr14 byte & operator&=( byte & l, byte r ) gsl_noexcept
-{
-#if gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
- return l = to_byte( to_uchar( l ) & to_uchar( r ) );
-#else
- l.v = to_uchar( l ) & to_uchar( r ); return l;
-#endif
-}
-
-gsl_api inline gsl_constexpr byte operator&( byte l, byte r ) gsl_noexcept
-{
- return to_byte( to_uchar( l ) & to_uchar( r ) );
-}
-
-gsl_api inline gsl_constexpr14 byte & operator^=( byte & l, byte r ) gsl_noexcept
-{
-#if gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
- return l = to_byte( to_uchar( l ) ^ to_uchar (r ) );
-#else
- l.v = to_uchar( l ) ^ to_uchar (r ); return l;
-#endif
-}
-
-gsl_api inline gsl_constexpr byte operator^( byte l, byte r ) gsl_noexcept
-{
- return to_byte( to_uchar( l ) ^ to_uchar( r ) );
-}
-
-gsl_api inline gsl_constexpr byte operator~( byte b ) gsl_noexcept
-{
- return to_byte( ~to_uchar( b ) );
-}
-
-// tag to select span constructor taking a container
-struct with_container_t{ gsl_constexpr14 with_container_t(){} };
-const with_container_t with_container;
-
-//
-// span<> - A 1D view of contiguous T's, replace (*,len).
-//
-template< class T >
-class span
-{
- template< class U > friend class span;
-
-public:
- typedef gsl_CONFIG_SPAN_INDEX_TYPE index_type; // p0122r3 uses std::ptrdiff_t
-
- typedef T element_type;
- typedef T & reference;
- typedef T * pointer;
- typedef T const * const_pointer;
- typedef T const & const_reference;
-
- typedef pointer iterator;
- typedef const_pointer const_iterator;
+#pragma message ("gsl/gsl-lite.h is deprecated since version 0.27.0, use gsl/gsl-lite.hpp instead.")
- typedef std::reverse_iterator< iterator > reverse_iterator;
- typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
-
- typedef typename std::iterator_traits< iterator >::difference_type difference_type;
-
- gsl_api gsl_constexpr14 span() gsl_noexcept
- : first_( gsl_nullptr )
- , last_ ( gsl_nullptr )
- {
- Expects( size() == 0 );
- }
-
-#if gsl_HAVE_NULLPTR
- gsl_api gsl_constexpr14 span( std::nullptr_t, index_type size_in )
- : first_( nullptr )
- , last_ ( nullptr )
- {
- Expects( size_in == 0 );
- }
-#endif
-
-#if gsl_HAVE_IS_DELETE
- gsl_api gsl_constexpr14 span( reference data_in )
- : span( &data_in, 1 )
- {}
-
- gsl_api gsl_constexpr14 span( element_type && ) = delete;
-#endif
-
- gsl_api gsl_constexpr14 span( pointer first_in, pointer last_in )
- : first_( first_in )
- , last_ ( last_in )
- {
- Expects( first_in <= last_in );
- }
-
- gsl_api gsl_constexpr14 span( pointer data_in, index_type size_in )
- : first_( data_in )
- , last_ ( data_in + size_in )
- {
- Expects( size_in == 0 || ( size_in > 0 && data_in != gsl_nullptr ) );
- }
-
- template< class U >
- gsl_api gsl_constexpr14 span( U * & data_in, index_type size_in )
- : first_( data_in )
- , last_ ( data_in + size_in )
- {
- Expects( size_in == 0 || ( size_in > 0 && data_in != gsl_nullptr ) );
- }
-
- template< class U >
- gsl_api gsl_constexpr14 span( U * const & data_in, index_type size_in )
- : first_( data_in )
- , last_ ( data_in + size_in )
- {
- Expects( size_in == 0 || ( size_in > 0 && data_in != gsl_nullptr ) );
- }
-
- template< class U, size_t N >
- gsl_api gsl_constexpr14 span( U (&arr)[N] )
- : first_( &arr[0] )
- , last_ ( &arr[0] + N )
- {}
-
-#if gsl_HAVE_ARRAY
- template< class U, size_t N >
- gsl_api gsl_constexpr14 span( std::array< U, N > & arr )
- : first_( arr.data() )
- , last_ ( arr.data() + N )
- {}
-
- template< class U, size_t N >
- gsl_api gsl_constexpr14 span( std::array< U, N > const & arr )
- : first_( arr.data() )
- , last_ ( arr.data() + N )
- {}
-#endif
-
-#if gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR
- // SFINAE enable only if Cont has a data() member function
- template< class Cont, class = decltype(std::declval<Cont>().data()) >
- gsl_api gsl_constexpr14 span( Cont & cont )
- : first_( cont.data() )
- , last_ ( cont.data() + cont.size() )
- {}
-#elif gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR
- template< class Cont >
- gsl_api gsl_constexpr14 span( Cont & cont )
- : first_( cont.size() == 0 ? gsl_nullptr : &cont[0] )
- , last_ ( cont.size() == 0 ? gsl_nullptr : &cont[0] + cont.size() )
- {}
-#endif
-
- template< class Cont >
- gsl_api gsl_constexpr14 span( with_container_t, Cont & cont )
- : first_( cont.size() == 0 ? gsl_nullptr : &cont[0] )
- , last_ ( cont.size() == 0 ? gsl_nullptr : &cont[0] + cont.size() )
- {}
-
-#if gsl_HAVE_SHARED_PTR
- gsl_api gsl_constexpr14 span( shared_ptr<element_type> const & ptr )
- : first_( ptr.get() )
- , last_ ( ptr.get() ? ptr.get() + 1 : 0 )
- {}
-#endif
-
-#if gsl_HAVE_UNIQUE_PTR
-# if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
- template< class ArrayElementType = typename std::add_pointer<element_type>::type >
-# else
- template< class ArrayElementType >
-# endif
- gsl_api gsl_constexpr14 span( unique_ptr<ArrayElementType> const & ptr, index_type count )
- : first_( ptr.get() )
- , last_ ( ptr.get() + count )
- {}
-
- gsl_api gsl_constexpr14 span( unique_ptr<element_type> const & ptr )
- : first_( ptr.get() )
- , last_ ( ptr.get() ? ptr.get() + 1 : 0 )
- {}
-#endif
-
-#if gsl_HAVE_IS_DEFAULT && ! gsl_BETWEEN( gsl_COMPILER_GCC_VERSION, 430, 600)
- gsl_api gsl_constexpr14 span( span && ) = default;
- gsl_api gsl_constexpr14 span( span const & ) = default;
-#else
- gsl_api gsl_constexpr14 span( span const & other )
- : first_( other.begin() )
- , last_ ( other.end() )
- {}
-#endif
-
- template< class U >
- gsl_api gsl_constexpr14 span( span<U> const & other )
- : first_( other.begin() )
- , last_ ( other.end() )
- {}
-
-#if gsl_HAVE_IS_DEFAULT
- gsl_api span & operator=( span && ) = default;
- gsl_api span & operator=( span const & ) = default;
-#else
- gsl_api span & operator=( span other )
- {
- other.swap( *this );
- return *this;
- }
-#endif
-
-#if 0
- // Converting from other span ?
- template< class U > operator=();
-#endif
-
- gsl_api gsl_constexpr14 span first( index_type count ) const gsl_noexcept
- {
- Expects( count <= this->size() );
- return span( this->data(), count );
- }
-
- gsl_api gsl_constexpr14 span last( index_type count ) const gsl_noexcept
- {
- Expects( count <= this->size() );
- return span( this->data() + this->size() - count, count );
- }
-
- gsl_api gsl_constexpr14 span subspan( index_type offset ) const gsl_noexcept
- {
- Expects( offset <= this->size() );
- return span( this->data() + offset, this->length() - offset );
- }
-
- gsl_api gsl_constexpr14 span subspan( index_type offset, index_type count ) const gsl_noexcept
- {
- Expects( offset <= this->size() && count <= this->size() - offset );
- return span( this->data() + offset, count );
- }
-
- gsl_api gsl_constexpr14 iterator begin() const gsl_noexcept
- {
- return iterator( first_ );
- }
-
- gsl_api gsl_constexpr14 iterator end() const gsl_noexcept
- {
- return iterator( last_ );
- }
-
- gsl_api gsl_constexpr14 const_iterator cbegin() const gsl_noexcept
- {
- return const_iterator( begin() );
- }
-
- gsl_api gsl_constexpr14 const_iterator cend() const gsl_noexcept
- {
- return const_iterator( end() );
- }
-
- gsl_api gsl_constexpr14 reverse_iterator rbegin() const gsl_noexcept
- {
- return reverse_iterator( end() );
- }
-
- gsl_api gsl_constexpr14 reverse_iterator rend() const gsl_noexcept
- {
- return reverse_iterator( begin() );
- }
-
- gsl_api gsl_constexpr14 const_reverse_iterator crbegin() const gsl_noexcept
- {
- return const_reverse_iterator( cend() );
- }
-
- gsl_api gsl_constexpr14 const_reverse_iterator crend() const gsl_noexcept
- {
- return const_reverse_iterator( cbegin() );
- }
-
- gsl_api gsl_constexpr14 reference operator[]( index_type index ) const
- {
- return at( index );
- }
-
- gsl_api gsl_constexpr14 reference operator()( index_type index ) const
- {
- return at( index );
- }
-
- gsl_api gsl_constexpr14 reference at( index_type index ) const
- {
- Expects( index < size() );
- return first_[ index ];
- }
-
- gsl_api gsl_constexpr14 pointer data() const gsl_noexcept
- {
- return first_;
- }
-
- gsl_api gsl_constexpr14 bool empty() const gsl_noexcept
- {
- return size() == 0;
- }
-
- gsl_api gsl_constexpr14 index_type size() const gsl_noexcept
- {
- return narrow_cast<index_type>( last_ - first_ );
- }
-
- gsl_api gsl_constexpr14 index_type length() const gsl_noexcept
- {
- return size();
- }
-
- gsl_api gsl_constexpr14 index_type size_bytes() const gsl_noexcept
- {
- return size() * narrow_cast<index_type>( sizeof( element_type ) );
- }
-
- gsl_api gsl_constexpr14 index_type length_bytes() const gsl_noexcept
- {
- return size_bytes();
- }
-
- gsl_api void swap( span & other ) gsl_noexcept
- {
- using std::swap;
- swap( first_, other.first_ );
- swap( last_ , other.last_ );
- }
-
- // member as_bytes(), as_writeable_bytes deprecated since 0.17.0
-
- gsl_api span< const byte > as_bytes() const gsl_noexcept
- {
- return span< const byte >( reinterpret_cast<const byte *>( data() ), size_bytes() );
- }
-
- gsl_api span< byte > as_writeable_bytes() const gsl_noexcept
- {
- return span< byte >( reinterpret_cast<byte *>( data() ), size_bytes() );
- }
-
- template< class U >
- gsl_api span< U > as_span() const gsl_noexcept
- {
- Expects( ( this->size_bytes() % sizeof(U) ) == 0 );
- return span< U >( reinterpret_cast<U *>( this->data() ), this->size_bytes() / sizeof( U ) );
- }
-
-private:
- pointer first_;
- pointer last_;
-};
-
-// span comparison functions
-
-#if gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator==( span<T> const & l, span<U> const & r )
-{
- return l.size() == r.size()
- && (l.begin() == r.begin() || std::equal( l.begin(), l.end(), r.begin() ) );
-}
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator< ( span<T> const & l, span<U> const & r )
-{
- return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
-}
-
-#else
-
-template< class T >
-gsl_api inline gsl_constexpr14 bool operator==( span<T> const & l, span<T> const & r )
-{
- return l.size() == r.size()
- && (l.begin() == r.begin() || std::equal( l.begin(), l.end(), r.begin() ) );
-}
-
-template< class T >
-gsl_api inline gsl_constexpr14 bool operator< ( span<T> const & l, span<T> const & r )
-{
- return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
-}
-#endif
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator!=( span<T> const & l, span<U> const & r )
-{
- return !( l == r );
-}
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator<=( span<T> const & l, span<U> const & r )
-{
- return !( r < l );
-}
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator> ( span<T> const & l, span<U> const & r )
-{
- return ( r < l );
-}
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator>=( span<T> const & l, span<U> const & r )
-{
- return !( l < r );
-}
-
-// span algorithms
-
-namespace detail {
-
-template< class II, class N, class OI >
-gsl_api inline OI copy_n( II first, N count, OI result )
-{
- if ( count > 0 )
- {
- *result++ = *first;
- for ( N i = 1; i < count; ++i )
- {
- *result++ = *++first;
- }
- }
- return result;
-}
-}
-
-template< class T, class U >
-gsl_api inline void copy( span<T> src, span<U> dest )
-{
-#if gsl_CPP14_OR_GREATER // gsl_HAVE_TYPE_TRAITS (circumvent Travis clang 3.4)
- static_assert( std::is_assignable<U &, T const &>::value, "Cannot assign elements of source span to elements of destination span" );
-#endif
- Expects( dest.size() >= src.size() );
- detail::copy_n( src.data(), src.size(), dest.data() );
-}
-
-// span creator functions (see ctors)
-
-template< class T >
-gsl_api inline span< const byte > as_bytes( span<T> spn ) gsl_noexcept
-{
- return span< const byte >( reinterpret_cast<const byte *>( spn.data() ), spn.size_bytes() );
-}
-
-template< class T>
-gsl_api inline span< byte > as_writeable_bytes( span<T> spn ) gsl_noexcept
-{
- return span< byte >( reinterpret_cast<byte *>( spn.data() ), spn.size_bytes() );
-}
-
-template< class T >
-gsl_api inline gsl_constexpr14 span<T> make_span( T * first, T * last )
-{
- return span<T>( first, last );
-}
-
-template< class T >
-gsl_api inline gsl_constexpr14 span<T> make_span( T * ptr, typename span<T>::index_type count )
-{
- return span<T>( ptr, count );
-}
-
-template< class T, size_t N >
-gsl_api inline gsl_constexpr14 span<T> make_span( T (&arr)[N] )
-{
- return span<T>( &arr[0], N );
-}
-
-#if gsl_HAVE_ARRAY
-
-template< class T, size_t N >
-gsl_api inline gsl_constexpr14 span<T> make_span( std::array<T,N> & arr )
-{
- return span<T>( arr );
-}
-
-template< class T, size_t N >
-gsl_api inline gsl_constexpr14 span<const T> make_span( std::array<T,N> const & arr )
-{
- return span<const T>( arr );
-}
-#endif
-
-#if gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR && gsl_HAVE_AUTO
-
-template< class Cont >
-gsl_api inline gsl_constexpr14 auto make_span( Cont & cont ) -> span< typename Cont::value_type >
-{
- return span< typename Cont::value_type >( cont );
-}
-
-template< class Cont >
-gsl_api inline gsl_constexpr14 auto make_span( Cont const & cont ) -> span< const typename Cont::value_type >
-{
- return span< const typename Cont::value_type >( cont );
-}
-
-#else
-
-template< class T >
-gsl_api inline span<T> make_span( std::vector<T> & cont )
-{
- return span<T>( with_container, cont );
-}
-
-template< class T >
-gsl_api inline span<const T> make_span( std::vector<T> const & cont )
-{
- return span<const T>( with_container, cont );
-}
-#endif
-
-template< class Ptr >
-gsl_api inline span<typename Ptr::element_type> make_span( Ptr & ptr )
-{
- return span<typename Ptr::element_type>( ptr );
-}
-
-template< class Ptr >
-span<typename Ptr::element_type> make_span( Ptr & ptr, typename span<typename Ptr::element_type>::index_type count )
-{
- return span<typename Ptr::element_type>( ptr, count);
-}
-
-//
-// basic_string_span:
-//
-
-template< class T >
-class basic_string_span;
-
-namespace detail {
-
-template< class T >
-struct is_basic_string_span_oracle : false_type {};
-
-template< class T >
-struct is_basic_string_span_oracle< basic_string_span<T> > : true_type {};
-
-template< class T >
-struct is_basic_string_span : is_basic_string_span_oracle< typename remove_cv<T>::type > {};
-
-template< class T >
-gsl_api inline gsl_constexpr14 std::size_t string_length( T * ptr, std::size_t max )
-{
- if ( ptr == gsl_nullptr || max <= 0 )
- return 0;
-
- std::size_t len = 0;
- while ( len < max && ptr[len] )
- ++len;
-
- return len;
-}
-
-} // namespace detail
-
-//
-// basic_string_span<> - A view of contiguous characters, replace (*,len).
-//
-template< class T >
-class basic_string_span
-{
-public:
- typedef T element_type;
- typedef span<T> span_type;
-
- typedef typename span_type::index_type index_type;
- typedef typename span_type::difference_type difference_type;
-
- typedef typename span_type::pointer pointer ;
- typedef typename span_type::reference reference ;
-
- typedef typename span_type::iterator iterator ;
- typedef typename span_type::const_iterator const_iterator ;
- typedef typename span_type::reverse_iterator reverse_iterator;
- typedef typename span_type::const_reverse_iterator const_reverse_iterator;
-
- // construction:
-
-#if gsl_HAVE_IS_DEFAULT
- gsl_api gsl_constexpr basic_string_span() gsl_noexcept = default;
-#else
- gsl_api gsl_constexpr basic_string_span() gsl_noexcept {}
-#endif
-
-#if gsl_HAVE_NULLPTR
- gsl_api gsl_constexpr basic_string_span( std::nullptr_t ptr ) gsl_noexcept
- : span_( ptr, 0 )
- {}
-#endif
-
- gsl_api gsl_constexpr basic_string_span( pointer ptr )
- : span_( remove_z( ptr, std::numeric_limits<index_type>::max() ) )
- {}
-
- gsl_api gsl_constexpr basic_string_span( pointer ptr, index_type count )
- : span_( ptr, count )
- {}
-
- gsl_api gsl_constexpr basic_string_span( pointer first, pointer last )
- : span_( first, last )
- {}
-
- template< std::size_t N >
- gsl_api gsl_constexpr basic_string_span( element_type (&arr)[N] )
- : span_( remove_z( &arr[0], N ) )
- {}
-
-#if gsl_HAVE_ARRAY
-
- template< std::size_t N >
- gsl_api gsl_constexpr basic_string_span( std::array< typename detail::remove_const<element_type>::type, N> & arr )
- : span_( remove_z( arr ) )
- {}
-
- template< std::size_t N >
- gsl_api gsl_constexpr basic_string_span( std::array< typename detail::remove_const<element_type>::type, N> const & arr )
- : span_( remove_z( arr ) )
- {}
-
-#endif
-
-#if gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR
-
- // Exclude: array, [basic_string,] basic_string_span
-
- template<
- class Cont,
- class = typename std::enable_if<
- ! detail::is_std_array< Cont >::value
- && ! detail::is_basic_string_span< Cont >::value
- && std::is_convertible< typename Cont::pointer, pointer >::value
- && std::is_convertible< typename Cont::pointer, decltype(std::declval<Cont>().data()) >::value
- >::type
- >
- gsl_api gsl_constexpr basic_string_span( Cont & cont )
- : span_( ( cont ) )
- {}
-
- // Exclude: array, [basic_string,] basic_string_span
-
- template<
- class Cont,
- class = typename std::enable_if<
- ! detail::is_std_array< Cont >::value
- && ! detail::is_basic_string_span< Cont >::value
- && std::is_convertible< typename Cont::pointer, pointer >::value
- && std::is_convertible< typename Cont::pointer, decltype(std::declval<Cont>().data()) >::value
- >::type
- >
- gsl_api gsl_constexpr basic_string_span( Cont const & cont )
- : span_( ( cont ) )
- {}
-
-#elif gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR
-
- template< class Cont >
- gsl_api gsl_constexpr basic_string_span( Cont & cont )
- : span_( cont )
- {}
-
- template< class Cont >
- gsl_api gsl_constexpr basic_string_span( Cont const & cont )
- : span_( cont )
- {}
-
-#else
-
- template< class U >
- gsl_api gsl_constexpr basic_string_span( span<U> const & rhs )
- : span_( rhs )
- {}
-
-#endif
-
- template< class Cont >
- gsl_api gsl_constexpr14 basic_string_span( with_container_t, Cont & cont )
- : span_( with_container, cont )
- {}
-
-#if gsl_HAVE_IS_DEFAULT
-# if gsl_BETWEEN( gsl_COMPILER_GCC_VERSION, 440, 600 )
- gsl_api gsl_constexpr basic_string_span( basic_string_span const & rhs ) = default;
-
- gsl_api gsl_constexpr basic_string_span( basic_string_span && rhs ) = default;
-# else
- gsl_api gsl_constexpr basic_string_span( basic_string_span const & rhs ) gsl_noexcept = default;
-
- gsl_api gsl_constexpr basic_string_span( basic_string_span && rhs ) gsl_noexcept = default;
-# endif
-#endif
-
- template< class U
-#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
- , class = typename std::enable_if< std::is_convertible<typename basic_string_span<U>::pointer, pointer>::value >::type
-#endif
- >
- gsl_api gsl_constexpr basic_string_span( basic_string_span<U> const & rhs )
- : span_( reinterpret_cast<pointer>( rhs.data() ), rhs.length() )
- {}
-
-#if gsl_CPP11_OR_GREATER
- template< class U
- , class = typename std::enable_if< std::is_convertible<typename basic_string_span<U>::pointer, pointer>::value >::type
- >
- gsl_api gsl_constexpr basic_string_span( basic_string_span<U> && rhs )
- : span_( reinterpret_cast<pointer>( rhs.data() ), rhs.length() )
- {}
-#endif
-
- template< class CharTraits, class Allocator >
- gsl_api gsl_constexpr basic_string_span(
- std::basic_string< typename detail::remove_const<element_type>::type, CharTraits, Allocator > & str )
- : span_( &str[0], str.length() )
- {}
-
- template< class CharTraits, class Allocator >
- gsl_api gsl_constexpr basic_string_span(
- std::basic_string< typename detail::remove_const<element_type>::type, CharTraits, Allocator > const & str )
- : span_( &str[0], str.length() )
- {}
-
- // destruction, assignment:
-
-#if gsl_HAVE_IS_DEFAULT
- gsl_api ~basic_string_span() gsl_noexcept = default;
-
- gsl_api basic_string_span & operator=( basic_string_span const & rhs ) gsl_noexcept = default;
-
- gsl_api basic_string_span & operator=( basic_string_span && rhs ) gsl_noexcept = default;
-#endif
-
- // sub span:
-
- gsl_api gsl_constexpr basic_string_span first( index_type count ) const
- {
- return span_.first( count );
- }
-
- gsl_api gsl_constexpr basic_string_span last( index_type count ) const
- {
- return span_.last( count );
- }
-
- gsl_api gsl_constexpr basic_string_span subspan( index_type offset ) const
- {
- return span_.subspan( offset );
- }
-
- gsl_api gsl_constexpr basic_string_span subspan( index_type offset, index_type count ) const
- {
- return span_.subspan( offset, count );
- }
-
- // observers:
-
- gsl_api gsl_constexpr index_type length() const gsl_noexcept
- {
- return span_.size();
- }
-
- gsl_api gsl_constexpr index_type size() const gsl_noexcept
- {
- return span_.size();
- }
-
- gsl_api gsl_constexpr index_type length_bytes() const gsl_noexcept
- {
- return span_.size_bytes();
- }
-
- gsl_api gsl_constexpr index_type size_bytes() const gsl_noexcept
- {
- return span_.size_bytes();
- }
-
- gsl_api gsl_constexpr bool empty() const gsl_noexcept
- {
- return size() == 0;
- }
-
- gsl_api gsl_constexpr reference operator[]( index_type idx ) const
- {
- return span_[idx];
- }
-
- gsl_api gsl_constexpr reference operator()( index_type idx ) const
- {
- return span_[idx];
- }
-
- gsl_api gsl_constexpr pointer data() const gsl_noexcept
- {
- return span_.data();
- }
-
- gsl_api iterator begin() const gsl_noexcept
- {
- return span_.begin();
- }
-
- gsl_api iterator end() const gsl_noexcept
- {
- return span_.end();
- }
-
- gsl_api reverse_iterator rbegin() const gsl_noexcept
- {
- return span_.rbegin();
- }
-
- gsl_api reverse_iterator rend() const gsl_noexcept
- {
- return span_.rend();
- }
-
- // const version not in p0123r2:
-
- gsl_api const_iterator cbegin() const gsl_noexcept
- {
- return span_.cbegin();
- }
-
- gsl_api const_iterator cend() const gsl_noexcept
- {
- return span_.cend();
- }
-
- gsl_api const_reverse_iterator crbegin() const gsl_noexcept
- {
- return span_.crbegin();
- }
-
- gsl_api const_reverse_iterator crend() const gsl_noexcept
- {
- return span_.crend();
- }
-
-private:
- gsl_api static gsl_constexpr14 span_type remove_z( pointer const & sz, std::size_t max )
- {
- return span_type( sz, detail::string_length( sz, max ) );
- }
-
-#if gsl_HAVE_ARRAY
- template< size_t N >
- gsl_api static gsl_constexpr14 span_type remove_z( std::array<typename detail::remove_const<element_type>::type, N> & arr )
- {
- return remove_z( &arr[0], narrow_cast< std::size_t >( N ) );
- }
-
- template< size_t N >
- gsl_api static gsl_constexpr14 span_type remove_z( std::array<typename detail::remove_const<element_type>::type, N> const & arr )
- {
- return remove_z( &arr[0], narrow_cast< std::size_t >( N ) );
- }
-#endif
-
-private:
- span_type span_;
-};
-
-// basic_string_span comparison functions:
-
-#if gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator==( basic_string_span<T> const & l, U const & u ) gsl_noexcept
-{
- basic_string_span< typename detail::add_const<T>::type > r( u );
-
- return l.size() == r.size()
- && std::equal( l.begin(), l.end(), r.begin() );
-}
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator<( basic_string_span<T> const & l, U const & u ) gsl_noexcept
-{
- basic_string_span< typename detail::add_const<T>::type > r( u );
-
- return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
-}
-
-#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
-
-template< class T, class U,
- class = typename std::enable_if<!detail::is_basic_string_span<U>::value >::type >
-gsl_api inline gsl_constexpr14 bool operator==( U const & u, basic_string_span<T> const & r ) gsl_noexcept
-{
- basic_string_span< typename detail::add_const<T>::type > l( u );
-
- return l.size() == r.size()
- && std::equal( l.begin(), l.end(), r.begin() );
-}
-
-template< class T, class U,
- class = typename std::enable_if<!detail::is_basic_string_span<U>::value >::type >
-gsl_api inline gsl_constexpr14 bool operator<( U const & u, basic_string_span<T> const & r ) gsl_noexcept
-{
- basic_string_span< typename detail::add_const<T>::type > l( u );
-
- return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
-}
-#endif
-
-#else //gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
-
-template< class T >
-gsl_api inline gsl_constexpr14 bool operator==( basic_string_span<T> const & l, basic_string_span<T> const & r ) gsl_noexcept
-{
- return l.size() == r.size()
- && std::equal( l.begin(), l.end(), r.begin() );
-}
-
-template< class T >
-gsl_api inline gsl_constexpr14 bool operator<( basic_string_span<T> const & l, basic_string_span<T> const & r ) gsl_noexcept
-{
- return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
-}
-
-#endif // gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator!=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
-{
- return !( l == r );
-}
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator<=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
-{
-#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG || ! gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
- return !( r < l );
-#else
- basic_string_span< typename detail::add_const<T>::type > rr( r );
- return !( rr < l );
-#endif
-}
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator>( basic_string_span<T> const & l, U const & r ) gsl_noexcept
-{
-#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG || ! gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
- return ( r < l );
-#else
- basic_string_span< typename detail::add_const<T>::type > rr( r );
- return ( rr < l );
-#endif
-}
-
-template< class T, class U >
-gsl_api inline gsl_constexpr14 bool operator>=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
-{
- return !( l < r );
-}
-
-#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
-
-template< class T, class U,
- class = typename std::enable_if<!detail::is_basic_string_span<U>::value >::type >
-gsl_api inline gsl_constexpr14 bool operator!=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
-{
- return !( l == r );
-}
-
-template< class T, class U,
- class = typename std::enable_if<!detail::is_basic_string_span<U>::value >::type >
-gsl_api inline gsl_constexpr14 bool operator<=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
-{
- return !( r < l );
-}
-
-template< class T, class U,
- class = typename std::enable_if<!detail::is_basic_string_span<U>::value >::type >
-gsl_api inline gsl_constexpr14 bool operator>( U const & l, basic_string_span<T> const & r ) gsl_noexcept
-{
- return ( r < l );
-}
-
-template< class T, class U,
- class = typename std::enable_if<!detail::is_basic_string_span<U>::value >::type >
-gsl_api inline gsl_constexpr14 bool operator>=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
-{
- return !( l < r );
-}
-
-#endif // gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
-
-// convert basic_string_span to byte span:
-
-template< class T >
-gsl_api inline span< const byte > as_bytes( basic_string_span<T> spn ) gsl_noexcept
-{
- return span< const byte >( reinterpret_cast<const byte *>( spn.data() ), spn.size_bytes() );
-}
-
-//
-// String types:
-//
-
-typedef char * zstring;
-typedef wchar_t * zwstring;
-typedef const char * czstring;
-typedef const wchar_t * cwzstring;
-
-typedef basic_string_span< char > string_span;
-typedef basic_string_span< wchar_t > wstring_span;
-typedef basic_string_span< char const > cstring_span;
-typedef basic_string_span< wchar_t const > cwstring_span;
-
-// to_string() allow (explicit) conversions from string_span to string
-
-#if 0
-
-template< class T >
-gsl_api inline std::basic_string< typename std::remove_const<T>::type > to_string( basic_string_span<T> spn )
-{
- std::string( spn.data(), spn.length() );
-}
-
-#else
-
-gsl_api inline std::string to_string( string_span const & spn )
-{
- return std::string( spn.data(), spn.length() );
-}
-
-gsl_api inline std::string to_string( cstring_span const & spn )
-{
- return std::string( spn.data(), spn.length() );
-}
-
-gsl_api inline std::wstring to_string( wstring_span const & spn )
-{
- return std::wstring( spn.data(), spn.length() );
-}
-
-gsl_api inline std::wstring to_string( cwstring_span const & spn )
-{
- return std::wstring( spn.data(), spn.length() );
-}
-
-#endif // to_string()
-
-//
-// Stream output for string_span types
-//
-
-namespace detail {
-
-template< class Stream >
-gsl_api void write_padding( Stream & os, std::streamsize n )
-{
- for ( std::streamsize i = 0; i < n; ++i )
- os.rdbuf()->sputc( os.fill() );
-}
-
-template< class Stream, class Span >
-gsl_api Stream & write_to_stream( Stream & os, Span const & spn )
-{
- typename Stream::sentry sentry( os );
-
- if ( !os )
- return os;
-
- std::streamsize length = narrow<std::streamsize>( spn.length() );
-
- // Whether, and how, to pad
- bool pad = ( length < os.width() );
- bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::left;
-
- if ( left_pad )
- write_padding( os, os.width() - length );
-
- // Write span characters
- os.rdbuf()->sputn( spn.begin(), length );
-
- if ( pad && !left_pad )
- write_padding( os, os.width() - length );
-
- // Reset output stream width
- os.width(0);
-
- return os;
-}
-
-} // namespace detail
-
-template< typename Traits >
-gsl_api std::basic_ostream< char, Traits > & operator<<( std::basic_ostream< char, Traits > & os, string_span const & spn )
-{
- return detail::write_to_stream( os, spn );
-}
-
-template< typename Traits >
-gsl_api std::basic_ostream< char, Traits > & operator<<( std::basic_ostream< char, Traits > & os, cstring_span const & spn )
-{
- return detail::write_to_stream( os, spn );
-}
-
-template< typename Traits >
-gsl_api std::basic_ostream< wchar_t, Traits > & operator<<( std::basic_ostream< wchar_t, Traits > & os, wstring_span const & spn )
-{
- return detail::write_to_stream( os, spn );
-}
-
-template< typename Traits >
-gsl_api std::basic_ostream< wchar_t, Traits > & operator<<( std::basic_ostream< wchar_t, Traits > & os, cwstring_span const & spn )
-{
- return detail::write_to_stream( os, spn );
-}
-
-//
-// ensure_sentinel()
-//
-// Provides a way to obtain a 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.
-//
-namespace detail {
-
-template< class T, class SizeType, const T Sentinel >
-gsl_api static span<T> ensure_sentinel( T * seq, SizeType max = std::numeric_limits<SizeType>::max() )
-{
- typedef T * pointer;
-
- pointer cur = seq;
-
- while ( static_cast<SizeType>( cur - seq ) < max && *cur != Sentinel )
- ++cur;
-
- Expects( *cur == Sentinel );
-
- return span<T>( seq, narrow_cast< typename span<T>::index_type >( cur - seq ) );
-}
-} // namespace detail
-
-//
-// ensure_z - creates a string_span for a czstring or cwzstring.
-// Will fail fast if a null-terminator cannot be found before
-// the limit of size_type.
-//
-
-template< class T >
-gsl_api inline span<T> ensure_z( T * const & sz, size_t max = std::numeric_limits<size_t>::max() )
-{
- return detail::ensure_sentinel<T, size_t, 0>( sz, max );
-}
-
-template< class T, size_t N >
-gsl_api inline span<T> ensure_z( T (&sz)[N] )
-{
- return ensure_z( &sz[0], N );
-}
-
-# if gsl_HAVE_TYPE_TRAITS
-
-template< class Cont >
-gsl_api inline span< typename std::remove_pointer<typename Cont::pointer>::type >
-ensure_z( Cont & cont )
-{
- return ensure_z( cont.data(), cont.length() );
-}
-# endif
-
-} // namespace gsl
-
-#if gsl_CPP11_OR_GREATER
-
-namespace std {
-
-template<>
-struct hash< gsl::byte >
-{
-public:
- std::size_t operator()( gsl::byte v ) const gsl_noexcept
- {
- return gsl::to_integer<std::size_t>( v );
- }
-};
-
-} // namespace std
-
-#endif
+#include "gsl-lite.hpp"
#endif // GSL_GSL_LITE_H_INCLUDED
-
-// end of file
diff --git a/third_party/gsl/gsl-lite.hpp b/third_party/gsl/gsl-lite.hpp
new file mode 100644
index 0000000..21c114c
--- /dev/null
+++ b/third_party/gsl/gsl-lite.hpp
@@ -0,0 +1,5197 @@
+//
+// gsl-lite is based on GSL: Guidelines Support Library.
+// For more information see https://github.com/gsl-lite/gsl-lite
+//
+// Copyright (c) 2015-2019 Martin Moene
+// Copyright (c) 2019-2021 Moritz Beutel
+// Copyright (c) 2015-2018 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_LITE_HPP_INCLUDED
+#define GSL_GSL_LITE_HPP_INCLUDED
+
+#include <exception> // for exception, terminate(), uncaught_exceptions()
+#include <limits>
+#include <memory> // for addressof(), unique_ptr<>, shared_ptr<>
+#include <iosfwd> // for basic_ostream<>
+#include <ios> // for ios_base, streamsize
+#include <stdexcept> // for logic_error
+#include <string>
+#include <utility> // for move(), forward<>(), swap()
+#include <cstddef> // for size_t, ptrdiff_t, nullptr_t
+
+#define gsl_lite_MAJOR 0
+#define gsl_lite_MINOR 38
+#define gsl_lite_PATCH 1
+
+#define gsl_lite_VERSION gsl_STRINGIFY(gsl_lite_MAJOR) "." gsl_STRINGIFY(gsl_lite_MINOR) "." gsl_STRINGIFY(gsl_lite_PATCH)
+
+#define gsl_STRINGIFY( x ) gsl_STRINGIFY_( x )
+#define gsl_STRINGIFY_( x ) #x
+#define gsl_CONCAT_( a, b ) gsl_CONCAT2_( a, b )
+#define gsl_CONCAT2_( a, b ) a##b
+#define gsl_EVALF_( f ) f()
+
+// configuration argument checking:
+
+#define gsl_DETAIL_CFG_TOGGLE_VALUE_1 1
+#define gsl_DETAIL_CFG_TOGGLE_VALUE_0 1
+#define gsl_DETAIL_CFG_DEFAULTS_VERSION_VALUE_1 1
+#define gsl_DETAIL_CFG_DEFAULTS_VERSION_VALUE_0 1
+#define gsl_DETAIL_CFG_STD_VALUE_98 1
+#define gsl_DETAIL_CFG_STD_VALUE_3 1
+#define gsl_DETAIL_CFG_STD_VALUE_03 1
+#define gsl_DETAIL_CFG_STD_VALUE_11 1
+#define gsl_DETAIL_CFG_STD_VALUE_14 1
+#define gsl_DETAIL_CFG_STD_VALUE_17 1
+#define gsl_DETAIL_CFG_STD_VALUE_20 1
+#define gsl_DETAIL_CFG_NO_VALUE_ 1
+#define gsl_DETAIL_CFG_NO_VALUE_1 1 // many compilers treat the command-line parameter "-Dfoo" as equivalent to "-Dfoo=1", so we tolerate that
+#define gsl_CHECK_CFG_TOGGLE_VALUE_( x ) gsl_CONCAT_( gsl_DETAIL_CFG_TOGGLE_VALUE_, x )
+#define gsl_CHECK_CFG_DEFAULTS_VERSION_VALUE_( x ) gsl_CONCAT_( gsl_DETAIL_CFG_DEFAULTS_VERSION_VALUE_, x )
+#define gsl_CHECK_CFG_STD_VALUE_( x ) gsl_CONCAT_( gsl_DETAIL_CFG_STD_VALUE_, x )
+#define gsl_CHECK_CFG_NO_VALUE_( x ) gsl_CONCAT_( gsl_DETAIL_CFG_NO_VALUE, gsl_CONCAT_( _, x ) )
+
+// gsl-lite backward compatibility:
+
+#if defined( gsl_CONFIG_DEFAULTS_VERSION )
+# if ! gsl_CHECK_CFG_DEFAULTS_VERSION_VALUE_( gsl_CONFIG_DEFAULTS_VERSION )
+# pragma message ("invalid configuration value gsl_CONFIG_DEFAULTS_VERSION=" gsl_STRINGIFY(gsl_CONFIG_DEFAULTS_VERSION) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_DEFAULTS_VERSION gsl_lite_MAJOR // default
+#endif
+# define gsl_CONFIG_DEFAULTS_VERSION_() gsl_CONFIG_DEFAULTS_VERSION
+
+#if defined( gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR )
+# pragma message ("invalid configuration value gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR=" gsl_STRINGIFY(gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR) ", must be 0 or 1")
+# endif
+# define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR
+# pragma message ("gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR is deprecated since gsl-lite 0.7; replace with gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR, or consider span(with_container, cont).")
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_LEVEL_ON )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_LEVEL_ON )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_LEVEL_ON=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_LEVEL_ON) "; macro must be defined without value")
+# endif
+# pragma message ("gsl_CONFIG_CONTRACT_LEVEL_ON is deprecated since gsl-lite 0.36; replace with gsl_CONFIG_CONTRACT_CHECKING_ON.")
+# define gsl_CONFIG_CONTRACT_CHECKING_ON
+#endif
+#if defined( gsl_CONFIG_CONTRACT_LEVEL_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_LEVEL_OFF )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_LEVEL_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_LEVEL_OFF) "; macro must be defined without value")
+# endif
+# pragma message ("gsl_CONFIG_CONTRACT_LEVEL_OFF is deprecated since gsl-lite 0.36; replace with gsl_CONFIG_CONTRACT_CHECKING_OFF.")
+# define gsl_CONFIG_CONTRACT_CHECKING_OFF
+#endif
+#if defined( gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY) "; macro must be defined without value")
+# endif
+# pragma message ("gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY is deprecated since gsl-lite 0.36; replace with gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF and gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF.")
+# define gsl_CONFIG_CONTRACT_CHECKING_ON
+# define gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF
+# define gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF
+#elif defined( gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY) "; macro must be defined without value")
+# endif
+# pragma message ("gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY is deprecated since gsl-lite 0.36; replace with gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF and gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF.")
+# define gsl_CONFIG_CONTRACT_CHECKING_ON
+# define gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF
+# define gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF
+#endif
+
+// M-GSL compatibility:
+
+#if defined( GSL_THROW_ON_CONTRACT_VIOLATION )
+# if ! gsl_CHECK_CFG_NO_VALUE_( GSL_THROW_ON_CONTRACT_VIOLATION )
+# pragma message ("invalid configuration value GSL_THROW_ON_CONTRACT_VIOLATION=" gsl_STRINGIFY(GSL_THROW_ON_CONTRACT_VIOLATION) "; macro must be defined without value")
+# endif
+# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS
+#endif
+
+#if defined( GSL_TERMINATE_ON_CONTRACT_VIOLATION )
+# if ! gsl_CHECK_CFG_NO_VALUE_( GSL_TERMINATE_ON_CONTRACT_VIOLATION )
+# pragma message ("invalid configuration value GSL_TERMINATE_ON_CONTRACT_VIOLATION=" gsl_STRINGIFY(GSL_TERMINATE_ON_CONTRACT_VIOLATION) "; macro must be defined without value")
+# endif
+# define gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES
+#endif
+
+#if defined( GSL_UNENFORCED_ON_CONTRACT_VIOLATION )
+# if ! gsl_CHECK_CFG_NO_VALUE_( GSL_UNENFORCED_ON_CONTRACT_VIOLATION )
+# pragma message ("invalid configuration value GSL_UNENFORCED_ON_CONTRACT_VIOLATION=" gsl_STRINGIFY(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) "; macro must be defined without value")
+# endif
+# define gsl_CONFIG_CONTRACT_CHECKING_OFF
+#endif
+
+// Configuration: Features
+
+#if defined( gsl_FEATURE_WITH_CONTAINER_TO_STD )
+# if ! gsl_CHECK_CFG_STD_VALUE_( gsl_FEATURE_WITH_CONTAINER_TO_STD )
+# pragma message ("invalid configuration value gsl_FEATURE_WITH_CONTAINER_TO_STD=" gsl_STRINGIFY(gsl_FEATURE_WITH_CONTAINER_TO_STD) ", must be 98, 3, 11, 14, 17, or 20")
+# endif
+#else
+# define gsl_FEATURE_WITH_CONTAINER_TO_STD 99 // default
+#endif
+#define gsl_FEATURE_WITH_CONTAINER_TO_STD_() gsl_FEATURE_WITH_CONTAINER_TO_STD
+
+#if defined( gsl_FEATURE_MAKE_SPAN_TO_STD )
+# if ! gsl_CHECK_CFG_STD_VALUE_( gsl_FEATURE_MAKE_SPAN_TO_STD )
+# pragma message ("invalid configuration value gsl_FEATURE_MAKE_SPAN_TO_STD=" gsl_STRINGIFY(gsl_FEATURE_MAKE_SPAN_TO_STD) ", must be 98, 3, 11, 14, 17, or 20")
+# endif
+#else
+# define gsl_FEATURE_MAKE_SPAN_TO_STD 99 // default
+#endif
+#define gsl_FEATURE_MAKE_SPAN_TO_STD_() gsl_FEATURE_MAKE_SPAN_TO_STD
+
+#if defined( gsl_FEATURE_BYTE_SPAN_TO_STD )
+# if ! gsl_CHECK_CFG_STD_VALUE_( gsl_FEATURE_BYTE_SPAN_TO_STD )
+# pragma message ("invalid configuration value gsl_FEATURE_BYTE_SPAN_TO_STD=" gsl_STRINGIFY(gsl_FEATURE_BYTE_SPAN_TO_STD) ", must be 98, 3, 11, 14, 17, or 20")
+# endif
+#else
+# define gsl_FEATURE_BYTE_SPAN_TO_STD 99 // default
+#endif
+#define gsl_FEATURE_BYTE_SPAN_TO_STD_() gsl_FEATURE_BYTE_SPAN_TO_STD
+
+#if defined( gsl_FEATURE_IMPLICIT_MACRO )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_IMPLICIT_MACRO )
+# pragma message ("invalid configuration value gsl_FEATURE_IMPLICIT_MACRO=" gsl_STRINGIFY(gsl_FEATURE_IMPLICIT_MACRO) ", must be 0 or 1")
+# endif
+#else
+# define gsl_FEATURE_IMPLICIT_MACRO 0 // default
+#endif
+#define gsl_FEATURE_IMPLICIT_MACRO_() gsl_FEATURE_IMPLICIT_MACRO
+
+#if defined( gsl_FEATURE_OWNER_MACRO )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_OWNER_MACRO )
+# pragma message ("invalid configuration value gsl_FEATURE_OWNER_MACRO=" gsl_STRINGIFY(gsl_FEATURE_OWNER_MACRO) ", must be 0 or 1")
+# endif
+#else
+# define gsl_FEATURE_OWNER_MACRO (gsl_CONFIG_DEFAULTS_VERSION == 0) // default
+#endif
+#define gsl_FEATURE_OWNER_MACRO_() gsl_FEATURE_OWNER_MACRO
+
+#if defined( gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD )
+# pragma message ("invalid configuration value gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD=" gsl_STRINGIFY(gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD) ", must be 0 or 1")
+# endif
+#else
+# define gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD 0 // default
+#endif
+# define gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD_() gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD
+
+#if defined( gsl_FEATURE_GSL_LITE_NAMESPACE )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_FEATURE_GSL_LITE_NAMESPACE )
+# pragma message ("invalid configuration value gsl_FEATURE_GSL_LITE_NAMESPACE=" gsl_STRINGIFY(gsl_FEATURE_GSL_LITE_NAMESPACE) ", must be 0 or 1")
+# endif
+#else
+# define gsl_FEATURE_GSL_LITE_NAMESPACE (gsl_CONFIG_DEFAULTS_VERSION >= 1) // default
+#endif
+#define gsl_FEATURE_GSL_LITE_NAMESPACE_() gsl_FEATURE_GSL_LITE_NAMESPACE
+
+// Configuration: Other
+
+#if defined( gsl_CONFIG_TRANSPARENT_NOT_NULL )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_TRANSPARENT_NOT_NULL )
+# pragma message ("invalid configuration value gsl_CONFIG_TRANSPARENT_NOT_NULL=" gsl_STRINGIFY(gsl_CONFIG_TRANSPARENT_NOT_NULL) ", must be 0 or 1")
+# endif
+# if gsl_CONFIG_TRANSPARENT_NOT_NULL && defined( gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF )
+# error configuration option gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF is meaningless if gsl_CONFIG_TRANSPARENT_NOT_NULL=1
+# endif
+#else
+# define gsl_CONFIG_TRANSPARENT_NOT_NULL (gsl_CONFIG_DEFAULTS_VERSION >= 1) // default
+#endif
+# define gsl_CONFIG_TRANSPARENT_NOT_NULL_() gsl_CONFIG_TRANSPARENT_NOT_NULL
+
+#if ! defined( gsl_CONFIG_DEPRECATE_TO_LEVEL )
+# if gsl_CONFIG_DEFAULTS_VERSION >= 1
+# define gsl_CONFIG_DEPRECATE_TO_LEVEL 6
+# else
+# define gsl_CONFIG_DEPRECATE_TO_LEVEL 0
+# endif
+#endif
+
+#if ! defined( gsl_CONFIG_SPAN_INDEX_TYPE )
+# define gsl_CONFIG_SPAN_INDEX_TYPE std::size_t
+#endif
+# define gsl_CONFIG_SPAN_INDEX_TYPE_() gsl_CONFIG_SPAN_INDEX_TYPE
+
+#if ! defined( gsl_CONFIG_INDEX_TYPE )
+# if gsl_CONFIG_DEFAULTS_VERSION >= 1
+// p0122r3 uses std::ptrdiff_t
+# define gsl_CONFIG_INDEX_TYPE std::ptrdiff_t
+# else
+# define gsl_CONFIG_INDEX_TYPE gsl_CONFIG_SPAN_INDEX_TYPE
+# endif
+#endif
+# define gsl_CONFIG_INDEX_TYPE_() gsl_CONFIG_INDEX_TYPE
+
+#if defined( gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR )
+# pragma message ("invalid configuration value gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR=" gsl_STRINGIFY(gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR (gsl_CONFIG_DEFAULTS_VERSION >= 1) // default
+#endif
+#define gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR_() gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR
+
+#if defined( gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF )
+# pragma message ("invalid configuration value gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF=" gsl_STRINGIFY(gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF 0 // default
+#endif
+#define gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF_() gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF
+
+#if defined( gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS )
+# pragma message ("invalid configuration value gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS=" gsl_STRINGIFY(gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS 0 // default
+#endif
+#define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS_() gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS
+
+#if defined( gsl_CONFIG_ALLOWS_SPAN_COMPARISON )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_ALLOWS_SPAN_COMPARISON )
+# pragma message ("invalid configuration value gsl_CONFIG_ALLOWS_SPAN_COMPARISON=" gsl_STRINGIFY(gsl_CONFIG_ALLOWS_SPAN_COMPARISON) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_ALLOWS_SPAN_COMPARISON (gsl_CONFIG_DEFAULTS_VERSION == 0) // default
+#endif
+#define gsl_CONFIG_ALLOWS_SPAN_COMPARISON_() gsl_CONFIG_ALLOWS_SPAN_COMPARISON
+
+#if defined( gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON )
+# pragma message ("invalid configuration value gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=" gsl_STRINGIFY(gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON 1 // default
+#endif
+#define gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON_() gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON
+
+#if defined( gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+# pragma message ("invalid configuration value gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR=" gsl_STRINGIFY(gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR 0 // default
+#endif
+#define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR_() gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR
+
+#if defined( gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION )
+# if ! gsl_CHECK_CFG_TOGGLE_VALUE_( gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION )
+# pragma message ("invalid configuration value gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=" gsl_STRINGIFY(gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION) ", must be 0 or 1")
+# endif
+#else
+# define gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION (gsl_CONFIG_DEFAULTS_VERSION >= 1) // default
+#endif
+#define gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION_() gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION
+
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_AUDIT )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_AUDIT=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_AUDIT) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_ON )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_ON )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_ON=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_ON) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_CHECKING_OFF=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_CHECKING_OFF) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_THROWS )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_THROWS=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_THROWS) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_TRAPS=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_TRAPS) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# pragma message ("invalid configuration value gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER=" gsl_STRINGIFY(gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+# pragma message ("invalid configuration value gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME=" gsl_STRINGIFY(gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME) "; macro must be defined without value")
+# endif
+#endif
+#if defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE )
+# if ! gsl_CHECK_CFG_NO_VALUE_( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE )
+# pragma message ("invalid configuration value gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE=" gsl_STRINGIFY(gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE) "; macro must be defined without value")
+# endif
+#endif
+
+#if 1 < defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT ) + defined( gsl_CONFIG_CONTRACT_CHECKING_ON ) + defined( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+# error only one of gsl_CONFIG_CONTRACT_CHECKING_AUDIT, gsl_CONFIG_CONTRACT_CHECKING_ON, and gsl_CONFIG_CONTRACT_CHECKING_OFF may be defined
+#endif
+#if 1 < defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# error only one of gsl_CONFIG_CONTRACT_VIOLATION_THROWS, gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES, gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS, gsl_CONFIG_CONTRACT_VIOLATION_TRAPS, and gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER may be defined
+#endif
+#if 1 < defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME ) + defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE )
+# error only one of gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME and gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE may be defined
+#endif
+
+#if 0 == defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT ) + defined( gsl_CONFIG_CONTRACT_CHECKING_ON ) + defined( gsl_CONFIG_CONTRACT_CHECKING_OFF )
+// select default
+# define gsl_CONFIG_CONTRACT_CHECKING_ON
+#endif
+#if 0 == defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS ) + defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+// select default
+# define gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES
+#endif
+#if 0 == defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME ) + defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE )
+// select default
+# define gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE
+#endif
+
+// C++ language version detection (C++20 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef gsl_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+# define gsl_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+# define gsl_CPLUSPLUS __cplusplus
+# endif
+#endif
+
+// C++ standard library version:
+
+#ifndef gsl_CPLUSPLUS_STDLIB
+# define gsl_CPLUSPLUS_STDLIB gsl_CPLUSPLUS
+#endif
+
+#define gsl_CPP98_OR_GREATER ( gsl_CPLUSPLUS >= 199711L )
+#define gsl_CPP11_OR_GREATER ( gsl_CPLUSPLUS >= 201103L )
+#define gsl_CPP14_OR_GREATER ( gsl_CPLUSPLUS >= 201402L )
+#define gsl_CPP17_OR_GREATER ( gsl_CPLUSPLUS >= 201703L )
+#define gsl_CPP20_OR_GREATER ( gsl_CPLUSPLUS >= 202000L )
+
+// C++ language version (represent 98 as 3):
+
+#define gsl_CPLUSPLUS_V ( gsl_CPLUSPLUS / 100 - (gsl_CPLUSPLUS > 200000 ? 2000 : 1994) )
+
+// half-open range [lo..hi):
+#define gsl_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
+
+// Compiler versions:
+
+// MSVC++ 6.0 _MSC_VER == 1200 gsl_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
+// MSVC++ 7.0 _MSC_VER == 1300 gsl_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
+// MSVC++ 7.1 _MSC_VER == 1310 gsl_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
+// MSVC++ 8.0 _MSC_VER == 1400 gsl_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
+// MSVC++ 9.0 _MSC_VER == 1500 gsl_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
+// MSVC++ 10.0 _MSC_VER == 1600 gsl_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
+// MSVC++ 11.0 _MSC_VER == 1700 gsl_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
+// MSVC++ 12.0 _MSC_VER == 1800 gsl_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
+// MSVC++ 14.0 _MSC_VER == 1900 gsl_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
+// MSVC++ 14.1 _MSC_VER >= 1910 gsl_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
+// MSVC++ 14.2 _MSC_VER >= 1920 gsl_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
+
+#if defined( _MSC_VER ) && ! defined( __clang__ )
+# define gsl_COMPILER_MSVC_VER (_MSC_VER )
+# define gsl_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
+# define gsl_COMPILER_MSVC_VERSION_FULL (_MSC_VER - 100 * ( 5 + (_MSC_VER < 1900 ) ) )
+#else
+# define gsl_COMPILER_MSVC_VER 0
+# define gsl_COMPILER_MSVC_VERSION 0
+# define gsl_COMPILER_MSVC_VERSION_FULL 0
+#endif
+
+#define gsl_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
+
+// AppleClang 7.0.0 __apple_build_version__ == 7000172 gsl_COMPILER_APPLECLANG_VERSION == 700 (Xcode 7.0, 7.0.1) (LLVM 3.7.0)
+// AppleClang 7.0.0 __apple_build_version__ == 7000176 gsl_COMPILER_APPLECLANG_VERSION == 700 (Xcode 7.1) (LLVM 3.7.0)
+// AppleClang 7.0.2 __apple_build_version__ == 7000181 gsl_COMPILER_APPLECLANG_VERSION == 702 (Xcode 7.2, 7.2.1) (LLVM 3.7.0)
+// AppleClang 7.3.0 __apple_build_version__ == 7030029 gsl_COMPILER_APPLECLANG_VERSION == 730 (Xcode 7.3) (LLVM 3.8.0)
+// AppleClang 7.3.0 __apple_build_version__ == 7030031 gsl_COMPILER_APPLECLANG_VERSION == 730 (Xcode 7.3.1) (LLVM 3.8.0)
+// AppleClang 8.0.0 __apple_build_version__ == 8000038 gsl_COMPILER_APPLECLANG_VERSION == 800 (Xcode 8.0) (LLVM 3.9.0)
+// AppleClang 8.0.0 __apple_build_version__ == 8000042 gsl_COMPILER_APPLECLANG_VERSION == 800 (Xcode 8.1, 8.2, 8.2.1) (LLVM 3.9.0)
+// AppleClang 8.1.0 __apple_build_version__ == 8020038 gsl_COMPILER_APPLECLANG_VERSION == 810 (Xcode 8.3) (LLVM 3.9.0)
+// AppleClang 8.1.0 __apple_build_version__ == 8020041 gsl_COMPILER_APPLECLANG_VERSION == 810 (Xcode 8.3.1) (LLVM 3.9.0)
+// AppleClang 8.1.0 __apple_build_version__ == 8020042 gsl_COMPILER_APPLECLANG_VERSION == 810 (Xcode 8.3.2, 8.3.3) (LLVM 3.9.0)
+// AppleClang 9.0.0 __apple_build_version__ == 9000037 gsl_COMPILER_APPLECLANG_VERSION == 900 (Xcode 9.0) (LLVM 4.0.0)
+// AppleClang 9.0.0 __apple_build_version__ == 9000038 gsl_COMPILER_APPLECLANG_VERSION == 900 (Xcode 9.1) (LLVM 4.0.0)
+// AppleClang 9.0.0 __apple_build_version__ == 9000039 gsl_COMPILER_APPLECLANG_VERSION == 900 (Xcode 9.2) (LLVM 4.0.0)
+// AppleClang 9.1.0 __apple_build_version__ == 9020039 gsl_COMPILER_APPLECLANG_VERSION == 910 (Xcode 9.3, 9.3.1) (LLVM 5.0.2)
+// AppleClang 9.1.0 __apple_build_version__ == 9020039 gsl_COMPILER_APPLECLANG_VERSION == 910 (Xcode 9.4, 9.4.1) (LLVM 5.0.2)
+// AppleClang 10.0.0 __apple_build_version__ == 10001145 gsl_COMPILER_APPLECLANG_VERSION == 1000 (Xcode 10.0, 10.1) (LLVM 6.0.1)
+// AppleClang 10.0.1 __apple_build_version__ == 10010046 gsl_COMPILER_APPLECLANG_VERSION == 1001 (Xcode 10.2, 10.2.1, 10.3) (LLVM 7.0.0)
+// AppleClang 11.0.0 __apple_build_version__ == 11000033 gsl_COMPILER_APPLECLANG_VERSION == 1100 (Xcode 11.1, 11.2, 11.3, 11.3.1) (LLVM 8.0.0)
+// AppleClang 11.0.3 __apple_build_version__ == 11030032 gsl_COMPILER_APPLECLANG_VERSION == 1103 (Xcode 11.4, 11.4.1, 11.5, 11.6) (LLVM 9.0.0)
+// AppleClang 12.0.0 __apple_build_version__ == 12000032 gsl_COMPILER_APPLECLANG_VERSION == 1200 (Xcode 12.0–12.4) (LLVM 10.0.0)
+// AppleClang 12.0.5 __apple_build_version__ == 12050022 gsl_COMPILER_APPLECLANG_VERSION == 1205 (Xcode 12.5) (LLVM 10.0.0)
+
+#if defined( __apple_build_version__ )
+# define gsl_COMPILER_APPLECLANG_VERSION gsl_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
+# define gsl_COMPILER_CLANG_VERSION 0
+#elif defined( __clang__ )
+# define gsl_COMPILER_APPLECLANG_VERSION 0
+# define gsl_COMPILER_CLANG_VERSION gsl_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
+#else
+# define gsl_COMPILER_APPLECLANG_VERSION 0
+# define gsl_COMPILER_CLANG_VERSION 0
+#endif
+
+#if defined( __GNUC__ ) && ! defined( __clang__ )
+# define gsl_COMPILER_GNUC_VERSION gsl_COMPILER_VERSION( __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ )
+#else
+# define gsl_COMPILER_GNUC_VERSION 0
+#endif
+
+#if defined( __NVCC__ )
+# define gsl_COMPILER_NVCC_VERSION ( __CUDACC_VER_MAJOR__ * 10 + __CUDACC_VER_MINOR__ )
+#else
+# define gsl_COMPILER_NVCC_VERSION 0
+#endif
+
+#if defined( __ARMCC_VERSION )
+# define gsl_COMPILER_ARMCC_VERSION ( __ARMCC_VERSION / 10000 )
+# define gsl_COMPILER_ARMCC_VERSION_FULL __ARMCC_VERSION
+#else
+# define gsl_COMPILER_ARMCC_VERSION 0
+# define gsl_COMPILER_ARMCC_VERSION_FULL 0
+#endif
+
+// Compiler non-strict aliasing:
+
+#if defined(__clang__) || defined(__GNUC__)
+# define gsl_may_alias __attribute__((__may_alias__))
+#else
+# define gsl_may_alias
+#endif
+
+// Presence of gsl, language and library features:
+
+#define gsl_IN_STD( v ) ( ((v) == 98 ? 3 : (v)) >= gsl_CPLUSPLUS_V )
+
+#define gsl_DEPRECATE_TO_LEVEL( level ) ( level <= gsl_CONFIG_DEPRECATE_TO_LEVEL )
+#define gsl_FEATURE_TO_STD( feature ) gsl_IN_STD( gsl_FEATURE( feature##_TO_STD ) )
+#define gsl_FEATURE( feature ) gsl_EVALF_( gsl_FEATURE_##feature##_ )
+#define gsl_CONFIG( feature ) gsl_EVALF_( gsl_CONFIG_##feature##_ )
+#define gsl_HAVE( feature ) gsl_EVALF_( gsl_HAVE_##feature##_ )
+
+// Presence of wide character support:
+
+#ifdef __DJGPP__
+# define gsl_HAVE_WCHAR 0
+#else
+# define gsl_HAVE_WCHAR 1
+#endif
+#define gsl_HAVE_WCHAR_() gsl_HAVE_WCHAR
+
+// Presence of language & library features:
+
+#if gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+# ifdef __OBJC__
+ // There are a bunch of inconsistencies about __EXCEPTIONS and __has_feature(cxx_exceptions) in Clang 3.4/3.5/3.6.
+ // We're interested in C++ exceptions, which can be checked by __has_feature(cxx_exceptions) in 3.5+.
+ // In pre-3.5, __has_feature(cxx_exceptions) can be true if ObjC exceptions are enabled, but C++ exceptions are disabled.
+ // The recommended way to check is `__EXCEPTIONS && __has_feature(cxx_exceptions)`.
+ // See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
+ // Note: this is only relevant in Objective-C++, thus the ifdef.
+# if __EXCEPTIONS && __has_feature(cxx_exceptions)
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif // __EXCEPTIONS && __has_feature(cxx_exceptions)
+# else
+ // clang-cl doesn't define __EXCEPTIONS for MSVC compatibility (see https://reviews.llvm.org/D4065).
+ // Neither does Clang in MS-compatiblity mode.
+ // Let's hope no one tries to build Objective-C++ code using MS-compatibility mode or clang-cl.
+# if __has_feature(cxx_exceptions)
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif
+# endif
+#elif gsl_COMPILER_GNUC_VERSION
+# if gsl_BETWEEN(gsl_COMPILER_GNUC_VERSION, 1, 500)
+# ifdef __EXCEPTIONS
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif // __EXCEPTIONS
+# else
+# ifdef __cpp_exceptions
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif // __cpp_exceptions
+# endif // gsl_BETWEEN(gsl_COMPILER_GNUC_VERSION, 1, 500)
+#elif gsl_COMPILER_MSVC_VERSION
+# ifdef _CPPUNWIND
+# define gsl_HAVE_EXCEPTIONS 1
+# else
+# define gsl_HAVE_EXCEPTIONS 0
+# endif // _CPPUNWIND
+#else
+// For all other compilers, assume exceptions are always enabled.
+# define gsl_HAVE_EXCEPTIONS 1
+#endif
+#define gsl_HAVE_EXCEPTIONS_() gsl_HAVE_EXCEPTIONS
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && ! gsl_HAVE_EXCEPTIONS
+# error Cannot use gsl_CONFIG_CONTRACT_VIOLATION_THROWS if exceptions are disabled.
+#endif // defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && !gsl_HAVE( EXCEPTIONS )
+
+#ifdef _HAS_CPP0X
+# define gsl_HAS_CPP0X _HAS_CPP0X
+#else
+# define gsl_HAS_CPP0X 0
+#endif
+
+#define gsl_CPP11_100 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1600)
+#define gsl_CPP11_110 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1700)
+#define gsl_CPP11_120 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800)
+#define gsl_CPP11_140 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_CPP14_000 (gsl_CPP14_OR_GREATER)
+#define gsl_CPP14_120 (gsl_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800)
+#define gsl_CPP14_140 (gsl_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_CPP17_000 (gsl_CPP17_OR_GREATER)
+#define gsl_CPP17_140 (gsl_CPP17_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_CPP11_140_CPP0X_90 (gsl_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1500 && gsl_HAS_CPP0X))
+#define gsl_CPP11_140_CPP0X_100 (gsl_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1600 && gsl_HAS_CPP0X))
+
+// Presence of C++11 language features:
+
+#define gsl_HAVE_C99_PREPROCESSOR gsl_CPP11_140
+#define gsl_HAVE_AUTO gsl_CPP11_100
+#define gsl_HAVE_RVALUE_REFERENCE gsl_CPP11_100
+#define gsl_HAVE_FUNCTION_REF_QUALIFIER ( gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 481 ) )
+#define gsl_HAVE_ENUM_CLASS gsl_CPP11_110
+#define gsl_HAVE_ALIAS_TEMPLATE gsl_CPP11_120
+#define gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG gsl_CPP11_120
+#define gsl_HAVE_EXPLICIT gsl_CPP11_120
+#define gsl_HAVE_VARIADIC_TEMPLATE gsl_CPP11_120
+#define gsl_HAVE_IS_DELETE gsl_CPP11_120
+#define gsl_HAVE_CONSTEXPR_11 gsl_CPP11_140
+#define gsl_HAVE_IS_DEFAULT gsl_CPP11_140
+#define gsl_HAVE_NOEXCEPT gsl_CPP11_140
+#define gsl_HAVE_NORETURN ( gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 480 ) )
+#define gsl_HAVE_EXPRESSION_SFINAE gsl_CPP11_140
+#define gsl_HAVE_OVERRIDE_FINAL gsl_CPP11_110
+
+#define gsl_HAVE_C99_PREPROCESSOR_() gsl_HAVE_C99_PREPROCESSOR
+#define gsl_HAVE_AUTO_() gsl_HAVE_AUTO
+#define gsl_HAVE_RVALUE_REFERENCE_() gsl_HAVE_RVALUE_REFERENCE
+#define gsl_HAVE_FUNCTION_REF_QUALIFIER_() gsl_HAVE_FUNCTION_REF_QUALIFIER
+#define gsl_HAVE_ENUM_CLASS_() gsl_HAVE_ENUM_CLASS
+#define gsl_HAVE_ALIAS_TEMPLATE_() gsl_HAVE_ALIAS_TEMPLATE
+#define gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG_() gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+#define gsl_HAVE_EXPLICIT_() gsl_HAVE_EXPLICIT
+#define gsl_HAVE_VARIADIC_TEMPLATE_() gsl_HAVE_VARIADIC_TEMPLATE
+#define gsl_HAVE_IS_DELETE_() gsl_HAVE_IS_DELETE
+#define gsl_HAVE_CONSTEXPR_11_() gsl_HAVE_CONSTEXPR_11
+#define gsl_HAVE_IS_DEFAULT_() gsl_HAVE_IS_DEFAULT
+#define gsl_HAVE_NOEXCEPT_() gsl_HAVE_NOEXCEPT
+#define gsl_HAVE_NORETURN_() gsl_HAVE_NORETURN
+#define gsl_HAVE_EXPRESSION_SFINAE_() gsl_HAVE_EXPRESSION_SFINAE
+#define gsl_HAVE_OVERRIDE_FINAL_() gsl_HAVE_OVERRIDE_FINAL
+
+// Presence of C++14 language features:
+
+#define gsl_HAVE_CONSTEXPR_14 ( gsl_CPP14_000 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 600 ) )
+#define gsl_HAVE_DECLTYPE_AUTO gsl_CPP14_140
+#define gsl_HAVE_DEPRECATED ( gsl_CPP14_140 && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 142 ) )
+
+#define gsl_HAVE_CONSTEXPR_14_() gsl_HAVE_CONSTEXPR_14
+#define gsl_HAVE_DECLTYPE_AUTO_() gsl_HAVE_DECLTYPE_AUTO
+#define gsl_HAVE_DEPRECATED_() gsl_HAVE_DEPRECATED
+
+// Presence of C++17 language features:
+// MSVC: template parameter deduction guides since Visual Studio 2017 v15.7
+
+#define gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE gsl_CPP17_000
+#define gsl_HAVE_DEDUCTION_GUIDES ( gsl_CPP17_000 && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION_FULL, 1, 1414 ) )
+#define gsl_HAVE_NODISCARD gsl_CPP17_000
+#define gsl_HAVE_CONSTEXPR_17 gsl_CPP17_OR_GREATER
+
+#define gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE_() gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE
+#define gsl_HAVE_DEDUCTION_GUIDES_() gsl_HAVE_DEDUCTION_GUIDES
+#define gsl_HAVE_NODISCARD_() gsl_HAVE_NODISCARD
+#define gsl_HAVE_CONSTEXPR_17_() gsl_HAVE_CONSTEXPR_17
+
+// Presence of C++20 language features:
+
+#define gsl_HAVE_CONSTEXPR_20 gsl_CPP20_OR_GREATER
+
+#define gsl_HAVE_CONSTEXPR_20_() gsl_HAVE_CONSTEXPR_20
+
+// Presence of C++ library features:
+
+#if gsl_BETWEEN( gsl_COMPILER_ARMCC_VERSION, 1, 600 )
+// Some versions of the ARM compiler apparently ship without a C++11 standard library despite having some C++11 support.
+# define gsl_STDLIB_CPP98_OR_GREATER gsl_CPP98_OR_GREATER
+# define gsl_STDLIB_CPP11_OR_GREATER 0
+# define gsl_STDLIB_CPP14_OR_GREATER 0
+# define gsl_STDLIB_CPP17_OR_GREATER 0
+# define gsl_STDLIB_CPP20_OR_GREATER 0
+#else
+# define gsl_STDLIB_CPP98_OR_GREATER gsl_CPP98_OR_GREATER
+# define gsl_STDLIB_CPP11_OR_GREATER gsl_CPP11_OR_GREATER
+# define gsl_STDLIB_CPP14_OR_GREATER gsl_CPP14_OR_GREATER
+# define gsl_STDLIB_CPP17_OR_GREATER gsl_CPP17_OR_GREATER
+# define gsl_STDLIB_CPP20_OR_GREATER gsl_CPP20_OR_GREATER
+#endif
+
+#define gsl_STDLIB_CPP11_100 (gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1600)
+#define gsl_STDLIB_CPP11_110 (gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1700)
+#define gsl_STDLIB_CPP11_120 (gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800)
+#define gsl_STDLIB_CPP11_140 (gsl_STDLIB_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_STDLIB_CPP14_000 (gsl_STDLIB_CPP14_OR_GREATER)
+#define gsl_STDLIB_CPP14_120 (gsl_STDLIB_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800)
+#define gsl_STDLIB_CPP14_140 (gsl_STDLIB_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_STDLIB_CPP17_000 (gsl_STDLIB_CPP17_OR_GREATER)
+#define gsl_STDLIB_CPP17_140 (gsl_STDLIB_CPP17_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900)
+
+#define gsl_STDLIB_CPP11_140_CPP0X_90 (gsl_STDLIB_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1500 && gsl_HAS_CPP0X))
+#define gsl_STDLIB_CPP11_140_CPP0X_100 (gsl_STDLIB_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1600 && gsl_HAS_CPP0X))
+
+#define gsl_HAVE_ADDRESSOF gsl_STDLIB_CPP17_000
+#define gsl_HAVE_ARRAY gsl_STDLIB_CPP11_110
+#define gsl_HAVE_TYPE_TRAITS gsl_STDLIB_CPP11_110
+#define gsl_HAVE_TR1_TYPE_TRAITS gsl_STDLIB_CPP11_110
+#define gsl_HAVE_CONTAINER_DATA_METHOD gsl_STDLIB_CPP11_140_CPP0X_90
+#define gsl_HAVE_STD_DATA gsl_STDLIB_CPP17_000
+#ifdef __cpp_lib_ssize
+# define gsl_HAVE_STD_SSIZE 1
+#else
+# define gsl_HAVE_STD_SSIZE ( gsl_COMPILER_GNUC_VERSION >= 1000 && __cplusplus > 201703L )
+#endif
+#define gsl_HAVE_HASH gsl_STDLIB_CPP11_120
+#define gsl_HAVE_SIZED_TYPES gsl_STDLIB_CPP11_140
+#define gsl_HAVE_MAKE_SHARED gsl_STDLIB_CPP11_140_CPP0X_100
+#define gsl_HAVE_SHARED_PTR gsl_STDLIB_CPP11_140_CPP0X_100
+#define gsl_HAVE_UNIQUE_PTR gsl_STDLIB_CPP11_140_CPP0X_100
+#define gsl_HAVE_MAKE_UNIQUE gsl_STDLIB_CPP14_120
+#define gsl_HAVE_MOVE_FORWARD gsl_STDLIB_CPP11_100
+#define gsl_HAVE_NULLPTR gsl_STDLIB_CPP11_100
+#define gsl_HAVE_UNCAUGHT_EXCEPTIONS gsl_STDLIB_CPP17_140
+#define gsl_HAVE_ADD_CONST gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_INITIALIZER_LIST gsl_STDLIB_CPP11_120
+#define gsl_HAVE_INTEGRAL_CONSTANT gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_REMOVE_CONST gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_REMOVE_REFERENCE gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_REMOVE_CVREF gsl_STDLIB_CPP20_OR_GREATER
+#define gsl_HAVE_TR1_ADD_CONST gsl_HAVE_TR1_TYPE_TRAITS
+#define gsl_HAVE_TR1_INTEGRAL_CONSTANT gsl_HAVE_TR1_TYPE_TRAITS
+#define gsl_HAVE_TR1_REMOVE_CONST gsl_HAVE_TR1_TYPE_TRAITS
+#define gsl_HAVE_TR1_REMOVE_REFERENCE gsl_HAVE_TR1_TYPE_TRAITS
+
+#define gsl_HAVE_ADDRESSOF_() gsl_HAVE_ADDRESSOF
+#define gsl_HAVE_ARRAY_() gsl_HAVE_ARRAY
+#define gsl_HAVE_TYPE_TRAITS_() gsl_HAVE_TYPE_TRAITS
+#define gsl_HAVE_TR1_TYPE_TRAITS_() gsl_HAVE_TR1_TYPE_TRAITS
+#define gsl_HAVE_CONTAINER_DATA_METHOD_() gsl_HAVE_CONTAINER_DATA_METHOD
+#define gsl_HAVE_HASH_() gsl_HAVE_HASH
+#define gsl_HAVE_STD_DATA_() gsl_HAVE_STD_DATA
+#define gsl_HAVE_STD_SSIZE_() gsl_HAVE_STD_SSIZE
+#define gsl_HAVE_SIZED_TYPES_() gsl_HAVE_SIZED_TYPES
+#define gsl_HAVE_MAKE_SHARED_() gsl_HAVE_MAKE_SHARED
+#define gsl_HAVE_MOVE_FORWARD_() gsl_HAVE_MOVE_FORWARD
+#define gsl_HAVE_NULLPTR_() gsl_HAVE_NULLPTR // It's a language feature but needs library support, so we list it as a library feature.
+#define gsl_HAVE_SHARED_PTR_() gsl_HAVE_SHARED_PTR
+#define gsl_HAVE_UNIQUE_PTR_() gsl_HAVE_UNIQUE_PTR
+#define gsl_HAVE_MAKE_UNIQUE_() gsl_HAVE_MAKE_UNIQUE
+#define gsl_HAVE_UNCAUGHT_EXCEPTIONS_() gsl_HAVE_UNCAUGHT_EXCEPTIONS
+#define gsl_HAVE_ADD_CONST_() gsl_HAVE_ADD_CONST
+#define gsl_HAVE_INITIALIZER_LIST_() gsl_HAVE_INITIALIZER_LIST // It's a language feature but needs library support, so we list it as a library feature.
+#define gsl_HAVE_INTEGRAL_CONSTANT_() gsl_HAVE_INTEGRAL_CONSTANT
+#define gsl_HAVE_REMOVE_CONST_() gsl_HAVE_REMOVE_CONST
+#define gsl_HAVE_REMOVE_REFERENCE_() gsl_HAVE_REMOVE_REFERENCE
+#define gsl_HAVE_REMOVE_CVREF_() gsl_HAVE_REMOVE_CVREF
+#define gsl_HAVE_TR1_ADD_CONST_() gsl_HAVE_TR1_ADD_CONST
+#define gsl_HAVE_TR1_INTEGRAL_CONSTANT_() gsl_HAVE_TR1_INTEGRAL_CONSTANT
+#define gsl_HAVE_TR1_REMOVE_CONST_() gsl_HAVE_TR1_REMOVE_CONST
+#define gsl_HAVE_TR1_REMOVE_REFERENCE_() gsl_HAVE_TR1_REMOVE_REFERENCE
+
+// C++ feature usage:
+
+#if gsl_HAVE( ADDRESSOF )
+# define gsl_ADDRESSOF(x) std::addressof(x)
+#else
+# define gsl_ADDRESSOF(x) (&x)
+#endif
+
+#if gsl_HAVE( CONSTEXPR_11 )
+# define gsl_constexpr constexpr
+#else
+# define gsl_constexpr /*constexpr*/
+#endif
+
+#if gsl_HAVE( CONSTEXPR_14 )
+# define gsl_constexpr14 constexpr
+#else
+# define gsl_constexpr14 /*constexpr*/
+#endif
+
+#if gsl_HAVE( CONSTEXPR_17 )
+# define gsl_constexpr17 constexpr
+#else
+# define gsl_constexpr17 /*constexpr*/
+#endif
+
+#if gsl_HAVE( CONSTEXPR_20 )
+# define gsl_constexpr20 constexpr
+#else
+# define gsl_constexpr20 /*constexpr*/
+#endif
+
+#if gsl_HAVE( EXPLICIT )
+# define gsl_explicit explicit
+#else
+# define gsl_explicit /*explicit*/
+#endif
+
+#if gsl_FEATURE( IMPLICIT_MACRO )
+# define implicit /*implicit*/
+#endif
+
+#if gsl_HAVE( IS_DELETE )
+# define gsl_is_delete = delete
+#else
+# define gsl_is_delete
+#endif
+
+#if gsl_HAVE( IS_DELETE )
+# define gsl_is_delete_access public
+#else
+# define gsl_is_delete_access private
+#endif
+
+#if gsl_HAVE( NOEXCEPT )
+# define gsl_noexcept noexcept
+# define gsl_noexcept_if( expr ) noexcept( expr )
+#else
+# define gsl_noexcept throw()
+# define gsl_noexcept_if( expr ) /*noexcept( expr )*/
+#endif
+#if defined( gsl_TESTING_ )
+# define gsl_noexcept_not_testing
+#else
+# define gsl_noexcept_not_testing gsl_noexcept
+#endif
+
+#if gsl_HAVE( NULLPTR )
+# define gsl_nullptr nullptr
+#else
+# define gsl_nullptr NULL
+#endif
+
+#if gsl_HAVE( NODISCARD )
+# define gsl_NODISCARD [[nodiscard]]
+#else
+# define gsl_NODISCARD
+#endif
+
+#if gsl_HAVE( NORETURN )
+# define gsl_NORETURN [[noreturn]]
+#elif defined(_MSC_VER)
+# define gsl_NORETURN __declspec(noreturn)
+#elif gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION || gsl_COMPILER_ARMCC_VERSION
+# define gsl_NORETURN __attribute__((noreturn))
+#else
+# define gsl_NORETURN
+#endif
+
+#if gsl_HAVE( DEPRECATED ) && ! defined( gsl_TESTING_ )
+# define gsl_DEPRECATED [[deprecated]]
+# define gsl_DEPRECATED_MSG( msg ) [[deprecated( msg )]]
+#else
+# define gsl_DEPRECATED
+# define gsl_DEPRECATED_MSG( msg )
+#endif
+
+#if gsl_HAVE( C99_PREPROCESSOR )
+# if gsl_CPP20_OR_GREATER
+# define gsl_CONSTRAINT(...) __VA_ARGS__
+# else
+# define gsl_CONSTRAINT(...) typename
+# endif
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS )
+# define gsl_STATIC_ASSERT_( cond, msg ) static_assert( cond, msg )
+#else
+# define gsl_STATIC_ASSERT_( cond, msg ) ( ( void )sizeof( char[1 - 2*!!( cond ) ] ) )
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS )
+
+#define gsl_DEFINE_ENUM_BITMASK_OPERATORS_( ENUM ) \
+ gsl_NODISCARD gsl_api inline gsl_constexpr ENUM \
+ operator~( ENUM val ) gsl_noexcept \
+ { \
+ typedef typename ::gsl::std11::underlying_type<ENUM>::type U; \
+ return ENUM( ~U( val ) ); \
+ } \
+ gsl_NODISCARD gsl_api inline gsl_constexpr ENUM \
+ operator|( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl::std11::underlying_type<ENUM>::type U; \
+ return ENUM( U( lhs ) | U( rhs ) ); \
+ } \
+ gsl_NODISCARD gsl_api inline gsl_constexpr ENUM \
+ operator&( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl::std11::underlying_type<ENUM>::type U; \
+ return ENUM( U( lhs ) & U( rhs ) ); \
+ } \
+ gsl_NODISCARD gsl_api inline gsl_constexpr ENUM \
+ operator^( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl::std11::underlying_type<ENUM>::type U; \
+ return ENUM( U( lhs ) ^ U( rhs ) ); \
+ } \
+ gsl_api inline gsl_constexpr14 ENUM & \
+ operator|=( ENUM & lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ return lhs = lhs | rhs; \
+ } \
+ gsl_api inline gsl_constexpr14 ENUM & \
+ operator&=( ENUM & lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ return lhs = lhs & rhs; \
+ } \
+ gsl_api inline gsl_constexpr14 ENUM & \
+ operator^=( ENUM & lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ return lhs = lhs ^ rhs; \
+ }
+
+#define gsl_DEFINE_ENUM_RELATIONAL_OPERATORS_( ENUM ) \
+ gsl_NODISCARD gsl_api inline gsl_constexpr bool \
+ operator<( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl::std11::underlying_type<ENUM>::type U; \
+ return U( lhs ) < U( rhs ); \
+ } \
+ gsl_NODISCARD gsl_api inline gsl_constexpr bool \
+ operator>( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl::std11::underlying_type<ENUM>::type U; \
+ return U( lhs ) > U( rhs ); \
+ } \
+ gsl_NODISCARD gsl_api inline gsl_constexpr bool \
+ operator<=( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl::std11::underlying_type<ENUM>::type U; \
+ return U( lhs ) <= U( rhs ); \
+ } \
+ gsl_NODISCARD gsl_api inline gsl_constexpr bool \
+ operator>=( ENUM lhs, ENUM rhs ) gsl_noexcept \
+ { \
+ typedef typename ::gsl::std11::underlying_type<ENUM>::type U; \
+ return U( lhs ) >= U( rhs ); \
+ }
+
+ //
+ // Defines bitmask operators `|`, `&`, `^`, `~`, `|=`, `&=`, and `^=` for the given enum type.
+ //
+ // enum class Vegetables { tomato = 0b001, onion = 0b010, eggplant = 0b100 };
+ // gsl_DEFINE_ENUM_BITMASK_OPERATORS( Vegetables )
+ //
+#define gsl_DEFINE_ENUM_BITMASK_OPERATORS( ENUM ) gsl_DEFINE_ENUM_BITMASK_OPERATORS_( ENUM )
+
+ //
+ // Defines relational operators `<`, `>`, `<=`, `>=` for the given enum type.
+ //
+ // enum class OperatorPrecedence { additive = 0, multiplicative = 1, power = 2 };
+ // gsl_DEFINE_ENUM_RELATIONAL_OPERATORS( OperatorPrecedence )
+ //
+#define gsl_DEFINE_ENUM_RELATIONAL_OPERATORS( ENUM ) gsl_DEFINE_ENUM_RELATIONAL_OPERATORS_( ENUM )
+
+#endif // gsl_HAVE( TYPE_TRAITS )
+
+#define gsl_DIMENSION_OF( a ) ( sizeof(a) / sizeof(0[a]) )
+
+
+// Method enabling (C++98, VC120 (VS2013) cannot use __VA_ARGS__)
+
+#if gsl_HAVE( EXPRESSION_SFINAE )
+# define gsl_TRAILING_RETURN_TYPE_(T) auto
+# define gsl_RETURN_DECLTYPE_(EXPR) -> decltype( EXPR )
+#else
+# define gsl_TRAILING_RETURN_TYPE_(T) T
+# define gsl_RETURN_DECLTYPE_(EXPR)
+#endif
+
+// NOTE: When using SFINAE in gsl-lite, please note that overloads of function templates must always use SFINAE with non-type default arguments
+// as explained in https://en.cppreference.com/w/cpp/types/enable_if#Notes. `gsl_ENABLE_IF_()` implements graceful fallback to default
+// type arguments (for compilers that don't support non-type default arguments); please verify that this is appropriate in the given
+// situation, and add additional checks if necessary.
+//
+// Also, please note that `gsl_ENABLE_IF_()` doesn't enforce the constraint at all if no compiler/library support is available (i.e. pre-C++11).
+
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+# if !gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 ) // VS 2013 seems to have trouble with SFINAE for default non-type arguments
+# define gsl_ENABLE_IF_(VA) , typename std::enable_if< ( VA ), int >::type = 0
+# else
+# define gsl_ENABLE_IF_(VA) , typename = typename std::enable_if< ( VA ), ::gsl::detail::enabler >::type
+# endif
+#else
+# define gsl_ENABLE_IF_(VA)
+#endif
+
+
+// Other features:
+
+#define gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR ( gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG && gsl_HAVE_CONTAINER_DATA_METHOD )
+#define gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR_() gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR
+
+#define gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR ( gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR && gsl_COMPILER_NVCC_VERSION == 0 )
+#define gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR_() gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR
+
+// GSL API (e.g. for CUDA platform):
+
+// Guidelines for using `gsl_api`:
+//
+// NVCC imposes the restriction that a function annotated `__host__ __device__` cannot call host-only or device-only functions.
+// This makes `gsl_api` inappropriate for generic functions that call unknown code, e.g. the template constructors of `span<>`
+// or functions like `finally()` which accept an arbitrary function object.
+// It is often preferable to annotate functions only with `gsl_constexpr` or `gsl_constexpr14`. The "extended constexpr" mode
+// of NVCC (currently an experimental feature) will implicitly consider constexpr functions `__host__ __device__` functions
+// but tolerates calls to host-only or device-only functions.
+
+#ifndef gsl_api
+# ifdef __CUDACC__
+# define gsl_api __host__ __device__
+# else
+# define gsl_api /*gsl_api*/
+# endif
+#endif
+
+// Additional includes:
+
+#if ! gsl_CPP11_OR_GREATER
+# include <algorithm> // for swap() before C++11
+#endif // ! gsl_CPP11_OR_GREATER
+
+#if gsl_HAVE( ARRAY )
+# include <array> // indirectly includes reverse_iterator<>
+#endif
+
+#if ! gsl_HAVE( ARRAY )
+# include <iterator> // for reverse_iterator<>
+#endif
+
+#if ! gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) || ! gsl_HAVE( AUTO )
+# include <vector>
+#endif
+
+#if gsl_HAVE( INITIALIZER_LIST )
+# include <initializer_list>
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS )
+# include <cassert>
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS ) && gsl_COMPILER_MSVC_VERSION >= 110 // __fastfail() supported by VS 2012 and later
+# include <intrin.h>
+#endif
+
+#if gsl_HAVE( ENUM_CLASS ) && gsl_COMPILER_ARMCC_VERSION
+# include <endian.h>
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS )
+# include <type_traits> // for enable_if<>,
+ // add_const<>, add_pointer<>, common_type<>, make_signed<>, remove_cv<>, remove_const<>, remove_volatile<>, remove_reference<>, remove_cvref<>, remove_pointer<>, underlying_type<>,
+ // is_assignable<>, is_constructible<>, is_const<>, is_convertible<>, is_integral<>, is_pointer<>, is_signed<>,
+ // integral_constant<>, declval()
+#elif gsl_HAVE( TR1_TYPE_TRAITS )
+# include <tr1/type_traits> // for add_const<>, remove_cv<>, remove_const<>, remove_volatile<>, remove_reference<>, integral_constant<>
+#endif
+
+#if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+// Declare __cxa_get_globals() or equivalent in namespace gsl::detail for uncaught_exceptions():
+
+# if ! gsl_HAVE( UNCAUGHT_EXCEPTIONS )
+# if defined( _MSC_VER ) // MS-STL with either MSVC or clang-cl
+namespace gsl { namespace detail { extern "C" char * __cdecl _getptd(); } }
+# elif gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+# if defined( __GLIBCXX__ ) || defined( __GLIBCPP__ ) // libstdc++: prototype from cxxabi.h
+# include <cxxabi.h>
+# elif ! defined( BOOST_CORE_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED_ ) // libc++: prototype from Boost?
+# if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
+namespace __cxxabiv1 { struct __cxa_eh_globals; extern "C" __cxa_eh_globals * __cxa_get_globals(); }
+# else
+namespace __cxxabiv1 { struct __cxa_eh_globals; extern "C" __cxa_eh_globals * __cxa_get_globals() gsl_noexcept; }
+# endif
+# endif
+ namespace gsl { namespace detail { using ::__cxxabiv1::__cxa_get_globals; } }
+# endif
+# endif // ! gsl_HAVE( UNCAUGHT_EXCEPTIONS )
+#endif // gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+
+// MSVC warning suppression macros:
+
+#if gsl_COMPILER_MSVC_VERSION >= 140 && ! gsl_COMPILER_NVCC_VERSION
+# define gsl_SUPPRESS_MSGSL_WARNING(expr) /* Pimm: note disabled for intel [[gsl::suppress(expr)]]*/
+# define gsl_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) )
+# define gsl_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
+# define gsl_RESTORE_MSVC_WARNINGS() __pragma(warning(pop ))
+#else
+// TODO: define for Clang
+# define gsl_SUPPRESS_MSGSL_WARNING(expr)
+# define gsl_SUPPRESS_MSVC_WARNING(code, descr)
+# define gsl_DISABLE_MSVC_WARNINGS(codes)
+# define gsl_RESTORE_MSVC_WARNINGS()
+#endif
+
+// Suppress the following MSVC GSL warnings:
+// - C26432: gsl::c.21 : if you define or delete any default operation in the type '...', define or delete them all
+// - C26410: gsl::r.32 : the parameter 'ptr' is a reference to const unique pointer, use const T* or const T& instead
+// - C26415: gsl::r.30 : smart pointer parameter 'ptr' is used only to access contained pointer. Use T* or T& instead
+// - C26418: gsl::r.36 : shared pointer parameter 'ptr' is not copied or moved. Use T* or T& instead
+// - C26472: gsl::t.1 : don't use a static_cast for arithmetic conversions;
+// use brace initialization, gsl::narrow_cast or gsl::narrow
+// - C26439: gsl::f.6 : special function 'function' can be declared 'noexcept'
+// - C26440: gsl::f.6 : function 'function' can be declared 'noexcept'
+// - C26455: gsl::f.6 : default constructor may not throw. Declare it 'noexcept'
+// - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same
+// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
+// - C26482: gsl::b.2 : only index into arrays using constant expressions
+// - C26446: gdl::b.4 : prefer to use gsl::at() instead of unchecked subscript operator
+// - C26490: gsl::t.1 : don't use reinterpret_cast
+// - C26487: gsl::l.4 : don't return a pointer '(<some number>'s result)' that may be invalid
+// - C26457: es.48 : (void) should not be used to ignore return values, use 'std::ignore =' instead
+
+gsl_DISABLE_MSVC_WARNINGS( 26432 26410 26415 26418 26472 26439 26440 26455 26473 26481 26482 26446 26490 26487 26457 )
+
+namespace gsl {
+
+// forward declare span<>:
+
+template< class T >
+class span;
+
+// C++98 emulation:
+
+namespace std98 {
+
+// We implement `equal()` and `lexicographical_compare()` here to avoid having to pull in the <algorithm> header.
+template< class InputIt1, class InputIt2 >
+bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2 )
+{
+ // Implementation borrowed from https://en.cppreference.com/w/cpp/algorithm/equal.
+ for ( ; first1 != last1; ++first1, ++first2 )
+ {
+ if ( ! (*first1 == *first2 ) ) return false;
+ }
+ return true;
+}
+template< class InputIt1, class InputIt2 >
+bool lexicographical_compare( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2 )
+{
+ // Implementation borrowed from https://en.cppreference.com/w/cpp/algorithm/lexicographical_compare.
+ for ( ; first1 != last1 && first2 != last2; ++first1, (void) ++first2 )
+ {
+ if ( *first1 < *first2 ) return true;
+ if ( *first2 < *first1 ) return false;
+ }
+ return first1 == last1 && first2 != last2;
+}
+
+} // namespace std98
+
+// C++11 emulation:
+
+namespace std11 {
+
+#if gsl_HAVE( ADD_CONST )
+
+using std::add_const;
+
+#elif gsl_HAVE( TR1_ADD_CONST )
+
+using std::tr1::add_const;
+
+#else
+
+template< class T > struct add_const { typedef const T type; };
+
+#endif // gsl_HAVE( ADD_CONST )
+
+#if gsl_HAVE( REMOVE_CONST )
+
+using std::remove_cv;
+using std::remove_const;
+using std::remove_volatile;
+
+#elif gsl_HAVE( TR1_REMOVE_CONST )
+
+using std::tr1::remove_cv;
+using std::tr1::remove_const;
+using std::tr1::remove_volatile;
+
+#else
+
+template< class T > struct remove_const { typedef T type; };
+template< class T > struct remove_const<T const> { typedef T type; };
+
+template< class T > struct remove_volatile { typedef T type; };
+template< class T > struct remove_volatile<T volatile> { typedef T type; };
+
+template< class T >
+struct remove_cv
+{
+ typedef typename remove_volatile<typename remove_const<T>::type>::type type;
+};
+
+#endif // gsl_HAVE( REMOVE_CONST )
+
+#if gsl_HAVE( REMOVE_REFERENCE )
+
+using std::remove_reference;
+
+#elif gsl_HAVE( TR1_REMOVE_REFERENCE )
+
+using std::tr1::remove_reference;
+
+#else
+
+template< class T > struct remove_reference { typedef T type; };
+template< class T > struct remove_reference<T&> { typedef T type; };
+# if gsl_HAVE( RVALUE_REFERENCE )
+template< class T > struct remove_reference<T&&> { typedef T type; };
+# endif
+
+#endif // gsl_HAVE( REMOVE_REFERENCE )
+
+
+#if gsl_HAVE( INTEGRAL_CONSTANT )
+
+using std::integral_constant;
+using std::true_type;
+using std::false_type;
+
+#elif gsl_HAVE( TR1_INTEGRAL_CONSTANT )
+
+using std::tr1::integral_constant;
+using std::tr1::true_type;
+using std::tr1::false_type;
+
+#else
+
+template< class T, T v > struct integral_constant { enum { value = v }; };
+typedef integral_constant< bool, true > true_type;
+typedef integral_constant< bool, false > false_type;
+
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS )
+
+using std::underlying_type;
+
+#elif gsl_HAVE( TR1_TYPE_TRAITS )
+
+using std::tr1::underlying_type;
+
+#else
+
+// We could try to define `underlying_type<>` for pre-C++11 here, but let's not until someone actually needs it.
+
+#endif
+
+} // namespace std11
+
+// C++14 emulation:
+
+namespace std14 {
+
+#if gsl_HAVE( UNIQUE_PTR )
+# if gsl_HAVE( MAKE_UNIQUE )
+
+using std::make_unique;
+
+# elif gsl_HAVE( VARIADIC_TEMPLATE )
+
+template< class T, class... Args >
+gsl_NODISCARD std::unique_ptr<T>
+make_unique( Args &&... args )
+{
+ return std::unique_ptr<T>( new T( std::forward<Args>( args )... ) );
+}
+
+# endif // gsl_HAVE( MAKE_UNIQUE ), gsl_HAVE( VARIADIC_TEMPLATE )
+#endif // gsl_HAVE( UNIQUE_PTR )
+
+} // namespace std14
+
+namespace detail {
+
+#if gsl_HAVE( VARIADIC_TEMPLATE )
+
+template < bool V0, class T0, class... Ts > struct conjunction_ { using type = T0; };
+template < class T0, class T1, class... Ts > struct conjunction_<true, T0, T1, Ts...> : conjunction_<T1::value, T1, Ts...> { };
+template < bool V0, class T0, class... Ts > struct disjunction_ { using type = T0; };
+template < class T0, class T1, class... Ts > struct disjunction_<false, T0, T1, Ts...> : disjunction_<T1::value, T1, Ts...> { };
+
+#endif
+
+template <typename> struct dependent_false : std11::integral_constant<bool, false> { };
+
+} // namespace detail
+
+// C++17 emulation:
+
+namespace std17 {
+
+template< bool v > struct bool_constant : std11::integral_constant<bool, v>{};
+
+#if gsl_CPP11_120
+
+template < class... Ts > struct conjunction;
+template < > struct conjunction< > : std11::true_type { };
+template < class T0, class... Ts > struct conjunction<T0, Ts...> : detail::conjunction_<T0::value, T0, Ts...>::type { };
+template < class... Ts > struct disjunction;
+template < > struct disjunction< > : std11::false_type { };
+template < class T0, class... Ts > struct disjunction<T0, Ts...> : detail::disjunction_<T0::value, T0, Ts...>::type { };
+template < class T > struct negation : std11::integral_constant<bool, !T::value> { };
+
+# if gsl_CPP14_OR_GREATER
+
+template < class... Ts > constexpr bool conjunction_v = conjunction<Ts...>::value;
+template < class... Ts > constexpr bool disjunction_v = disjunction<Ts...>::value;
+template < class T > constexpr bool negation_v = negation<T>::value;
+
+# endif // gsl_CPP14_OR_GREATER
+
+template< class... Ts >
+struct make_void { typedef void type; };
+
+template< class... Ts >
+using void_t = typename make_void< Ts... >::type;
+
+#endif // gsl_CPP11_120
+
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+template< class T, size_t N >
+gsl_NODISCARD gsl_api inline gsl_constexpr auto
+size( T const(&)[N] ) gsl_noexcept -> size_t
+{
+ return N;
+}
+
+template< class C >
+gsl_NODISCARD inline gsl_constexpr auto
+size( C const & cont ) -> decltype( cont.size() )
+{
+ return cont.size();
+}
+
+template< class T, size_t N >
+gsl_NODISCARD gsl_api inline gsl_constexpr auto
+data( T(&arr)[N] ) gsl_noexcept -> T*
+{
+ return &arr[0];
+}
+
+template< class C >
+gsl_NODISCARD inline gsl_constexpr auto
+data( C & cont ) -> decltype( cont.data() )
+{
+ return cont.data();
+}
+
+template< class C >
+gsl_NODISCARD inline gsl_constexpr auto
+data( C const & cont ) -> decltype( cont.data() )
+{
+ return cont.data();
+}
+
+template< class E >
+gsl_NODISCARD inline gsl_constexpr auto
+data( std::initializer_list<E> il ) gsl_noexcept -> E const *
+{
+ return il.begin();
+}
+
+#endif // gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+} // namespace std17
+
+// C++20 emulation:
+
+namespace std20 {
+
+#if gsl_CPP11_100
+
+struct identity
+{
+ template < class T >
+ gsl_constexpr T && operator ()( T && arg ) const gsl_noexcept
+ {
+ return std::forward<T>( arg );
+ }
+};
+
+# if gsl_HAVE( ENUM_CLASS )
+enum class endian
+{
+# if defined( _WIN32 )
+ little = 0,
+ big = 1,
+ native = little
+# elif gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+ little = __ORDER_LITTLE_ENDIAN__,
+ big = __ORDER_BIG_ENDIAN__,
+ native = __BYTE_ORDER__
+# elif gsl_COMPILER_ARMCC_VERSION
+ // from <endian.h> header file
+ little = __LITTLE_ENDIAN,
+ big = __BIG_ENDIAN,
+ native = __BYTE_ORDER
+# else
+// Do not define any endianness constants for unknown compilers.
+# endif
+};
+# endif // gsl_HAVE( ENUM_CLASS )
+
+#endif // gsl_CPP11_100
+
+template< class T >
+struct type_identity
+{
+ typedef T type;
+};
+#if gsl_HAVE( ALIAS_TEMPLATE )
+template< class T >
+using type_identity_t = typename type_identity<T>::type;
+#endif // gsl_HAVE( ALIAS_TEMPLATE )
+
+#if gsl_HAVE( STD_SSIZE )
+
+using std::ssize;
+
+#elif gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+template < class C >
+gsl_NODISCARD gsl_constexpr auto
+ssize( C const & c )
+ -> typename std::common_type<std::ptrdiff_t, typename std::make_signed<decltype(c.size())>::type>::type
+{
+ using R = typename std::common_type<std::ptrdiff_t, typename std::make_signed<decltype(c.size())>::type>::type;
+ return static_cast<R>( c.size() );
+}
+
+template <class T, std::size_t N>
+gsl_NODISCARD gsl_constexpr auto
+ssize( T const(&)[N] ) gsl_noexcept -> std::ptrdiff_t
+{
+ return std::ptrdiff_t( N );
+}
+
+#endif // gsl_HAVE( STD_SSIZE )
+
+#if gsl_HAVE( REMOVE_CVREF )
+
+using std::remove_cvref;
+
+#else
+
+template< class T > struct remove_cvref { typedef typename std11::remove_cv< typename std11::remove_reference< T >::type >::type type; };
+
+#endif // gsl_HAVE( REMOVE_CVREF )
+
+} // namespace std20
+
+namespace detail {
+
+/// for gsl_ENABLE_IF_()
+
+/*enum*/ class enabler{};
+
+#if gsl_HAVE( TYPE_TRAITS )
+
+template< class Q >
+struct is_span_oracle : std::false_type{};
+
+template< class T>
+struct is_span_oracle< span<T> > : std::true_type{};
+
+template< class Q >
+struct is_span : is_span_oracle< typename std::remove_cv<Q>::type >{};
+
+template< class Q >
+struct is_std_array_oracle : std::false_type{};
+
+# if gsl_HAVE( ARRAY )
+
+template< class T, std::size_t Extent >
+struct is_std_array_oracle< std::array<T, Extent> > : std::true_type{};
+
+# endif
+
+template< class Q >
+struct is_std_array : is_std_array_oracle< typename std::remove_cv<Q>::type >{};
+
+template< class Q >
+struct is_array : std::false_type{};
+
+template< class T >
+struct is_array<T[]> : std::true_type{};
+
+template< class T, std::size_t N >
+struct is_array<T[N]> : std::true_type{};
+
+# if gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 500 )
+
+template< class, class = void >
+struct has_size_and_data : std::false_type{};
+
+template< class C >
+struct has_size_and_data
+<
+ C, std17::void_t<
+ decltype( std17::size(std::declval<C>()) ),
+ decltype( std17::data(std::declval<C>()) ) >
+> : std::true_type{};
+
+template< class, class, class = void >
+struct is_compatible_element : std::false_type {};
+
+template< class C, class E >
+struct is_compatible_element
+<
+ C, E, std17::void_t<
+ decltype( std17::data(std::declval<C>()) ),
+ typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[] >
+> : std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >{};
+
+template< class C >
+struct is_container : std17::bool_constant
+<
+ ! is_span< C >::value
+ && ! is_array< C >::value
+ && ! is_std_array< C >::value
+ && has_size_and_data< C >::value
+>{};
+
+template< class C, class E >
+struct is_compatible_container : std17::bool_constant
+<
+ is_container<C>::value
+ && is_compatible_element<C,E>::value
+>{};
+
+# else // ^^^ gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 500 ) ^^^ / vvv ! gsl_CPP11_140 || gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 500 ) vvv
+
+template<
+ class C, class E
+ , typename = typename std::enable_if<
+ ! is_span< C >::value
+ && ! is_array< C >::value
+ && ! is_std_array< C >::value
+ && ( std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >::value)
+ // && has_size_and_data< C >::value
+ , enabler>::type
+ , class = decltype( std17::size(std::declval<C>()) )
+ , class = decltype( std17::data(std::declval<C>()) )
+>
+# if gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+// VS2013 has insufficient support for expression SFINAE; we cannot make `is_compatible_container<>` a proper type trait here
+struct is_compatible_container : std::true_type { };
+# else
+struct is_compatible_container_r { is_compatible_container_r(int); };
+template< class C, class E >
+std::true_type is_compatible_container_f( is_compatible_container_r<C, E> );
+template< class C, class E >
+std::false_type is_compatible_container_f( ... );
+
+template< class C, class E >
+struct is_compatible_container : decltype( is_compatible_container_f< C, E >( 0 ) ) { };
+# endif // gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+
+# endif // gsl_CPP11_140 && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 1, 500 )
+
+#endif // gsl_HAVE( TYPE_TRAITS )
+
+} // namespace detail
+
+//
+// GSL.util: utilities
+//
+
+// Integer type for indices (e.g. in a loop).
+typedef gsl_CONFIG_INDEX_TYPE index;
+
+// Integer type for dimensions.
+typedef gsl_CONFIG_INDEX_TYPE dim;
+
+// Integer type for array strides.
+typedef gsl_CONFIG_INDEX_TYPE stride;
+
+// Integer type for pointer, iterator, or index differences.
+typedef gsl_CONFIG_INDEX_TYPE diff;
+
+//
+// GSL.owner: ownership pointers
+//
+#if gsl_HAVE( SHARED_PTR )
+ using std::unique_ptr;
+ using std::shared_ptr;
+ using std::make_shared;
+# if gsl_HAVE( MAKE_UNIQUE ) || gsl_HAVE( VARIADIC_TEMPLATE )
+ using std14::make_unique;
+# endif
+#endif
+
+#if gsl_HAVE( ALIAS_TEMPLATE )
+ template< class T
+#if gsl_HAVE( TYPE_TRAITS )
+ , typename = typename std::enable_if< std::is_pointer<T>::value >::type
+#endif
+ >
+ using owner = T;
+#elif gsl_CONFIG( DEFAULTS_VERSION ) == 0
+ // TODO vNext: remove
+ template< class T > struct owner { typedef T type; };
+#endif
+
+#define gsl_HAVE_OWNER_TEMPLATE gsl_HAVE_ALIAS_TEMPLATE
+#define gsl_HAVE_OWNER_TEMPLATE_() gsl_HAVE_OWNER_TEMPLATE
+
+// TODO vNext: remove
+#if gsl_FEATURE( OWNER_MACRO )
+# if gsl_HAVE( OWNER_TEMPLATE )
+# define Owner(t) ::gsl::owner<t>
+# else
+# define Owner(t) ::gsl::owner<t>::type
+# endif
+#endif
+
+//
+// GSL.assert: assertions
+//
+
+#if gsl_HAVE( TYPE_TRAITS )
+# define gsl_ELIDE_( x ) static_assert( ::std::is_constructible<bool, decltype( x )>::value, "argument of contract check must be convertible to bool" )
+#else
+# define gsl_ELIDE_( x )
+#endif
+#define gsl_NO_OP_() ( static_cast<void>( 0 ) )
+
+#if defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+# if defined( __CUDACC__ ) && defined( __CUDA_ARCH__ )
+# if gsl_COMPILER_NVCC_VERSION >= 113
+# define gsl_ASSUME_( x ) ( ( x ) ? static_cast<void>(0) : __builtin_unreachable() )
+# define gsl_ASSUME_UNREACHABLE_() __builtin_unreachable()
+# else
+# define gsl_ASSUME_( x ) gsl_ELIDE_( x ) /* there is no assume intrinsic in CUDA device code */
+# define gsl_ASSUME_UNREACHABLE_() gsl_NO_OP_() /* there is no assume intrinsic in CUDA device code */
+# endif
+# elif gsl_COMPILER_MSVC_VERSION >= 140
+# define gsl_ASSUME_( x ) __assume( x )
+# define gsl_ASSUME_UNREACHABLE_() __assume( 0 )
+# elif gsl_COMPILER_GNUC_VERSION
+# define gsl_ASSUME_( x ) ( ( x ) ? static_cast<void>(0) : __builtin_unreachable() )
+# define gsl_ASSUME_UNREACHABLE_() __builtin_unreachable()
+# elif defined(__has_builtin)
+# if __has_builtin(__builtin_unreachable)
+# define gsl_ASSUME_( x ) ( ( x ) ? static_cast<void>(0) : __builtin_unreachable() )
+# define gsl_ASSUME_UNREACHABLE_() __builtin_unreachable()
+# else
+# error gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME: gsl-lite does not know how to generate UB optimization hints for this compiler; use gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE instead
+# endif
+# else
+# error gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME: gsl-lite does not know how to generate UB optimization hints for this compiler; use gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE instead
+# endif
+#endif // defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+
+#if defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ASSUME )
+# define gsl_CONTRACT_UNENFORCED_( x ) gsl_ASSUME_( x )
+#else // defined( gsl_CONFIG_UNENFORCED_CONTRACTS_ELIDE ) [default]
+# define gsl_CONTRACT_UNENFORCED_( x ) gsl_ELIDE_( x )
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+# if defined( __CUDACC__ ) && defined( __CUDA_ARCH__ )
+# define gsl_TRAP_() __trap()
+# elif gsl_COMPILER_MSVC_VERSION >= 110 // __fastfail() supported by VS 2012 and later
+# define gsl_TRAP_() __fastfail( 0 ) /* legacy failure code for buffer-overrun errors, cf. winnt.h, "Fast fail failure codes" */
+# elif gsl_COMPILER_GNUC_VERSION
+# define gsl_TRAP_() __builtin_trap()
+# elif defined(__has_builtin)
+# if __has_builtin(__builtin_trap)
+# define gsl_TRAP_() __builtin_trap()
+# else
+# error gsl_CONFIG_CONTRACT_VIOLATION_TRAPS: gsl-lite does not know how to generate a trap instruction for this compiler; use gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES instead
+# endif
+# else
+# error gsl_CONFIG_CONTRACT_VIOLATION_TRAPS: gsl-lite does not know how to generate a trap instruction for this compiler; use gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES instead
+# endif
+#endif // defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+# define gsl_CONTRACT_CHECK_( str, x ) ( ( x ) ? static_cast<void>(0) : ::gsl::fail_fast_assert_handler( #x, str, __FILE__, __LINE__ ) )
+# if defined( __CUDACC__ ) && defined( __CUDA_ARCH__ )
+# define gsl_FAILFAST_() ( ::gsl::fail_fast_assert_handler( "", "GSL: failure", __FILE__, __LINE__ ), gsl_TRAP_() ) /* do not let the custom assertion handler continue execution */
+# else
+# define gsl_FAILFAST_() ( ::gsl::fail_fast_assert_handler( "", "GSL: failure", __FILE__, __LINE__ ), ::gsl::detail::fail_fast_terminate() ) /* do not let the custom assertion handler continue execution */
+# endif
+#elif defined( __CUDACC__ ) && defined( __CUDA_ARCH__ )
+# if defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS ) || ! defined( NDEBUG )
+# define gsl_CONTRACT_CHECK_( str, x ) assert( str && ( x ) )
+# else
+# define gsl_CONTRACT_CHECK_( str, x ) ( ( x ) ? static_cast<void>(0) : __trap() )
+#endif
+# define gsl_FAILFAST_() ( __trap() )
+#elif defined( gsl_CONFIG_CONTRACT_VIOLATION_ASSERTS )
+# define gsl_CONTRACT_CHECK_( str, x ) assert( str && ( x ) )
+# if ! defined( NDEBUG )
+# define gsl_FAILFAST_() ( assert( ! "GSL: failure" ), ::gsl::detail::fail_fast_terminate() )
+# else
+# define gsl_FAILFAST_() ( ::gsl::detail::fail_fast_terminate() )
+# endif
+#elif defined( gsl_CONFIG_CONTRACT_VIOLATION_TRAPS )
+# define gsl_CONTRACT_CHECK_( str, x ) ( ( x ) ? static_cast<void>(0) : gsl_TRAP_() )
+# if gsl_COMPILER_MSVC_VERSION
+# define gsl_FAILFAST_() ( gsl_TRAP_(), ::gsl::detail::fail_fast_terminate() )
+# else
+# define gsl_FAILFAST_() ( gsl_TRAP_() )
+# endif
+#elif defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS )
+# define gsl_CONTRACT_CHECK_( str, x ) ( ( x ) ? static_cast<void>(0) : ::gsl::detail::fail_fast_throw( str ": '" #x "' at " __FILE__ ":" gsl_STRINGIFY(__LINE__) ) )
+# define gsl_FAILFAST_() ( ::gsl::detail::fail_fast_throw( "GSL: failure at " __FILE__ ":" gsl_STRINGIFY(__LINE__) ) )
+#else // defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) [default]
+# define gsl_CONTRACT_CHECK_( str, x ) ( ( x ) ? static_cast<void>(0) : ::gsl::detail::fail_fast_terminate() )
+# define gsl_FAILFAST_() ( ::gsl::detail::fail_fast_terminate() )
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_OFF ) || defined( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# define gsl_Expects( x ) gsl_CONTRACT_UNENFORCED_( x )
+#else
+# define gsl_Expects( x ) gsl_CONTRACT_CHECK_( "GSL: Precondition failure", x )
+#endif
+#define Expects( x ) gsl_Expects( x )
+#if !defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT ) || defined( gsl_CONFIG_CONTRACT_CHECKING_EXPECTS_OFF )
+# define gsl_ExpectsAudit( x ) gsl_ELIDE_( x )
+#else
+# define gsl_ExpectsAudit( x ) gsl_CONTRACT_CHECK_( "GSL: Precondition failure (audit)", x )
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_OFF ) || defined( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# define gsl_Ensures( x ) gsl_CONTRACT_UNENFORCED_( x )
+#else
+# define gsl_Ensures( x ) gsl_CONTRACT_CHECK_( "GSL: Postcondition failure", x )
+#endif
+#define Ensures( x ) gsl_Ensures( x )
+#if !defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT ) || defined( gsl_CONFIG_CONTRACT_CHECKING_ENSURES_OFF )
+# define gsl_EnsuresAudit( x ) gsl_ELIDE_( x )
+#else
+# define gsl_EnsuresAudit( x ) gsl_CONTRACT_CHECK_( "GSL: Postcondition failure (audit)", x )
+#endif
+
+#if defined( gsl_CONFIG_CONTRACT_CHECKING_OFF ) || defined( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# define gsl_Assert( x ) gsl_CONTRACT_UNENFORCED_( x )
+#else
+# define gsl_Assert( x ) gsl_CONTRACT_CHECK_( "GSL: Assertion failure", x )
+#endif
+#if !defined( gsl_CONFIG_CONTRACT_CHECKING_AUDIT ) || defined( gsl_CONFIG_CONTRACT_CHECKING_ASSERT_OFF )
+# define gsl_AssertAudit( x ) gsl_ELIDE_( x )
+#else
+# define gsl_AssertAudit( x ) gsl_CONTRACT_CHECK_( "GSL: Assertion failure (audit)", x )
+#endif
+
+#define gsl_FailFast() gsl_FAILFAST_()
+
+
+struct fail_fast : public std::logic_error
+{
+ explicit fail_fast( char const * message )
+ : std::logic_error( message ) {}
+};
+
+namespace detail {
+
+
+#if gsl_HAVE( EXCEPTIONS )
+gsl_NORETURN inline void fail_fast_throw( char const * message )
+{
+ throw fail_fast( message );
+}
+#endif // gsl_HAVE( EXCEPTIONS )
+gsl_NORETURN inline void fail_fast_terminate() gsl_noexcept
+{
+ std::terminate();
+}
+
+} // namespace detail
+
+// Should be defined by user
+gsl_api void fail_fast_assert_handler( char const * const expression, char const * const message, char const * const file, int line );
+
+#if defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS )
+
+# if gsl_HAVE( EXCEPTIONS )
+gsl_DEPRECATED_MSG("don't call gsl::fail_fast_assert() directly; use contract checking macros instead")
+gsl_constexpr14 inline
+void fail_fast_assert( bool cond, char const * const message )
+{
+ if ( !cond )
+ throw fail_fast( message );
+}
+# endif // gsl_HAVE( EXCEPTIONS )
+
+#elif defined( gsl_CONFIG_CONTRACT_VIOLATION_CALLS_HANDLER )
+
+gsl_DEPRECATED_MSG("don't call gsl::fail_fast_assert() directly; use contract checking macros instead")
+gsl_api gsl_constexpr14 inline
+void fail_fast_assert( bool cond, char const * const expression, char const * const message, char const * const file, int line )
+{
+ if ( !cond )
+ ::gsl::fail_fast_assert_handler( expression, message, file, line );
+}
+
+#else // defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) [default]
+
+gsl_DEPRECATED_MSG("don't call gsl::fail_fast_assert() directly; use contract checking macros instead")
+gsl_constexpr14 inline
+void fail_fast_assert( bool cond ) gsl_noexcept
+{
+ if ( !cond )
+ std::terminate();
+}
+
+#endif
+
+
+//
+// GSL.util: utilities
+//
+
+#if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+// Add uncaught_exceptions for pre-2017 MSVC, GCC and Clang
+// Return unsigned char to save stack space, uncaught_exceptions can only increase by 1 in a scope
+
+namespace std11 {
+
+# if gsl_HAVE( UNCAUGHT_EXCEPTIONS )
+
+inline unsigned char uncaught_exceptions() gsl_noexcept
+{
+ return static_cast<unsigned char>( std::uncaught_exceptions() );
+}
+
+# else // ! gsl_HAVE( UNCAUGHT_EXCEPTIONS )
+# if defined( _MSC_VER ) // MS-STL with either MSVC or clang-cl
+
+inline unsigned char uncaught_exceptions() gsl_noexcept
+{
+ return static_cast<unsigned char>( *reinterpret_cast<unsigned const*>( detail::_getptd() + (sizeof(void *) == 8 ? 0x100 : 0x90 ) ) );
+}
+
+# elif gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_GNUC_VERSION || gsl_COMPILER_APPLECLANG_VERSION
+
+inline unsigned char uncaught_exceptions() gsl_noexcept
+{
+ return static_cast<unsigned char>( ( *reinterpret_cast<unsigned const *>( reinterpret_cast<unsigned char const *>(detail::__cxa_get_globals()) + sizeof(void *) ) ) );
+}
+
+# endif
+# endif
+
+} // namespace std11
+
+#endif // gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+#if gsl_STDLIB_CPP11_110
+
+gsl_DISABLE_MSVC_WARNINGS( 4702 ) // unreachable code
+
+template< class F >
+class final_action
+{
+public:
+ explicit final_action( F action ) gsl_noexcept
+ : action_( std::move( action ) )
+ , invoke_( true )
+ {}
+
+ final_action( final_action && other ) gsl_noexcept
+ : action_( std::move( other.action_ ) )
+ , invoke_( other.invoke_ )
+ {
+ other.invoke_ = false;
+ }
+
+ gsl_SUPPRESS_MSGSL_WARNING(f.6)
+ virtual ~final_action() gsl_noexcept
+ {
+ if ( invoke_ )
+ action_();
+ }
+
+gsl_is_delete_access:
+ final_action( final_action const & ) gsl_is_delete;
+ final_action & operator=( final_action const & ) gsl_is_delete;
+ final_action & operator=( final_action && ) gsl_is_delete;
+
+protected:
+ void dismiss() gsl_noexcept
+ {
+ invoke_ = false;
+ }
+
+private:
+ F action_;
+ bool invoke_;
+};
+
+template< class F >
+gsl_NODISCARD inline final_action<F>
+finally( F const & action ) gsl_noexcept
+{
+ return final_action<F>( action );
+}
+
+template< class F >
+gsl_NODISCARD inline final_action<F>
+finally( F && action ) gsl_noexcept
+{
+ return final_action<F>( std::forward<F>( action ) );
+}
+
+# if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+template< class F >
+class final_action_return : public final_action<F>
+{
+public:
+ explicit final_action_return( F && action ) gsl_noexcept
+ : final_action<F>( std::move( action ) )
+ , exception_count( std11::uncaught_exceptions() )
+ {}
+
+ final_action_return( final_action_return && other ) gsl_noexcept
+ : final_action<F>( std::move( other ) )
+ , exception_count( std11::uncaught_exceptions() )
+ {}
+
+ ~final_action_return() override
+ {
+ if ( std11::uncaught_exceptions() != exception_count )
+ this->dismiss();
+ }
+
+gsl_is_delete_access:
+ final_action_return( final_action_return const & ) gsl_is_delete;
+ final_action_return & operator=( final_action_return const & ) gsl_is_delete;
+
+private:
+ unsigned char exception_count;
+};
+
+template< class F >
+gsl_NODISCARD inline final_action_return<F>
+on_return( F const & action ) gsl_noexcept
+{
+ return final_action_return<F>( action );
+}
+
+template< class F >
+gsl_NODISCARD inline final_action_return<F>
+on_return( F && action ) gsl_noexcept
+{
+ return final_action_return<F>( std::forward<F>( action ) );
+}
+
+template< class F >
+class final_action_error : public final_action<F>
+{
+public:
+ explicit final_action_error( F && action ) gsl_noexcept
+ : final_action<F>( std::move( action ) )
+ , exception_count( std11::uncaught_exceptions() )
+ {}
+
+ final_action_error( final_action_error && other ) gsl_noexcept
+ : final_action<F>( std::move( other ) )
+ , exception_count( std11::uncaught_exceptions() )
+ {}
+
+ ~final_action_error() override
+ {
+ if ( std11::uncaught_exceptions() == exception_count )
+ this->dismiss();
+ }
+
+gsl_is_delete_access:
+ final_action_error( final_action_error const & ) gsl_is_delete;
+ final_action_error & operator=( final_action_error const & ) gsl_is_delete;
+
+private:
+ unsigned char exception_count;
+};
+
+template< class F >
+gsl_NODISCARD inline final_action_error<F>
+on_error( F const & action ) gsl_noexcept
+{
+ return final_action_error<F>( action );
+}
+
+template< class F >
+gsl_NODISCARD inline final_action_error<F>
+on_error( F && action ) gsl_noexcept
+{
+ return final_action_error<F>( std::forward<F>( action ) );
+}
+
+# endif // gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+gsl_RESTORE_MSVC_WARNINGS()
+
+#else // ! gsl_STDLIB_CPP11_110
+
+class final_action
+{
+public:
+ typedef void (*Action)();
+
+ final_action( Action action )
+ : action_( action )
+ , invoke_( true )
+ {}
+
+ final_action( final_action const & other )
+ : action_( other.action_ )
+ , invoke_( other.invoke_ )
+ {
+ other.invoke_ = false;
+ }
+
+ virtual ~final_action()
+ {
+ if ( invoke_ )
+ action_();
+ }
+
+protected:
+ void dismiss()
+ {
+ invoke_ = false;
+ }
+
+private:
+ final_action & operator=( final_action const & );
+
+private:
+ Action action_;
+ mutable bool invoke_;
+};
+
+template< class F >
+inline final_action finally( F const & f )
+{
+ return final_action(( f ));
+}
+
+#if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+class final_action_return : public final_action
+{
+public:
+ explicit final_action_return( Action action )
+ : final_action( action )
+ , exception_count( std11::uncaught_exceptions() )
+ {}
+
+ ~final_action_return()
+ {
+ if ( std11::uncaught_exceptions() != exception_count )
+ this->dismiss();
+ }
+
+private:
+ final_action_return & operator=( final_action_return const & );
+
+private:
+ unsigned char exception_count;
+};
+
+template< class F >
+inline final_action_return on_return( F const & action )
+{
+ return final_action_return( action );
+}
+
+class final_action_error : public final_action
+{
+public:
+ explicit final_action_error( Action action )
+ : final_action( action )
+ , exception_count( std11::uncaught_exceptions() )
+ {}
+
+ ~final_action_error()
+ {
+ if ( std11::uncaught_exceptions() == exception_count )
+ this->dismiss();
+ }
+
+private:
+ final_action_error & operator=( final_action_error const & );
+
+private:
+ unsigned char exception_count;
+};
+
+template< class F >
+inline final_action_error on_error( F const & action )
+{
+ return final_action_error( action );
+}
+
+# endif // gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+#endif // gsl_STDLIB_CPP11_110
+
+#if gsl_STDLIB_CPP11_120
+
+template< class T, class U >
+gsl_NODISCARD gsl_api inline gsl_constexpr T
+narrow_cast( U && u ) gsl_noexcept
+{
+ return static_cast<T>( std::forward<U>( u ) );
+}
+
+#else // ! gsl_STDLIB_CPP11_120
+
+template< class T, class U >
+gsl_api inline T
+narrow_cast( U u ) gsl_noexcept
+{
+ return static_cast<T>( u );
+}
+
+#endif // gsl_STDLIB_CPP11_120
+
+struct narrowing_error : public std::exception
+{
+ char const * what() const gsl_noexcept
+#if gsl_HAVE( OVERRIDE_FINAL )
+ override
+#endif
+ {
+ return "narrowing_error";
+ }
+};
+
+#if gsl_HAVE( TYPE_TRAITS )
+
+namespace detail {
+
+ template< class T, class U >
+ struct is_same_signedness : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value> {};
+
+# if gsl_COMPILER_NVCC_VERSION
+ // We do this to circumvent NVCC warnings about pointless unsigned comparisons with 0.
+ template< class T >
+ gsl_constexpr gsl_api bool is_negative( T value, std::true_type /*isSigned*/ ) gsl_noexcept
+ {
+ return value < T();
+ }
+ template< class T >
+ gsl_constexpr gsl_api bool is_negative( T /*value*/, std::false_type /*isUnsigned*/ ) gsl_noexcept
+ {
+ return false;
+ }
+ template< class T, class U >
+ gsl_constexpr gsl_api bool have_same_sign( T, U, std::true_type /*isSameSignedness*/ ) gsl_noexcept
+ {
+ return true;
+ }
+ template< class T, class U >
+ gsl_constexpr gsl_api bool have_same_sign( T t, U u, std::false_type /*isSameSignedness*/ ) gsl_noexcept
+ {
+ return detail::is_negative( t, std::is_signed<T>() ) == detail::is_negative( u, std::is_signed<U>() );
+ }
+# endif // gsl_COMPILER_NVCC_VERSION
+
+} // namespace detail
+
+#endif
+
+template< class T, class U >
+gsl_NODISCARD
+#if !gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION ) && !defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS )
+gsl_api
+#endif
+inline T
+narrow( U u )
+{
+#if gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION ) && ! gsl_HAVE( EXCEPTIONS )
+ gsl_STATIC_ASSERT_( detail::dependent_false< T >::value,
+ "According to the GSL specification, narrow<>() throws an exception of type narrowing_error on truncation. Therefore "
+ "it cannot be used if exceptions are disabled. Consider using narrow_failfast<>() instead which raises a precondition "
+ "violation if the given value cannot be represented in the target type." );
+#endif
+
+ T t = static_cast<T>( u );
+
+ if ( static_cast<U>( t ) != u )
+ {
+#if gsl_HAVE( EXCEPTIONS ) && ( gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION ) || defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) )
+ throw narrowing_error();
+#else
+ std::terminate();
+#endif
+ }
+
+#if gsl_HAVE( TYPE_TRAITS )
+# if gsl_COMPILER_NVCC_VERSION
+ if ( ! detail::have_same_sign( t, u, detail::is_same_signedness<T, U>() ) )
+# else
+ gsl_SUPPRESS_MSVC_WARNING( 4127, "conditional expression is constant" )
+ if ( ! detail::is_same_signedness<T, U>::value && ( t < T() ) != ( u < U() ) )
+# endif
+#else
+ // Don't assume T() works:
+ gsl_SUPPRESS_MSVC_WARNING( 4127, "conditional expression is constant" )
+ if ( ( t < 0 ) != ( u < 0 ) )
+#endif
+ {
+#if gsl_HAVE( EXCEPTIONS ) && ( gsl_CONFIG( NARROW_THROWS_ON_TRUNCATION ) || defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) )
+ throw narrowing_error();
+#else
+ std::terminate();
+#endif
+ }
+
+ return t;
+}
+
+template< class T, class U >
+gsl_NODISCARD gsl_api inline T
+narrow_failfast( U u )
+{
+ T t = static_cast<T>( u );
+
+ gsl_Expects( static_cast<U>( t ) == u );
+
+#if gsl_HAVE( TYPE_TRAITS )
+# if gsl_COMPILER_NVCC_VERSION
+ gsl_Expects( ::gsl::detail::have_same_sign( t, u, ::gsl::detail::is_same_signedness<T, U>() ) );
+# else
+ gsl_SUPPRESS_MSVC_WARNING( 4127, "conditional expression is constant" )
+ gsl_Expects( ( ::gsl::detail::is_same_signedness<T, U>::value || ( t < T() ) == ( u < U() ) ) );
+# endif
+#else
+ // Don't assume T() works:
+ gsl_SUPPRESS_MSVC_WARNING( 4127, "conditional expression is constant" )
+ gsl_Expects( ( t < 0 ) == ( u < 0 ) );
+#endif
+
+ return t;
+}
+
+
+//
+// at() - Bounds-checked way of accessing static arrays, std::array, std::vector.
+//
+
+template< class T, size_t N >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 T &
+at( T(&arr)[N], size_t pos )
+{
+ gsl_Expects( pos < N );
+ return arr[pos];
+}
+
+template< class Container >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 typename Container::value_type &
+at( Container & cont, size_t pos )
+{
+ gsl_Expects( pos < cont.size() );
+ return cont[pos];
+}
+
+template< class Container >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 typename Container::value_type const &
+at( Container const & cont, size_t pos )
+{
+ gsl_Expects( pos < cont.size() );
+ return cont[pos];
+}
+
+#if gsl_HAVE( INITIALIZER_LIST )
+
+template< class T >
+gsl_NODISCARD gsl_api inline const gsl_constexpr14 T
+at( std::initializer_list<T> cont, size_t pos )
+{
+ gsl_Expects( pos < cont.size() );
+ return *( cont.begin() + pos );
+}
+#endif
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 T &
+at( span<T> s, size_t pos )
+{
+ return s[ pos ];
+}
+
+//
+// GSL.views: views
+//
+
+//
+// not_null<> - Wrap any indirection and enforce non-null.
+//
+
+template< class T >
+class not_null;
+
+namespace detail {
+
+// helper class to figure out the pointed-to type of a pointer
+#if gsl_STDLIB_CPP11_OR_GREATER
+template< class T, class E = void >
+struct element_type_helper
+{
+ // For types without a member element_type (this will handle raw pointers)
+ typedef typename std::remove_reference< decltype( *std::declval<T>() ) >::type type;
+};
+
+template< class T >
+struct element_type_helper< T, std17::void_t< typename T::element_type > >
+{
+ // For types with a member element_type
+ typedef typename T::element_type type;
+};
+#else // ! gsl_STDLIB_CPP11_OR_GREATER
+// Pre-C++11, we cannot have decltype, so we cannot handle types without a member element_type
+template< class T, class E = void >
+struct element_type_helper
+{
+ typedef typename T::element_type type;
+};
+
+template< class T >
+struct element_type_helper< T* >
+{
+ typedef T type;
+};
+#endif // gsl_STDLIB_CPP11_OR_GREATER
+
+template< class T >
+struct is_not_null_or_bool_oracle : std11::false_type { };
+template< class T >
+struct is_not_null_or_bool_oracle< not_null<T> > : std11::true_type { };
+template<>
+struct is_not_null_or_bool_oracle< bool > : std11::true_type { };
+
+
+template< class T, bool IsCopyable = true >
+struct not_null_data;
+#if gsl_HAVE( MOVE_FORWARD )
+template< class T >
+struct not_null_data< T, false >
+{
+ T ptr_;
+
+ gsl_api gsl_constexpr14 not_null_data( T && _ptr ) gsl_noexcept
+ : ptr_( std::move( _ptr ) )
+ {
+ }
+
+ gsl_api gsl_constexpr14 not_null_data( not_null_data && other ) gsl_noexcept
+ : ptr_( std::move( other.ptr_ ) )
+ {
+ }
+ gsl_api gsl_constexpr14 not_null_data & operator=( not_null_data && other ) gsl_noexcept
+ {
+ ptr_ = std::move( other.ptr_ );
+ return *this;
+ }
+
+gsl_is_delete_access:
+ not_null_data( not_null_data const & ) gsl_is_delete;
+ not_null_data & operator=( not_null_data const & ) gsl_is_delete;
+};
+# if gsl_CONFIG_DEFAULTS_VERSION >= 1
+# endif // gsl_CONFIG_DEFAULTS_VERSION >= 1
+#endif // gsl_HAVE( MOVE_FORWARD )
+template< class T >
+struct not_null_data< T, true >
+{
+ T ptr_;
+
+ gsl_api gsl_constexpr14 not_null_data( T const & _ptr ) gsl_noexcept
+ : ptr_( _ptr )
+ {
+ }
+
+#if gsl_HAVE( MOVE_FORWARD )
+ gsl_api gsl_constexpr14 not_null_data( T && _ptr ) gsl_noexcept
+ : ptr_( std::move( _ptr ) )
+ {
+ }
+
+ gsl_api gsl_constexpr14 not_null_data( not_null_data && other ) gsl_noexcept
+ : ptr_( std::move( other.ptr_ ) )
+ {
+ }
+ gsl_api gsl_constexpr14 not_null_data & operator=( not_null_data && other ) gsl_noexcept
+ {
+ ptr_ = std::move( other.ptr_ );
+ return *this;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+ gsl_api gsl_constexpr14 not_null_data( not_null_data const & other )
+ : ptr_( other.ptr_ )
+ {
+ gsl_Expects( ptr_ != gsl_nullptr );
+ }
+ gsl_api gsl_constexpr14 not_null_data & operator=( not_null_data const & other )
+ {
+ gsl_Expects( other.ptr_ != gsl_nullptr );
+ ptr_ = other.ptr_;
+ return *this;
+ }
+};
+#if gsl_CONFIG_DEFAULTS_VERSION >= 1
+template< class T >
+struct not_null_data< T *, true >
+{
+ T * ptr_;
+
+ gsl_api gsl_constexpr14 not_null_data( T * _ptr ) gsl_noexcept
+ : ptr_( _ptr )
+ {
+ }
+};
+#endif // gsl_CONFIG_DEFAULTS_VERSION >= 1
+template< class T >
+struct is_copyable
+#if gsl_HAVE( TYPE_TRAITS )
+: std11::integral_constant< bool, std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value >
+#else
+: std11::true_type
+#endif
+{
+};
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( UNIQUE_PTR ) && gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 140 )
+// Type traits are buggy in VC++ 2013, so we explicitly declare `unique_ptr<>` non-copyable.
+template< class T, class Deleter >
+struct is_copyable< std::unique_ptr< T, Deleter > > : std11::false_type
+{
+};
+#endif
+
+template< class T >
+struct not_null_accessor;
+
+} // namespace detail
+
+template< class T >
+class not_null
+{
+private:
+ detail::not_null_data< T, detail::is_copyable< T >::value > data_;
+
+ // need to access `not_null<U>::data_`
+ template< class U >
+ friend class not_null;
+
+ template< class U >
+ friend struct detail::not_null_accessor;
+
+public:
+ typedef typename detail::element_type_helper<T>::type element_type;
+
+#if gsl_HAVE( TYPE_TRAITS )
+ static_assert( std::is_assignable<typename std::remove_const<typename std::remove_reference<T>::type>::type&, std::nullptr_t>::value, "T cannot be assigned nullptr." );
+#endif
+
+#if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+# if gsl_HAVE( MOVE_FORWARD )
+ template< class U
+ // In Clang 3.x, `is_constructible<not_null<unique_ptr<X>>, unique_ptr<X>>` tries to instantiate the copy constructor of `unique_ptr<>`, triggering an error.
+ // Note that Apple Clang's `__clang_major__` etc. are different from regular Clang.
+# if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<T, U>::value ), int >::type = 0
+# endif
+ >
+ gsl_api gsl_constexpr14 explicit not_null( U other )
+ : data_( T( std::move( other ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+ template< class U >
+ gsl_api gsl_constexpr14 explicit not_null( U const& other )
+ : data_( T( other ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# endif // gsl_HAVE( MOVE_FORWARD )
+#else // a.k.a. !gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+# if gsl_HAVE( MOVE_FORWARD )
+ // In Clang 3.x, `is_constructible<not_null<unique_ptr<X>>, unique_ptr<X>>` tries to instantiate the copy constructor of `unique_ptr<>`, triggering an error.
+ // Note that Apple Clang's `__clang_major__` etc. are different from regular Clang.
+# if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<T, U>::value && !std::is_convertible<U, T>::value ), int >::type = 0
+ >
+ gsl_api gsl_constexpr14 explicit not_null( U other )
+ : data_( T( std::move( other ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_convertible<U, T>::value ), int >::type = 0
+ >
+ gsl_api gsl_constexpr14 not_null( U other )
+ : data_( std::move( other ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# else // a.k.a. !( gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ // If type_traits are not available, then we can't distinguish `is_convertible<>` and `is_constructible<>`, so we unconditionally permit implicit construction.
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( U other )
+ : data_( T( std::move( other ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+# else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( U const& other )
+ : data_( T( other ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# endif // gsl_HAVE( MOVE_FORWARD )
+#endif // gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+
+public:
+#if gsl_HAVE( MOVE_FORWARD )
+ // In Clang 3.x, `is_constructible<not_null<unique_ptr<X>>, unique_ptr<X>>` tries to instantiate the copy constructor of `unique_ptr<>`, triggering an error.
+ // Note that Apple Clang's `__clang_major__` etc. are different from regular Clang.
+# if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<T, U>::value && !std::is_convertible<U, T>::value ), int >::type = 0
+ >
+ gsl_api gsl_constexpr14 explicit not_null( not_null<U> other )
+ : data_( T( std::move( other.data_.ptr_ ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_convertible<U, T>::value ), int >::type = 0
+ >
+ gsl_api gsl_constexpr14 not_null( not_null<U> other )
+ : data_( T( std::move( other.data_.ptr_ ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# else // a.k.a. ! ( gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ // If type_traits are not available, then we can't distinguish `is_convertible<>` and `is_constructible<>`, so we unconditionally permit implicit construction.
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( not_null<U> other )
+ : data_( T( std::move( other.data_.ptr_ ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+ template< class U >
+ gsl_api gsl_constexpr14 not_null<T>& operator=( not_null<U> other )
+ {
+ gsl_Expects( other.data_.ptr_ != gsl_nullptr );
+ data_.ptr_ = std::move( other.data_.ptr_ );
+ return *this;
+ }
+# endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+#else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( not_null<U> const& other )
+ : data_( T( other.data_.ptr_ ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+ template< class U >
+ gsl_api gsl_constexpr14 not_null<T>& operator=( not_null<U> const & other )
+ {
+ gsl_Expects( other.data_.ptr_ != gsl_nullptr );
+ data_.ptr_ = other.data_.ptr_;
+ return *this;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+#if gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ gsl_NODISCARD gsl_api gsl_constexpr14 element_type *
+ get() const
+ {
+ element_type * result = data_.ptr_.get();
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+#else
+# if gsl_CONFIG( NOT_NULL_GET_BY_CONST_REF )
+ gsl_NODISCARD gsl_api gsl_constexpr14 T const &
+ get() const
+ {
+ T const & result = data_.ptr_;
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+# else
+ gsl_NODISCARD gsl_api gsl_constexpr14 T
+ get() const
+ {
+ T result = data_.ptr_;
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+# endif
+#endif
+
+ // We want an implicit conversion operator that can be used to convert from both lvalues (by
+ // const reference or by copy) and rvalues (by move). So it seems like we could define
+ //
+ // template< class U >
+ // operator U const &() const & { ... }
+ // template< class U >
+ // operator U &&() && { ... }
+ //
+ // However, having two conversion operators with different return types renders the assignment
+ // operator of the result type ambiguous:
+ //
+ // not_null<std::unique_ptr<T>> p( ... );
+ // std::unique_ptr<U> q;
+ // q = std::move( p ); // ambiguous
+ //
+ // To avoid this ambiguity, we have both overloads of the conversion operator return `U`
+ // rather than `U const &` or `U &&`. This implies that converting an lvalue always induces
+ // a copy, which can cause unnecessary copies or even fail to compile in some situations:
+ //
+ // not_null<std::shared_ptr<T>> sp( ... );
+ // std::shared_ptr<U> const & rs = sp; // unnecessary copy
+ // std::unique_ptr<U> const & ru = p; // error: cannot copy `unique_ptr<T>`
+ //
+ // However, these situations are rather unusual, and the following, more frequent situations
+ // remain unimpaired:
+ //
+ // std::shared_ptr<U> vs = sp; // no extra copy
+ // std::unique_ptr<U> vu = std::move( p );
+
+#if gsl_HAVE( MOVE_FORWARD ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT )
+ // explicit conversion operator
+
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<U, T const &>::value && !std::is_convertible<T, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ), int >::type = 0
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14 explicit
+ operator U() const
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ &
+# endif
+ {
+ U result( data_.ptr_ );
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<U, T>::value && !std::is_convertible<T, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ), int >::type = 0
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14 explicit
+ operator U() &&
+ {
+ U result( std::move( data_.ptr_ ) );
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+# endif
+
+ // implicit conversion operator
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<U, T const &>::value && std::is_convertible<T, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ), int >::type = 0
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ operator U() const
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ &
+# endif
+ {
+ U result( data_.ptr_ );
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+# if gsl_HAVE( FUNCTION_REF_QUALIFIER )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_convertible<T, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ), int >::type = 0
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ operator U() &&
+ {
+ U result( std::move( data_.ptr_ ) );
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+# endif
+#else // a.k.a. #if !( gsl_HAVE( MOVE_FORWARD ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT ) )
+ template< class U >
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ operator U() const
+ {
+ U result( data_.ptr_ );
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT )
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 T const &
+ operator->() const
+ {
+ T const & result( data_.ptr_ );
+ gsl_Ensures( result != gsl_nullptr );
+ return result;
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 element_type &
+ operator*() const
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ return *data_.ptr_;
+ }
+
+#if gsl_HAVE( MOVE_FORWARD )
+ // Visual C++ 2013 doesn't generate default move constructors, so we declare them explicitly.
+ gsl_api gsl_constexpr14 not_null( not_null && other )
+ gsl_noexcept_not_testing // we want to be nothrow-movable despite the precondition check
+ : data_( std::move( other.data_ ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+ gsl_api gsl_constexpr14 not_null & operator=( not_null && other )
+ gsl_noexcept_not_testing // we want to be nothrow-movable despite the precondition check
+ {
+ gsl_Expects( other.data_.ptr_ != gsl_nullptr || &other == this );
+ data_ = std::move( other.data_ );
+ return *this;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr14 not_null( not_null const & ) = default;
+ gsl_constexpr14 not_null & operator=( not_null const & ) = default;
+#endif
+
+ gsl_api gsl_constexpr20 friend void swap( not_null & lhs, not_null & rhs )
+ gsl_noexcept_not_testing // we want to be nothrow-swappable despite the precondition check
+ {
+ gsl_Expects( lhs.data_.ptr_ != gsl_nullptr && rhs.data_.ptr_ != gsl_nullptr );
+ using std::swap;
+ swap( lhs.data_.ptr_, rhs.data_.ptr_ );
+ }
+
+gsl_is_delete_access:
+ not_null() gsl_is_delete;
+ // prevent compilation when initialized with a nullptr or literal 0:
+#if gsl_HAVE( NULLPTR )
+ not_null( std::nullptr_t ) gsl_is_delete;
+ not_null & operator=( std::nullptr_t ) gsl_is_delete;
+#else
+ not_null( int ) gsl_is_delete;
+ not_null & operator=( int ) gsl_is_delete;
+#endif
+
+ // unwanted operators...pointers only point to single objects!
+ not_null & operator++() gsl_is_delete;
+ not_null & operator--() gsl_is_delete;
+ not_null operator++( int ) gsl_is_delete;
+ not_null operator--( int ) gsl_is_delete;
+ not_null & operator+ ( size_t ) gsl_is_delete;
+ not_null & operator+=( size_t ) gsl_is_delete;
+ not_null & operator- ( size_t ) gsl_is_delete;
+ not_null & operator-=( size_t ) gsl_is_delete;
+ not_null & operator+=( std::ptrdiff_t ) gsl_is_delete;
+ not_null & operator-=( std::ptrdiff_t ) gsl_is_delete;
+ void operator[]( std::ptrdiff_t ) const gsl_is_delete;
+};
+#if gsl_CONFIG_DEFAULTS_VERSION >= 1
+template< class T >
+class not_null< T * >
+{
+private:
+ detail::not_null_data<T *, true> data_;
+
+ // need to access `not_null<U>::data_`
+ template< class U >
+ friend class not_null;
+
+ template< class U >
+ friend struct detail::not_null_accessor;
+
+public:
+ typedef T element_type;
+
+ gsl_api gsl_constexpr14
+#if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+ explicit
+#endif // gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR )
+ not_null( T * other )
+ : data_( other )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+
+#if gsl_HAVE( MOVE_FORWARD )
+ // In Clang 3.x, `is_constructible<not_null<unique_ptr<X>>, unique_ptr<X>>` tries to instantiate the copy constructor of `unique_ptr<>`, triggering an error.
+ // Note that Apple Clang's `__clang_major__` etc. are different from regular Clang.
+# if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<T*, U>::value && !std::is_convertible<U, T*>::value ), int >::type = 0
+ >
+ gsl_api gsl_constexpr14 explicit not_null( not_null<U> other )
+ : data_( static_cast<T*>( std::move( other.data_.ptr_ ) ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_convertible<U, T*>::value ), int >::type = 0
+ >
+ gsl_api gsl_constexpr14 not_null( not_null<U> other )
+ : data_( std::move( other.data_.ptr_ ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+# else // a.k.a. ! ( gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+ // If type_traits are not available, then we can't distinguish `is_convertible<>` and `is_constructible<>`, so we unconditionally permit implicit construction.
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( not_null<U> other )
+ : data_( std::move( other.data_.ptr_ ) )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+ template< class U >
+ gsl_api gsl_constexpr14 not_null<T*>& operator=( not_null<U> other )
+ {
+ gsl_Expects( other.data_.ptr_ != gsl_nullptr );
+ data_.ptr_ = std::move( other.data_.ptr_ );
+ return *this;
+ }
+# endif // gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && ! gsl_BETWEEN( gsl_COMPILER_CLANG_VERSION, 1, 400 ) && ! gsl_BETWEEN( gsl_COMPILER_APPLECLANG_VERSION, 1, 1001 )
+#else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+ template< class U >
+ gsl_api gsl_constexpr14 not_null( not_null<U> const& other )
+ : data_( other.data_.ptr_ )
+ {
+ gsl_Expects( data_.ptr_ != gsl_nullptr );
+ }
+ template< class U >
+ gsl_api gsl_constexpr14 not_null<T*>& operator=( not_null<U> const & other )
+ {
+ gsl_Expects( other.data_.ptr_ != gsl_nullptr );
+ data_.ptr_ = other.data_.ptr_;
+ return *this;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+#if ! gsl_CONFIG( TRANSPARENT_NOT_NULL )
+ gsl_NODISCARD gsl_api gsl_constexpr14 T*
+ get() const
+ {
+ return data_.ptr_;
+ }
+#endif
+
+#if gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT )
+ // explicit conversion operator
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<U, T*>::value && !std::is_convertible<T*, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ), int >::type = 0
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14 explicit
+ operator U() const
+ {
+ return U( data_.ptr_ );
+ }
+
+ // implicit conversion operator
+ template< class U
+ // We *have* to use SFINAE with an NTTP arg here, otherwise the overload is ambiguous.
+ , typename std::enable_if< ( std::is_constructible<U, T*>::value && std::is_convertible<T*, U>::value && !detail::is_not_null_or_bool_oracle<U>::value ), int >::type = 0
+ >
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ operator U() const
+ {
+ return data_.ptr_;
+ }
+#else // a.k.a. #if !( gsl_HAVE( MOVE_FORWARD ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT ) )
+ template< class U >
+ gsl_NODISCARD gsl_api gsl_constexpr14
+ operator U() const
+ {
+ return data_.ptr_;
+ }
+#endif // gsl_HAVE( MOVE_FORWARD ) && gsl_HAVE( TYPE_TRAITS ) && gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) && gsl_HAVE( EXPLICIT )
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 T*
+ operator->() const
+ {
+ return data_.ptr_;
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 element_type &
+ operator*() const
+ {
+ return *data_.ptr_;
+ }
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr14 not_null( not_null const & ) = default;
+ gsl_constexpr14 not_null & operator=( not_null const & ) = default;
+#endif
+
+ gsl_api gsl_constexpr20 friend void swap( not_null & lhs, not_null & rhs ) gsl_noexcept
+ {
+ using std::swap;
+ swap( lhs.data_.ptr_, rhs.data_.ptr_ );
+ }
+
+gsl_is_delete_access:
+ not_null() gsl_is_delete;
+ // prevent compilation when initialized with a nullptr or literal 0:
+#if gsl_HAVE( NULLPTR )
+ not_null( std::nullptr_t ) gsl_is_delete;
+ not_null & operator=( std::nullptr_t ) gsl_is_delete;
+#else
+ not_null( int ) gsl_is_delete;
+ not_null & operator=( int ) gsl_is_delete;
+#endif
+
+ // unwanted operators...pointers only point to single objects!
+ not_null & operator++() gsl_is_delete;
+ not_null & operator--() gsl_is_delete;
+ not_null operator++( int ) gsl_is_delete;
+ not_null operator--( int ) gsl_is_delete;
+ not_null & operator+ ( size_t ) gsl_is_delete;
+ not_null & operator+=( size_t ) gsl_is_delete;
+ not_null & operator- ( size_t ) gsl_is_delete;
+ not_null & operator-=( size_t ) gsl_is_delete;
+ not_null & operator+=( std::ptrdiff_t ) gsl_is_delete;
+ not_null & operator-=( std::ptrdiff_t ) gsl_is_delete;
+ void operator[]( std::ptrdiff_t ) const gsl_is_delete;
+};
+#endif // gsl_CONFIG_DEFAULTS_VERSION >= 1
+#if gsl_HAVE( DEDUCTION_GUIDES )
+template< class U >
+not_null( U ) -> not_null<U>;
+template< class U >
+not_null( not_null<U> ) -> not_null<U>;
+#endif
+
+#if gsl_HAVE( NULLPTR )
+void make_not_null( std::nullptr_t ) gsl_is_delete;
+#endif // gsl_HAVE( NULLPTR )
+#if gsl_HAVE( MOVE_FORWARD )
+template< class U >
+gsl_NODISCARD gsl_api gsl_constexpr14 not_null<U>
+make_not_null( U u )
+{
+ return not_null<U>( std::move( u ) );
+}
+template< class U >
+gsl_NODISCARD gsl_api gsl_constexpr14 not_null<U>
+make_not_null( not_null<U> u )
+{
+ return std::move( u );
+}
+#else // a.k.a. ! gsl_HAVE( MOVE_FORWARD )
+template< class U >
+gsl_NODISCARD gsl_api not_null<U>
+make_not_null( U const & u )
+{
+ return not_null<U>( u );
+}
+template< class U >
+gsl_NODISCARD gsl_api not_null<U>
+make_not_null( not_null<U> const & u )
+{
+ return u;
+}
+#endif // gsl_HAVE( MOVE_FORWARD )
+
+namespace detail {
+
+template< class T >
+struct as_nullable_helper
+{
+ typedef T type;
+};
+template< class T >
+struct as_nullable_helper< not_null<T> >
+{
+};
+
+template< class T >
+struct not_null_accessor
+{
+#if gsl_HAVE( MOVE_FORWARD )
+ static gsl_api T get( not_null<T>&& p ) gsl_noexcept
+ {
+ return std::move( p.data_.ptr_ );
+ }
+#endif
+ static gsl_api T const & get( not_null<T> const & p ) gsl_noexcept
+ {
+ return p.data_.ptr_;
+ }
+};
+
+namespace no_adl {
+
+#if gsl_HAVE( MOVE_FORWARD )
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr auto as_nullable( T && p )
+gsl_noexcept_if( std::is_nothrow_move_constructible<T>::value )
+-> typename detail::as_nullable_helper<typename std20::remove_cvref<T>::type>::type
+{
+ return std::move( p );
+}
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr14 T as_nullable( not_null<T> && p )
+{
+ T result = detail::not_null_accessor<T>::get( std::move( p ) );
+ gsl_Expects( result != gsl_nullptr );
+ return result;
+}
+#else // ! gsl_HAVE( MOVE_FORWARD )
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr T const & as_nullable( T const & p ) gsl_noexcept
+{
+ return p;
+}
+#endif // gsl_HAVE( MOVE_FORWARD )
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr14 T const & as_nullable( not_null<T> const & p )
+{
+ T const & result = detail::not_null_accessor<T>::get( p );
+ gsl_Expects( result != gsl_nullptr );
+ return result;
+}
+template< class T >
+gsl_NODISCARD gsl_api gsl_constexpr T* as_nullable( not_null<T*> p ) gsl_noexcept
+{
+ return detail::not_null_accessor<T*>::get( p );
+}
+
+} // namespace no_adl
+} // namespace detail
+
+using namespace detail::no_adl;
+
+// not_null with implicit constructor, allowing copy-initialization:
+
+template< class T >
+class not_null_ic : public not_null<T>
+{
+public:
+ template< class U
+ gsl_ENABLE_IF_(( std::is_constructible<T, U>::value ))
+ >
+ gsl_api gsl_constexpr14
+#if gsl_HAVE( MOVE_FORWARD )
+ not_null_ic( U && u )
+ : not_null<T>( std::forward<U>( u ) )
+#else // ! gsl_HAVE( MOVE_FORWARD )
+ not_null_ic( U const & u )
+ : not_null<T>( u )
+#endif // gsl_HAVE( MOVE_FORWARD )
+ {}
+};
+
+// more not_null unwanted operators
+
+template< class T, class U >
+std::ptrdiff_t operator-( not_null<T> const &, not_null<U> const & ) gsl_is_delete;
+
+template< class T >
+not_null<T> operator-( not_null<T> const &, std::ptrdiff_t ) gsl_is_delete;
+
+template< class T >
+not_null<T> operator+( not_null<T> const &, std::ptrdiff_t ) gsl_is_delete;
+
+template< class T >
+not_null<T> operator+( std::ptrdiff_t, not_null<T> const & ) gsl_is_delete;
+
+// not_null comparisons
+
+#if gsl_HAVE( NULLPTR ) && gsl_HAVE( IS_DELETE )
+template< class T >
+gsl_constexpr bool
+operator==( not_null<T> const &, std::nullptr_t ) = delete;
+template< class T >
+gsl_constexpr bool
+operator==( std::nullptr_t , not_null<T> const & ) = delete;
+template< class T >
+gsl_constexpr bool
+operator!=( not_null<T> const &, std::nullptr_t ) = delete;
+template< class T >
+gsl_constexpr bool
+operator!=( std::nullptr_t , not_null<T> const & ) = delete;
+#endif // gsl_HAVE( NULLPTR ) && gsl_HAVE( IS_DELETE )
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator==( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( l.operator->() == r.operator->() )
+{
+ return l.operator->() == r.operator->();
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator==( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_(l.operator->() == r )
+{
+ return l.operator->() == r;
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator==( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( l == r.operator->() )
+{
+ return l == r.operator->();
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( l.operator->() < r.operator->() )
+{
+ return l.operator->() < r.operator->();
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( l.operator->() < r )
+{
+ return l.operator->() < r;
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( l < r.operator->() )
+{
+ return l < r.operator->();
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator!=( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( l == r ) )
+{
+ return !( l == r );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator!=( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( !( l == r ) )
+{
+ return !( l == r );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator!=( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( l == r ) )
+{
+ return !( l == r );
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<=( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( r < l ) )
+{
+ return !( r < l );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<=( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( !( r < l ) )
+{
+ return !( r < l );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator<=( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( r < l ) )
+{
+ return !( r < l );
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( r < l )
+{
+ return r < l;
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( r < l )
+{
+ return r < l;
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( r < l )
+{
+ return r < l;
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>=( not_null<T> const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( l < r ) )
+{
+ return !( l < r );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>=( not_null<T> const & l, U const & r )
+gsl_RETURN_DECLTYPE_( !( l < r ) )
+{
+ return !( l < r );
+}
+template< class T, class U >
+gsl_NODISCARD inline gsl_api gsl_constexpr gsl_TRAILING_RETURN_TYPE_( bool )
+operator>=( T const & l, not_null<U> const & r )
+gsl_RETURN_DECLTYPE_( !( l < r ) )
+{
+ return !( l < r );
+}
+
+// print not_null
+
+template< class CharType, class Traits, class T >
+std::basic_ostream< CharType, Traits > & operator<<( std::basic_ostream< CharType, Traits > & os, not_null<T> const & p )
+{
+ return os << p.operator->();
+}
+
+
+//
+// Byte-specific type.
+//
+#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ enum class gsl_may_alias byte : unsigned char {};
+#else
+ struct gsl_may_alias byte { typedef unsigned char type; type v; };
+#endif
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr byte
+to_byte( T v ) gsl_noexcept
+{
+#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ return static_cast<byte>( v );
+#elif gsl_HAVE( CONSTEXPR_11 )
+ return { static_cast<typename byte::type>( v ) };
+#else
+ byte b = { static_cast<typename byte::type>( v ) }; return b;
+#endif
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_NODISCARD gsl_api inline gsl_constexpr IntegerType
+to_integer( byte b ) gsl_noexcept
+{
+#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ return static_cast<typename std::underlying_type<byte>::type>( b );
+#else
+ return b.v;
+#endif
+}
+
+gsl_NODISCARD gsl_api inline gsl_constexpr unsigned char
+to_uchar( byte b ) gsl_noexcept
+{
+ return to_integer<unsigned char>( b );
+}
+
+gsl_NODISCARD gsl_api inline gsl_constexpr unsigned char
+to_uchar( int i ) gsl_noexcept
+{
+ return static_cast<unsigned char>( i );
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_api inline gsl_constexpr14 byte &
+operator<<=( byte & b, IntegerType shift ) gsl_noexcept
+{
+#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ return b = ::gsl::to_byte( ::gsl::to_uchar( b ) << shift );
+#else
+ b.v = ::gsl::to_uchar( b.v << shift ); return b;
+#endif
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_NODISCARD gsl_api inline gsl_constexpr byte
+operator<<( byte b, IntegerType shift ) gsl_noexcept
+{
+ return ::gsl::to_byte( ::gsl::to_uchar( b ) << shift );
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_NODISCARD gsl_api inline gsl_constexpr14 byte &
+operator>>=( byte & b, IntegerType shift ) gsl_noexcept
+{
+#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+ return b = ::gsl::to_byte( ::gsl::to_uchar( b ) >> shift );
+#else
+ b.v = ::gsl::to_uchar( b.v >> shift ); return b;
+#endif
+}
+
+template< class IntegerType gsl_ENABLE_IF_(( std::is_integral<IntegerType>::value )) >
+gsl_NODISCARD gsl_api inline gsl_constexpr byte
+operator>>( byte b, IntegerType shift ) gsl_noexcept
+{
+ return ::gsl::to_byte( ::gsl::to_uchar( b ) >> shift );
+}
+
+#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+gsl_DEFINE_ENUM_BITMASK_OPERATORS( byte )
+gsl_DEFINE_ENUM_RELATIONAL_OPERATORS( byte )
+#else // a.k.a. !gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+gsl_api inline gsl_constexpr bool operator==( byte l, byte r ) gsl_noexcept
+{
+ return l.v == r.v;
+}
+
+gsl_api inline gsl_constexpr bool operator!=( byte l, byte r ) gsl_noexcept
+{
+ return !( l == r );
+}
+
+gsl_api inline gsl_constexpr bool operator< ( byte l, byte r ) gsl_noexcept
+{
+ return l.v < r.v;
+}
+
+gsl_api inline gsl_constexpr bool operator<=( byte l, byte r ) gsl_noexcept
+{
+ return !( r < l );
+}
+
+gsl_api inline gsl_constexpr bool operator> ( byte l, byte r ) gsl_noexcept
+{
+ return ( r < l );
+}
+
+gsl_api inline gsl_constexpr bool operator>=( byte l, byte r ) gsl_noexcept
+{
+ return !( l < r );
+}
+
+gsl_api inline gsl_constexpr14 byte & operator|=( byte & l, byte r ) gsl_noexcept
+{
+ l.v |= r.v; return l;
+}
+
+gsl_api inline gsl_constexpr byte operator|( byte l, byte r ) gsl_noexcept
+{
+ return ::gsl::to_byte( l.v | r.v );
+}
+
+gsl_api inline gsl_constexpr14 byte & operator&=( byte & l, byte r ) gsl_noexcept
+{
+ l.v &= r.v; return l;
+}
+
+gsl_api inline gsl_constexpr byte operator&( byte l, byte r ) gsl_noexcept
+{
+ return ::gsl::to_byte( l.v & r.v );
+}
+
+gsl_api inline gsl_constexpr14 byte & operator^=( byte & l, byte r ) gsl_noexcept
+{
+ l.v ^= r.v; return l;
+}
+
+gsl_api inline gsl_constexpr byte operator^( byte l, byte r ) gsl_noexcept
+{
+ return ::gsl::to_byte( l.v ^ r.v );
+}
+
+gsl_api inline gsl_constexpr byte operator~( byte b ) gsl_noexcept
+{
+ return ::gsl::to_byte( ~b.v );
+}
+#endif // gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE )
+
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+
+// Tag to select span constructor taking a container:
+
+struct with_container_t { gsl_constexpr with_container_t( ) gsl_noexcept { } };
+const gsl_constexpr with_container_t with_container; // TODO: this can lead to ODR violations because the symbol will be defined in multiple translation units
+
+#endif
+
+namespace detail {
+
+template< class T >
+gsl_api gsl_constexpr14 T * endptr( T * data, gsl_CONFIG_SPAN_INDEX_TYPE size )
+{
+ // Be sure to run the check before doing pointer arithmetics, which would be UB for `nullptr` and non-0 integers.
+ gsl_Expects( size == 0 || data != gsl_nullptr );
+ return data + size;
+}
+
+} // namespace detail
+
+//
+// span<> - A 1D view of contiguous T's, replace (*,len).
+//
+template< class T >
+class span
+{
+ template< class U > friend class span;
+
+public:
+ typedef gsl_CONFIG_SPAN_INDEX_TYPE index_type;
+
+ typedef T element_type;
+ typedef typename std11::remove_cv< T >::type value_type;
+
+ typedef T & reference;
+ typedef T * pointer;
+ typedef T const * const_pointer;
+ typedef T const & const_reference;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+
+ typedef std::reverse_iterator< iterator > reverse_iterator;
+ typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
+
+ typedef gsl_CONFIG_SPAN_INDEX_TYPE size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ // 26.7.3.2 Constructors, copy, and assignment [span.cons]
+
+ gsl_api gsl_constexpr span() gsl_noexcept
+ : first_( gsl_nullptr )
+ , last_ ( gsl_nullptr )
+ {
+ }
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 5 )
+
+#if gsl_HAVE( NULLPTR )
+ gsl_api gsl_constexpr14 span( std::nullptr_t, index_type size_in )
+ : first_( nullptr )
+ , last_ ( nullptr )
+ {
+ gsl_Expects( size_in == 0 );
+ }
+#endif
+
+#if gsl_HAVE( IS_DELETE )
+ gsl_DEPRECATED
+ gsl_api gsl_constexpr span( reference data_in )
+ : span( &data_in, 1 )
+ {}
+
+ gsl_api gsl_constexpr span( element_type && ) = delete;
+#endif
+
+#endif // deprecate
+
+ gsl_api gsl_constexpr14 span( pointer data_in, index_type size_in )
+ : first_( data_in )
+ , last_( detail::endptr( data_in, size_in ) )
+ {
+ }
+
+ gsl_api gsl_constexpr14 span( pointer first_in, pointer last_in )
+ : first_( first_in )
+ , last_ ( last_in )
+ {
+ gsl_Expects( first_in <= last_in );
+ }
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 5 )
+
+ template< class U >
+ gsl_api gsl_constexpr14 span( U * data_in, index_type size_in )
+ : first_( data_in )
+ , last_( detail::endptr( data_in, size_in ) )
+ {
+ }
+
+#endif // deprecate
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 5 )
+ template< class U, size_t N >
+ gsl_api gsl_constexpr span( U (&arr)[N] ) gsl_noexcept
+ : first_( gsl_ADDRESSOF( arr[0] ) )
+ , last_ ( gsl_ADDRESSOF( arr[0] ) + N )
+ {}
+#else
+ template< size_t N
+ gsl_ENABLE_IF_(( std::is_convertible<value_type(*)[], element_type(*)[] >::value ))
+ >
+ gsl_api gsl_constexpr span( element_type (&arr)[N] ) gsl_noexcept
+ : first_( gsl_ADDRESSOF( arr[0] ) )
+ , last_ ( gsl_ADDRESSOF( arr[0] ) + N )
+ {}
+#endif // deprecate
+
+#if gsl_HAVE( ARRAY )
+#if ! gsl_DEPRECATE_TO_LEVEL( 5 )
+
+ template< class U, size_t N >
+ gsl_api gsl_constexpr span( std::array< U, N > & arr )
+ : first_( arr.data() )
+ , last_ ( arr.data() + N )
+ {}
+
+ template< class U, size_t N >
+ gsl_api gsl_constexpr span( std::array< U, N > const & arr )
+ : first_( arr.data() )
+ , last_ ( arr.data() + N )
+ {}
+
+#else
+
+ template< size_t N
+ gsl_ENABLE_IF_(( std::is_convertible<value_type(*)[], element_type(*)[] >::value ))
+ >
+ gsl_constexpr span( std::array< value_type, N > & arr )
+ : first_( arr.data() )
+ , last_ ( arr.data() + N )
+ {}
+
+ template< size_t N
+ gsl_ENABLE_IF_(( std::is_convertible<value_type(*)[], element_type(*)[] >::value ))
+ >
+ gsl_constexpr span( std::array< value_type, N > const & arr )
+ : first_( arr.data() )
+ , last_ ( arr.data() + N )
+ {}
+
+#endif // deprecate
+#endif // gsl_HAVE( ARRAY )
+
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+ template< class Container
+ gsl_ENABLE_IF_(( detail::is_compatible_container< Container, element_type >::value ))
+ >
+ gsl_api gsl_constexpr span( Container & cont ) gsl_noexcept
+ : first_( std17::data( cont ) )
+ , last_ ( std17::data( cont ) + std17::size( cont ) )
+ {}
+
+ template< class Container
+ gsl_ENABLE_IF_((
+ std::is_const< element_type >::value
+ && detail::is_compatible_container< Container, element_type >::value
+ ))
+ >
+ gsl_api gsl_constexpr span( Container const & cont ) gsl_noexcept
+ : first_( std17::data( cont ) )
+ , last_ ( std17::data( cont ) + std17::size( cont ) )
+ {}
+
+#elif gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+
+ template< class Container >
+ gsl_constexpr span( Container & cont )
+ : first_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) )
+ , last_ ( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) + cont.size() )
+ {}
+
+ template< class Container >
+ gsl_constexpr span( Container const & cont )
+ : first_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) )
+ , last_ ( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) + cont.size() )
+ {}
+
+#endif
+
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+
+ template< class Container >
+ gsl_constexpr span( with_container_t, Container & cont ) gsl_noexcept
+ : first_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) )
+ , last_ ( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) + cont.size() )
+ {}
+
+ template< class Container >
+ gsl_constexpr span( with_container_t, Container const & cont ) gsl_noexcept
+ : first_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) )
+ , last_ ( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) + cont.size() )
+ {}
+
+#endif
+
+#if !gsl_DEPRECATE_TO_LEVEL( 4 )
+ // constructor taking shared_ptr deprecated since 0.29.0
+
+# if gsl_HAVE( SHARED_PTR )
+ gsl_DEPRECATED
+ gsl_constexpr span( shared_ptr<element_type> const & ptr )
+ : first_( ptr.get() )
+ , last_ ( ptr.get() ? ptr.get() + 1 : gsl_nullptr )
+ {}
+# endif
+
+ // constructors taking unique_ptr deprecated since 0.29.0
+
+# if gsl_HAVE( UNIQUE_PTR )
+# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+ template< class ArrayElementType = typename std::add_pointer<element_type>::type >
+# else
+ template< class ArrayElementType >
+# endif
+ gsl_DEPRECATED
+ gsl_constexpr span( unique_ptr<ArrayElementType> const & ptr, index_type count )
+ : first_( ptr.get() )
+ , last_ ( ptr.get() + count )
+ {}
+
+ gsl_DEPRECATED
+ gsl_constexpr span( unique_ptr<element_type> const & ptr )
+ : first_( ptr.get() )
+ , last_ ( ptr.get() ? ptr.get() + 1 : gsl_nullptr )
+ {}
+# endif
+
+#endif // deprecate shared_ptr, unique_ptr
+
+#if gsl_HAVE( IS_DEFAULT ) && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 430, 600)
+ gsl_constexpr span( span && ) gsl_noexcept = default;
+ gsl_constexpr span( span const & ) = default;
+#else
+ gsl_api gsl_constexpr span( span const & other )
+ : first_( other.begin() )
+ , last_ ( other.end() )
+ {}
+#endif
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr14 span & operator=( span && ) gsl_noexcept = default;
+ gsl_constexpr14 span & operator=( span const & ) gsl_noexcept = default;
+#else
+ gsl_constexpr14 span & operator=( span other ) gsl_noexcept
+ {
+ first_ = other.first_;
+ last_ = other.last_;
+ return *this;
+ }
+#endif
+
+ template< class U
+ gsl_ENABLE_IF_(( std::is_convertible<U(*)[], element_type(*)[]>::value ))
+ >
+ gsl_api gsl_constexpr span( span<U> const & other )
+ : first_( other.begin() )
+ , last_ ( other.end() )
+ {}
+
+#if 0
+ // Converting from other span ?
+ template< class U > operator=();
+#endif
+
+ // 26.7.3.3 Subviews [span.sub]
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 span
+ first( index_type count ) const
+ {
+ gsl_Expects( std::size_t( count ) <= std::size_t( this->size() ) );
+ return span( this->data(), count );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 span
+ last( index_type count ) const
+ {
+ gsl_Expects( std::size_t( count ) <= std::size_t( this->size() ) );
+ return span( this->data() + this->size() - count, count );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 span
+ subspan( index_type offset ) const
+ {
+ gsl_Expects( std::size_t( offset ) <= std::size_t( this->size() ) );
+ return span( this->data() + offset, this->size() - offset );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 span
+ subspan( index_type offset, index_type count ) const
+ {
+ gsl_Expects(
+ std::size_t( offset ) <= std::size_t( this->size() ) &&
+ std::size_t( count ) <= std::size_t( this->size() - offset ) );
+ return span( this->data() + offset, count );
+ }
+
+ // 26.7.3.4 Observers [span.obs]
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ size() const gsl_noexcept
+ {
+ return narrow_cast<index_type>( last_ - first_ );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr std::ptrdiff_t
+ ssize() const gsl_noexcept
+ {
+ return narrow_cast<std::ptrdiff_t>( last_ - first_ );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ size_bytes() const gsl_noexcept
+ {
+ return size() * narrow_cast<index_type>( sizeof( element_type ) );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr bool
+ empty() const gsl_noexcept
+ {
+ return size() == 0;
+ }
+
+ // 26.7.3.5 Element access [span.elem]
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ operator[]( index_type pos ) const
+ {
+ gsl_Expects( pos < size() );
+ return first_[ pos ];
+ }
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 6 )
+ gsl_DEPRECATED_MSG("use subscript indexing instead")
+ gsl_api gsl_constexpr14 reference
+ operator()( index_type pos ) const
+ {
+ return (*this)[ pos ];
+ }
+
+ gsl_DEPRECATED_MSG("use subscript indexing instead")
+ gsl_api gsl_constexpr14 reference
+ at( index_type pos ) const
+ {
+ return (*this)[ pos ];
+ }
+#endif // deprecate
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ front() const
+ {
+ gsl_Expects( first_ != last_ );
+ return *first_;
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ back() const
+ {
+ gsl_Expects( first_ != last_ );
+ return *(last_ - 1);
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr pointer
+ data() const gsl_noexcept
+ {
+ return first_;
+ }
+
+ // 26.7.3.6 Iterator support [span.iterators]
+
+ gsl_NODISCARD gsl_api gsl_constexpr iterator
+ begin() const gsl_noexcept
+ {
+ return iterator( first_ );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr iterator
+ end() const gsl_noexcept
+ {
+ return iterator( last_ );
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr const_iterator
+ cbegin() const gsl_noexcept
+ {
+#if gsl_CPP11_OR_GREATER
+ return { begin() };
+#else
+ return const_iterator( begin() );
+#endif
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr const_iterator
+ cend() const gsl_noexcept
+ {
+#if gsl_CPP11_OR_GREATER
+ return { end() };
+#else
+ return const_iterator( end() );
+#endif
+ }
+
+ gsl_NODISCARD gsl_constexpr17 reverse_iterator
+ rbegin() const gsl_noexcept
+ {
+ return reverse_iterator( end() );
+ }
+
+ gsl_NODISCARD gsl_constexpr17 reverse_iterator
+ rend() const gsl_noexcept
+ {
+ return reverse_iterator( begin() );
+ }
+
+ gsl_NODISCARD gsl_constexpr17 const_reverse_iterator
+ crbegin() const gsl_noexcept
+ {
+ return const_reverse_iterator( cend() );
+ }
+
+ gsl_NODISCARD gsl_constexpr17 const_reverse_iterator
+ crend() const gsl_noexcept
+ {
+ return const_reverse_iterator( cbegin() );
+ }
+
+ gsl_constexpr14 void swap( span & other ) gsl_noexcept
+ {
+ std::swap( first_, other.first_ );
+ std::swap( last_ , other.last_ );
+ }
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 3 )
+ // member length() deprecated since 0.29.0
+
+ gsl_DEPRECATED_MSG("use size() instead")
+ gsl_api gsl_constexpr index_type length() const gsl_noexcept
+ {
+ return size();
+ }
+
+ // member length_bytes() deprecated since 0.29.0
+
+ gsl_DEPRECATED_MSG("use size_bytes() instead")
+ gsl_api gsl_constexpr index_type length_bytes() const gsl_noexcept
+ {
+ return size_bytes();
+ }
+#endif
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 2 )
+ // member as_bytes(), as_writeable_bytes deprecated since 0.17.0
+
+ gsl_DEPRECATED_MSG("use free function gsl::as_bytes() instead")
+ gsl_api span< const byte > as_bytes() const gsl_noexcept
+ {
+ return span< const byte >( reinterpret_cast<const byte *>( data() ), size_bytes() ); // NOLINT
+ }
+
+ gsl_DEPRECATED_MSG("use free function gsl::as_writable_bytes() instead")
+ gsl_api span< byte > as_writeable_bytes() const gsl_noexcept
+ {
+ return span< byte >( reinterpret_cast<byte *>( data() ), size_bytes() ); // NOLINT
+ }
+
+#endif
+
+ template< class U >
+ gsl_NODISCARD gsl_api span< U >
+ as_span() const
+ {
+ gsl_Expects( ( this->size_bytes() % sizeof(U) ) == 0 );
+ return span< U >( reinterpret_cast<U *>( this->data() ), this->size_bytes() / sizeof( U ) ); // NOLINT
+ }
+
+private:
+ pointer first_;
+ pointer last_;
+};
+
+// class template argument deduction guides:
+
+#if gsl_HAVE( DEDUCTION_GUIDES ) // gsl_CPP17_OR_GREATER
+
+template< class T, size_t N >
+span( T (&)[N] ) -> span<T /*, N*/>;
+
+template< class T, size_t N >
+span( std::array<T, N> & ) -> span<T /*, N*/>;
+
+template< class T, size_t N >
+span( std::array<T, N> const & ) -> span<const T /*, N*/>;
+
+template< class Container >
+span( Container& ) -> span<typename Container::value_type>;
+
+template< class Container >
+span( Container const & ) -> span<const typename Container::value_type>;
+
+#endif // gsl_HAVE( DEDUCTION_GUIDES )
+
+// 26.7.3.7 Comparison operators [span.comparison]
+
+#if gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+# if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, class U >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr bool operator==( span<T> const & l, span<U> const & r )
+{
+ return l.size() == r.size()
+ && (l.begin() == r.begin() || std98::equal( l.begin(), l.end(), r.begin() ) );
+}
+
+template< class T, class U >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr bool operator< ( span<T> const & l, span<U> const & r )
+{
+ return std98::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+
+# else // a.k.a. !gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr bool operator==( span<T> const & l, span<T> const & r )
+{
+ return l.size() == r.size()
+ && (l.begin() == r.begin() || std98::equal( l.begin(), l.end(), r.begin() ) );
+}
+
+template< class T >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr bool operator< ( span<T> const & l, span<T> const & r )
+{
+ return std98::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+# endif // gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr bool operator!=( span<T> const & l, span<U> const & r )
+{
+ return !( l == r );
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr bool operator<=( span<T> const & l, span<U> const & r )
+{
+ return !( r < l );
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr bool operator> ( span<T> const & l, span<U> const & r )
+{
+ return ( r < l );
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr bool operator>=( span<T> const & l, span<U> const & r )
+{
+ return !( l < r );
+}
+#endif // gsl_CONFIG( ALLOWS_SPAN_COMPARISON )
+
+// span algorithms
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr std::size_t
+size( span<T> const & spn )
+{
+ return static_cast<std::size_t>( spn.size() );
+}
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr std::ptrdiff_t
+ssize( span<T> const & spn )
+{
+ return spn.ssize();
+}
+
+namespace detail {
+
+template< class II, class N, class OI >
+gsl_api gsl_constexpr14 inline OI copy_n( II first, N count, OI result )
+{
+ if ( count > 0 )
+ {
+ *result++ = *first;
+ for ( N i = 1; i < count; ++i )
+ {
+ *result++ = *++first;
+ }
+ }
+ return result;
+}
+}
+
+template< class T, class U >
+gsl_api gsl_constexpr14 inline void copy( span<T> src, span<U> dest )
+{
+#if gsl_CPP14_OR_GREATER // gsl_HAVE( TYPE_TRAITS ) (circumvent Travis clang 3.4)
+ static_assert( std::is_assignable<U &, T const &>::value, "Cannot assign elements of source span to elements of destination span" );
+#endif
+ gsl_Expects( dest.size() >= src.size() );
+ detail::copy_n( src.data(), src.size(), dest.data() );
+}
+
+// span creator functions (see ctors)
+
+template< class T >
+gsl_NODISCARD gsl_api inline span< const byte >
+as_bytes( span<T> spn ) gsl_noexcept
+{
+ return span< const byte >( reinterpret_cast<const byte *>( spn.data() ), spn.size_bytes() ); // NOLINT
+}
+
+template< class T>
+gsl_NODISCARD gsl_api inline span< byte >
+as_writable_bytes( span<T> spn ) gsl_noexcept
+{
+ return span< byte >( reinterpret_cast<byte *>( spn.data() ), spn.size_bytes() ); // NOLINT
+}
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 6 )
+template< class T>
+gsl_DEPRECATED_MSG("use as_writable_bytes() (different spelling) instead")
+gsl_api inline span< byte > as_writeable_bytes( span<T> spn ) gsl_noexcept
+{
+ return span< byte >( reinterpret_cast<byte *>( spn.data() ), spn.size_bytes() ); // NOLINT
+}
+#endif // deprecate
+
+#if gsl_FEATURE_TO_STD( MAKE_SPAN )
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr span<T>
+make_span( T * ptr, typename span<T>::index_type count )
+{
+ return span<T>( ptr, count );
+}
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr span<T>
+make_span( T * first, T * last )
+{
+ return span<T>( first, last );
+}
+
+template< class T, size_t N >
+gsl_NODISCARD inline gsl_constexpr span<T>
+make_span( T (&arr)[N] )
+{
+ return span<T>( gsl_ADDRESSOF( arr[0] ), N );
+}
+
+#if gsl_HAVE( ARRAY )
+
+template< class T, size_t N >
+gsl_NODISCARD inline gsl_constexpr span<T>
+make_span( std::array<T,N> & arr )
+{
+ return span<T>( arr );
+}
+
+template< class T, size_t N >
+gsl_NODISCARD inline gsl_constexpr span<const T>
+make_span( std::array<T,N> const & arr )
+{
+ return span<const T>( arr );
+}
+#endif
+
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && gsl_HAVE( AUTO )
+
+template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
+gsl_NODISCARD inline gsl_constexpr auto
+make_span( Container & cont ) -> span< typename std::remove_pointer<EP>::type >
+{
+ return span< typename std::remove_pointer<EP>::type >( cont );
+}
+
+template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
+gsl_NODISCARD inline gsl_constexpr auto
+make_span( Container const & cont ) -> span< const typename std::remove_pointer<EP>::type >
+{
+ return span< const typename std::remove_pointer<EP>::type >( cont );
+}
+
+#else
+
+template< class T >
+inline span<T>
+make_span( std::vector<T> & cont )
+{
+ return span<T>( with_container, cont );
+}
+
+template< class T >
+inline span<const T>
+make_span( std::vector<T> const & cont )
+{
+ return span<const T>( with_container, cont );
+}
+#endif
+
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+
+template< class Container >
+gsl_NODISCARD inline gsl_constexpr span<typename Container::value_type>
+make_span( with_container_t, Container & cont ) gsl_noexcept
+{
+ return span< typename Container::value_type >( with_container, cont );
+}
+
+template< class Container >
+gsl_NODISCARD inline gsl_constexpr span<const typename Container::value_type>
+make_span( with_container_t, Container const & cont ) gsl_noexcept
+{
+ return span< const typename Container::value_type >( with_container, cont );
+}
+
+#endif // gsl_FEATURE_TO_STD( WITH_CONTAINER )
+
+#if !gsl_DEPRECATE_TO_LEVEL( 4 )
+template< class Ptr >
+gsl_DEPRECATED
+inline span<typename Ptr::element_type>
+make_span( Ptr & ptr )
+{
+ return span<typename Ptr::element_type>( ptr );
+}
+#endif // !gsl_DEPRECATE_TO_LEVEL( 4 )
+
+template< class Ptr >
+gsl_DEPRECATED
+inline span<typename Ptr::element_type>
+make_span( Ptr & ptr, typename span<typename Ptr::element_type>::index_type count )
+{
+ return span<typename Ptr::element_type>( ptr, count );
+}
+
+#endif // gsl_FEATURE_TO_STD( MAKE_SPAN )
+
+#if gsl_FEATURE_TO_STD( BYTE_SPAN )
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr span<byte>
+byte_span( T & t ) gsl_noexcept
+{
+ return span<byte>( reinterpret_cast<byte *>( &t ), sizeof(T) );
+}
+
+template< class T >
+gsl_NODISCARD gsl_api inline gsl_constexpr span<const byte>
+byte_span( T const & t ) gsl_noexcept
+{
+ return span<const byte>( reinterpret_cast<byte const *>( &t ), sizeof(T) );
+}
+
+#endif // gsl_FEATURE_TO_STD( BYTE_SPAN )
+
+//
+// basic_string_span:
+//
+
+template< class T >
+class basic_string_span;
+
+namespace detail {
+
+template< class T >
+struct is_basic_string_span_oracle : std11::false_type {};
+
+template< class T >
+struct is_basic_string_span_oracle< basic_string_span<T> > : std11::true_type {};
+
+template< class T >
+struct is_basic_string_span : is_basic_string_span_oracle< typename std11::remove_cv<T>::type > {};
+
+template< class T >
+gsl_api inline gsl_constexpr14 std::size_t string_length( T * ptr, std::size_t max )
+{
+ if ( ptr == gsl_nullptr || max <= 0 )
+ return 0;
+
+ std::size_t len = 0;
+ while ( len < max && ptr[len] ) // NOLINT
+ ++len;
+
+ return len;
+}
+
+} // namespace detail
+
+//
+// basic_string_span<> - A view of contiguous characters, replace (*,len).
+//
+template< class T >
+class basic_string_span
+{
+public:
+ typedef T element_type;
+ typedef span<T> span_type;
+
+ typedef typename span_type::size_type size_type;
+ typedef typename span_type::index_type index_type;
+ typedef typename span_type::difference_type difference_type;
+
+ typedef typename span_type::pointer pointer ;
+ typedef typename span_type::reference reference ;
+
+ typedef typename span_type::iterator iterator ;
+ typedef typename span_type::const_iterator const_iterator ;
+ typedef typename span_type::reverse_iterator reverse_iterator;
+ typedef typename span_type::const_reverse_iterator const_reverse_iterator;
+
+ // construction:
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr basic_string_span() gsl_noexcept = default;
+#else
+ gsl_api gsl_constexpr basic_string_span() gsl_noexcept {}
+#endif
+
+#if gsl_HAVE( NULLPTR )
+ gsl_api gsl_constexpr basic_string_span( std::nullptr_t ) gsl_noexcept
+ : span_( nullptr, static_cast<index_type>( 0 ) )
+ {}
+#endif
+
+#ifdef __CUDACC_RELAXED_CONSTEXPR__
+ gsl_api
+#endif // __CUDACC_RELAXED_CONSTEXPR__
+ gsl_constexpr basic_string_span( pointer ptr )
+ : span_( remove_z( ptr, (std::numeric_limits<index_type>::max)() ) )
+ {}
+
+ gsl_api gsl_constexpr basic_string_span( pointer ptr, index_type count )
+ : span_( ptr, count )
+ {}
+
+ gsl_api gsl_constexpr basic_string_span( pointer firstElem, pointer lastElem )
+ : span_( firstElem, lastElem )
+ {}
+
+ template< std::size_t N >
+ gsl_constexpr basic_string_span( element_type (&arr)[N] )
+ : span_( remove_z( gsl_ADDRESSOF( arr[0] ), N ) )
+ {}
+
+#if gsl_HAVE( ARRAY )
+
+ template< std::size_t N >
+ gsl_constexpr basic_string_span( std::array< typename std11::remove_const<element_type>::type, N> & arr )
+ : span_( remove_z( arr ) )
+ {}
+
+ template< std::size_t N >
+ gsl_constexpr basic_string_span( std::array< typename std11::remove_const<element_type>::type, N> const & arr )
+ : span_( remove_z( arr ) )
+ {}
+
+#endif
+
+#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+ // Exclude: array, [basic_string,] basic_string_span
+
+ template< class Container
+ gsl_ENABLE_IF_((
+ ! detail::is_std_array< Container >::value
+ && ! detail::is_basic_string_span< Container >::value
+ && std::is_convertible< typename Container::pointer, pointer >::value
+ && std::is_convertible< typename Container::pointer, decltype(std::declval<Container>().data()) >::value
+ ))
+ >
+ gsl_constexpr basic_string_span( Container & cont )
+ : span_( ( cont ) )
+ {}
+
+ // Exclude: array, [basic_string,] basic_string_span
+
+ template< class Container
+ gsl_ENABLE_IF_((
+ ! detail::is_std_array< Container >::value
+ && ! detail::is_basic_string_span< Container >::value
+ && std::is_convertible< typename Container::pointer, pointer >::value
+ && std::is_convertible< typename Container::pointer, decltype(std::declval<Container const &>().data()) >::value
+ ))
+ >
+ gsl_constexpr basic_string_span( Container const & cont )
+ : span_( ( cont ) )
+ {}
+
+#elif gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR )
+
+ template< class Container >
+ gsl_constexpr basic_string_span( Container & cont )
+ : span_( cont )
+ {}
+
+ template< class Container >
+ gsl_constexpr basic_string_span( Container const & cont )
+ : span_( cont )
+ {}
+
+#else
+
+ template< class U >
+ gsl_api gsl_constexpr basic_string_span( span<U> const & rhs )
+ : span_( rhs )
+ {}
+
+#endif
+
+#if gsl_FEATURE_TO_STD( WITH_CONTAINER )
+
+ template< class Container >
+ gsl_constexpr basic_string_span( with_container_t, Container & cont )
+ : span_( with_container, cont )
+ {}
+#endif
+
+#if gsl_HAVE( IS_DEFAULT )
+# if gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 440, 600 )
+ gsl_constexpr basic_string_span( basic_string_span const & ) = default;
+
+ gsl_constexpr basic_string_span( basic_string_span && ) = default;
+# else
+ gsl_constexpr basic_string_span( basic_string_span const & ) gsl_noexcept = default;
+
+ gsl_constexpr basic_string_span( basic_string_span && ) gsl_noexcept = default;
+# endif
+#endif
+
+ template< class U
+ gsl_ENABLE_IF_(( std::is_convertible<typename basic_string_span<U>::pointer, pointer>::value ))
+ >
+ gsl_api gsl_constexpr basic_string_span( basic_string_span<U> const & rhs )
+ : span_( reinterpret_cast<pointer>( rhs.data() ), rhs.length() ) // NOLINT
+ {}
+
+#if gsl_STDLIB_CPP11_120
+ template< class U
+ gsl_ENABLE_IF_(( std::is_convertible<typename basic_string_span<U>::pointer, pointer>::value ))
+ >
+ gsl_api gsl_constexpr basic_string_span( basic_string_span<U> && rhs )
+ : span_( reinterpret_cast<pointer>( rhs.data() ), rhs.length() ) // NOLINT
+ {}
+#endif // gsl_STDLIB_CPP11_120
+
+ template< class CharTraits, class Allocator >
+ gsl_constexpr basic_string_span(
+ std::basic_string< typename std11::remove_const<element_type>::type, CharTraits, Allocator > & str )
+ : span_( gsl_ADDRESSOF( str[0] ), str.length() )
+ {}
+
+ template< class CharTraits, class Allocator >
+ gsl_constexpr basic_string_span(
+ std::basic_string< typename std11::remove_const<element_type>::type, CharTraits, Allocator > const & str )
+ : span_( gsl_ADDRESSOF( str[0] ), str.length() )
+ {}
+
+ // assignment:
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr14 basic_string_span & operator=( basic_string_span const & ) gsl_noexcept = default;
+
+ gsl_constexpr14 basic_string_span & operator=( basic_string_span && ) gsl_noexcept = default;
+#endif
+
+ // sub span:
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr14 basic_string_span
+ first( index_type count ) const
+ {
+ return span_.first( count );
+ }
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr14 basic_string_span
+ last( index_type count ) const
+ {
+ return span_.last( count );
+ }
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr14 basic_string_span
+ subspan( index_type offset ) const
+ {
+ return span_.subspan( offset );
+ }
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr14 basic_string_span
+ subspan( index_type offset, index_type count ) const
+ {
+ return span_.subspan( offset, count );
+ }
+
+ // observers:
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ length() const gsl_noexcept
+ {
+ return span_.size();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ size() const gsl_noexcept
+ {
+ return span_.size();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ length_bytes() const gsl_noexcept
+ {
+ return span_.size_bytes();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr index_type
+ size_bytes() const gsl_noexcept
+ {
+ return span_.size_bytes();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr bool
+ empty() const gsl_noexcept
+ {
+ return size() == 0;
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ operator[]( index_type idx ) const
+ {
+ return span_[idx];
+ }
+
+#if ! gsl_DEPRECATE_TO_LEVEL( 6 )
+ gsl_DEPRECATED_MSG("use subscript indexing instead")
+ gsl_api gsl_constexpr14 reference operator()( index_type idx ) const
+ {
+ return span_[idx];
+ }
+#endif // deprecate
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ front() const
+ {
+ return span_.front();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr14 reference
+ back() const
+ {
+ return span_.back();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr pointer
+ data() const gsl_noexcept
+ {
+ return span_.data();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr iterator
+ begin() const gsl_noexcept
+ {
+ return span_.begin();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr iterator
+ end() const gsl_noexcept
+ {
+ return span_.end();
+ }
+
+ gsl_NODISCARD gsl_constexpr17 reverse_iterator
+ rbegin() const gsl_noexcept
+ {
+ return span_.rbegin();
+ }
+
+ gsl_NODISCARD gsl_constexpr17 reverse_iterator
+ rend() const gsl_noexcept
+ {
+ return span_.rend();
+ }
+
+ // const version not in p0123r2:
+
+ gsl_NODISCARD gsl_api gsl_constexpr const_iterator
+ cbegin() const gsl_noexcept
+ {
+ return span_.cbegin();
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr const_iterator
+ cend() const gsl_noexcept
+ {
+ return span_.cend();
+ }
+
+ gsl_NODISCARD gsl_constexpr17 const_reverse_iterator
+ crbegin() const gsl_noexcept
+ {
+ return span_.crbegin();
+ }
+
+ gsl_NODISCARD gsl_constexpr17 const_reverse_iterator
+ crend() const gsl_noexcept
+ {
+ return span_.crend();
+ }
+
+private:
+ gsl_api static gsl_constexpr14 span_type remove_z( pointer sz, std::size_t max )
+ {
+ return span_type( sz, detail::string_length( sz, max ) );
+ }
+
+#if gsl_HAVE( ARRAY )
+ template< size_t N >
+ gsl_NODISCARD static gsl_constexpr14 span_type
+ remove_z( std::array<typename std11::remove_const<element_type>::type, N> & arr )
+ {
+ return remove_z( gsl_ADDRESSOF( arr[0] ), narrow_cast< std::size_t >( N ) );
+ }
+
+ template< size_t N >
+ gsl_NODISCARD static gsl_constexpr14 span_type
+ remove_z( std::array<typename std11::remove_const<element_type>::type, N> const & arr )
+ {
+ return remove_z( gsl_ADDRESSOF( arr[0] ), narrow_cast< std::size_t >( N ) );
+ }
+#endif
+
+private:
+ span_type span_;
+};
+
+// basic_string_span comparison functions:
+
+#if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, class U >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator==( basic_string_span<T> const & l, U const & u ) gsl_noexcept
+{
+ const basic_string_span< typename std11::add_const<T>::type > r( u );
+
+ return l.size() == r.size()
+ && std98::equal( l.begin(), l.end(), r.begin() );
+}
+
+template< class T, class U >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<( basic_string_span<T> const & l, U const & u ) gsl_noexcept
+{
+ const basic_string_span< typename std11::add_const<T>::type > r( u );
+
+ return std98::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+
+#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator==( U const & u, basic_string_span<T> const & r ) gsl_noexcept
+{
+ const basic_string_span< typename std11::add_const<T>::type > l( u );
+
+ return l.size() == r.size()
+ && std98::equal( l.begin(), l.end(), r.begin() );
+}
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<( U const & u, basic_string_span<T> const & r ) gsl_noexcept
+{
+ const basic_string_span< typename std11::add_const<T>::type > l( u );
+
+ return std98::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+#endif
+
+#else //gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator==( basic_string_span<T> const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return l.size() == r.size()
+ && std98::equal( l.begin(), l.end(), r.begin() );
+}
+
+template< class T >
+gsl_SUPPRESS_MSGSL_WARNING(stl.1)
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<( basic_string_span<T> const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return std98::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+
+#endif // gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator!=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
+{
+ return !( l == r );
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
+{
+#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) || ! gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+ return !( r < l );
+#else
+ basic_string_span< typename std11::add_const<T>::type > rr( r );
+ return !( rr < l );
+#endif
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator>( basic_string_span<T> const & l, U const & r ) gsl_noexcept
+{
+#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) || ! gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON )
+ return ( r < l );
+#else
+ basic_string_span< typename std11::add_const<T>::type > rr( r );
+ return ( rr < l );
+#endif
+}
+
+template< class T, class U >
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator>=( basic_string_span<T> const & l, U const & r ) gsl_noexcept
+{
+ return !( l < r );
+}
+
+#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator!=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return !( l == r );
+}
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator<=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return !( r < l );
+}
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator>( U const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return ( r < l );
+}
+
+template< class T, class U
+ gsl_ENABLE_IF_(( !detail::is_basic_string_span<U>::value ))
+>
+gsl_NODISCARD inline gsl_constexpr14 bool
+operator>=( U const & l, basic_string_span<T> const & r ) gsl_noexcept
+{
+ return !( l < r );
+}
+
+#endif // gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+// convert basic_string_span to byte span:
+
+template< class T >
+gsl_NODISCARD gsl_api inline span< const byte >
+as_bytes( basic_string_span<T> spn ) gsl_noexcept
+{
+ return span< const byte >( reinterpret_cast<const byte *>( spn.data() ), spn.size_bytes() ); // NOLINT
+}
+
+//
+// String types:
+//
+
+typedef char * zstring;
+typedef const char * czstring;
+
+#if gsl_HAVE( WCHAR )
+typedef wchar_t * wzstring;
+typedef const wchar_t * cwzstring;
+#endif
+
+typedef basic_string_span< char > string_span;
+typedef basic_string_span< char const > cstring_span;
+
+#if gsl_HAVE( WCHAR )
+typedef basic_string_span< wchar_t > wstring_span;
+typedef basic_string_span< wchar_t const > cwstring_span;
+#endif
+
+// to_string() allow (explicit) conversions from string_span to string
+
+#if 0
+
+template< class T >
+inline std::basic_string< typename std::remove_const<T>::type > to_string( basic_string_span<T> spn )
+{
+ std::string( spn.data(), spn.length() );
+}
+
+#else
+
+gsl_NODISCARD inline std::string
+to_string( string_span const & spn )
+{
+ return std::string( spn.data(), static_cast<std::size_t>( spn.length() ) );
+}
+
+gsl_NODISCARD inline std::string
+to_string( cstring_span const & spn )
+{
+ return std::string( spn.data(), static_cast<std::size_t>( spn.length() ) );
+}
+
+#if gsl_HAVE( WCHAR )
+
+gsl_NODISCARD inline std::wstring
+to_string( wstring_span const & spn )
+{
+ return std::wstring( spn.data(), static_cast<std::size_t>( spn.length() ) );
+}
+
+gsl_NODISCARD inline std::wstring
+to_string( cwstring_span const & spn )
+{
+ return std::wstring( spn.data(), static_cast<std::size_t>( spn.length() ) );
+}
+
+#endif // gsl_HAVE( WCHAR )
+#endif // to_string()
+
+//
+// Stream output for string_span types
+//
+
+namespace detail {
+
+template< class Stream >
+void write_padding( Stream & os, std::streamsize n )
+{
+ for ( std::streamsize i = 0; i < n; ++i )
+ os.rdbuf()->sputc( os.fill() );
+}
+
+template< class Stream, class Span >
+Stream & write_to_stream( Stream & os, Span const & spn )
+{
+ typename Stream::sentry sentry( os );
+
+ if ( !os )
+ return os;
+
+ const std::streamsize length = gsl::narrow_failfast<std::streamsize>( spn.length() );
+
+ // Whether, and how, to pad
+ const bool pad = ( length < os.width() );
+ const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right;
+
+ if ( left_pad )
+ detail::write_padding( os, os.width() - length );
+
+ // Write span characters
+ os.rdbuf()->sputn( spn.begin(), length );
+
+ if ( pad && !left_pad )
+ detail::write_padding( os, os.width() - length );
+
+ // Reset output stream width
+ os.width(0);
+
+ return os;
+}
+
+} // namespace detail
+
+template< typename Traits >
+std::basic_ostream< char, Traits > & operator<<( std::basic_ostream< char, Traits > & os, string_span const & spn )
+{
+ return detail::write_to_stream( os, spn );
+}
+
+template< typename Traits >
+std::basic_ostream< char, Traits > & operator<<( std::basic_ostream< char, Traits > & os, cstring_span const & spn )
+{
+ return detail::write_to_stream( os, spn );
+}
+
+#if gsl_HAVE( WCHAR )
+
+template< typename Traits >
+std::basic_ostream< wchar_t, Traits > & operator<<( std::basic_ostream< wchar_t, Traits > & os, wstring_span const & spn )
+{
+ return detail::write_to_stream( os, spn );
+}
+
+template< typename Traits >
+std::basic_ostream< wchar_t, Traits > & operator<<( std::basic_ostream< wchar_t, Traits > & os, cwstring_span const & spn )
+{
+ return detail::write_to_stream( os, spn );
+}
+
+#endif // gsl_HAVE( WCHAR )
+
+//
+// ensure_sentinel()
+//
+// Provides a way to obtain a 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.
+//
+namespace detail {
+
+template< class T, class SizeType, const T Sentinel >
+gsl_constexpr14 static span<T> ensure_sentinel( T * seq, SizeType max = (std::numeric_limits<SizeType>::max)() )
+{
+ typedef T * pointer;
+
+ gsl_SUPPRESS_MSVC_WARNING( 26429, "f.23: symbol 'cur' is never tested for nullness, it can be marked as not_null" )
+ pointer cur = seq;
+
+ while ( static_cast<SizeType>( cur - seq ) < max && *cur != Sentinel )
+ ++cur;
+
+ gsl_Expects( *cur == Sentinel );
+
+ return span<T>( seq, gsl::narrow_cast< typename span<T>::index_type >( cur - seq ) );
+}
+} // namespace detail
+
+//
+// ensure_z - creates a string_span for a czstring or cwzstring.
+// Will fail fast if a null-terminator cannot be found before
+// the limit of size_type.
+//
+
+template< class T >
+gsl_NODISCARD inline gsl_constexpr14 span<T>
+ensure_z( T * const & sz, size_t max = (std::numeric_limits<size_t>::max)() )
+{
+ return detail::ensure_sentinel<T, size_t, 0>( sz, max );
+}
+
+template< class T, size_t N >
+gsl_NODISCARD inline gsl_constexpr14 span<T>
+ensure_z( T (&sz)[N] )
+{
+ return ::gsl::ensure_z( gsl_ADDRESSOF( sz[0] ), N );
+}
+
+# if gsl_HAVE( TYPE_TRAITS )
+
+template< class Container >
+gsl_NODISCARD inline gsl_constexpr14 span< typename std::remove_pointer<typename Container::pointer>::type >
+ensure_z( Container & cont )
+{
+ return ::gsl::ensure_z( cont.data(), cont.length() );
+}
+# endif
+
+//
+// basic_zstring_span<> - A view of contiguous null-terminated characters, replace (*,len).
+//
+
+template <typename T>
+class basic_zstring_span
+{
+public:
+ typedef T element_type;
+ typedef span<T> span_type;
+
+ typedef typename span_type::index_type index_type;
+ typedef typename span_type::difference_type difference_type;
+
+ typedef element_type * czstring_type;
+ typedef basic_string_span<element_type> string_span_type;
+
+ gsl_api gsl_constexpr14 basic_zstring_span( span_type s )
+ : span_( s )
+ {
+ // expects a zero-terminated span
+ gsl_Expects( s.back() == '\0' );
+ }
+
+#if gsl_HAVE( IS_DEFAULT )
+ gsl_constexpr basic_zstring_span( basic_zstring_span const & ) = default;
+ gsl_constexpr basic_zstring_span( basic_zstring_span && ) = default;
+ gsl_constexpr14 basic_zstring_span & operator=( basic_zstring_span const & ) = default;
+ gsl_constexpr14 basic_zstring_span & operator=( basic_zstring_span && ) = default;
+#else
+ gsl_api gsl_constexpr basic_zstring_span( basic_zstring_span const & other) : span_ ( other.span_ ) {}
+ gsl_api gsl_constexpr basic_zstring_span & operator=( basic_zstring_span const & other ) { span_ = other.span_; return *this; }
+#endif
+
+ gsl_NODISCARD gsl_api gsl_constexpr bool
+ empty() const gsl_noexcept
+ {
+ return false;
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr string_span_type
+ as_string_span() const gsl_noexcept
+ {
+ return string_span_type( span_.data(), span_.size() - 1 );
+ }
+
+ /*gsl_api*/ // currently disabled due to an apparent NVCC bug
+ gsl_NODISCARD gsl_constexpr string_span_type
+ ensure_z() const
+ {
+ return ::gsl::ensure_z(span_.data(), span_.size());
+ }
+
+ gsl_NODISCARD gsl_api gsl_constexpr czstring_type
+ assume_z() const gsl_noexcept
+ {
+ return span_.data();
+ }
+
+private:
+ span_type span_;
+};
+
+//
+// zString types:
+//
+
+typedef basic_zstring_span< char > zstring_span;
+typedef basic_zstring_span< char const > czstring_span;
+
+#if gsl_HAVE( WCHAR )
+typedef basic_zstring_span< wchar_t > wzstring_span;
+typedef basic_zstring_span< wchar_t const > cwzstring_span;
+#endif
+
+} // namespace gsl
+
+#if gsl_HAVE( HASH )
+
+//
+// std::hash specializations for GSL types
+//
+
+namespace gsl {
+
+namespace detail {
+
+//
+// Helper struct for std::hash specializations
+//
+
+template<bool Condition>
+struct conditionally_enabled_hash
+{
+
+};
+
+// disabled as described in [unord.hash]
+template<>
+struct conditionally_enabled_hash< false >
+{
+gsl_is_delete_access:
+ conditionally_enabled_hash() gsl_is_delete;
+ conditionally_enabled_hash( conditionally_enabled_hash const & ) gsl_is_delete;
+ conditionally_enabled_hash( conditionally_enabled_hash && ) gsl_is_delete;
+ conditionally_enabled_hash & operator=( conditionally_enabled_hash const & ) gsl_is_delete;
+ conditionally_enabled_hash & operator=( conditionally_enabled_hash && ) gsl_is_delete;
+};
+
+} // namespace detail
+
+} // namespace gsl
+
+namespace std {
+
+template< class T >
+struct hash< ::gsl::not_null< T > > : public ::gsl::detail::conditionally_enabled_hash<is_default_constructible<hash<T>>::value>
+{
+public:
+ gsl_NODISCARD gsl_constexpr std::size_t
+ operator()( ::gsl::not_null<T> const & v ) const
+ // hash function is not `noexcept` because `as_nullable()` has preconditions
+ {
+ return hash<T>()( ::gsl::as_nullable( v ) );
+ }
+};
+template< class T >
+struct hash< ::gsl::not_null< T* > >
+{
+public:
+ gsl_NODISCARD gsl_constexpr std::size_t
+ operator()( ::gsl::not_null< T* > const & v ) const gsl_noexcept
+ {
+ return hash<T*>()( ::gsl::as_nullable( v ) );
+ }
+};
+
+template<>
+struct hash< ::gsl::byte >
+{
+public:
+ gsl_NODISCARD gsl_constexpr std::size_t operator()( ::gsl::byte v ) const gsl_noexcept
+ {
+ return ::gsl::to_integer<std::size_t>( v );
+ }
+};
+
+} // namespace std
+
+#endif // gsl_HAVE( HASH )
+
+#if gsl_FEATURE( GSL_LITE_NAMESPACE )
+
+// gsl_lite namespace:
+
+// gsl-lite currently keeps all symbols in the namespace `gsl`. The `gsl_lite` namespace contains all the symbols in the
+// `gsl` namespace, plus some extensions that are not specified in the Core Guidelines.
+//
+// Going forward, we want to support coexistence of gsl-lite with M-GSL, so we want to encourage using the `gsl_lite`
+// namespace when consuming gsl-lite. Typical use in library code would be:
+//
+// #include <gsl-lite/gsl-lite.hpp> // instead of <gsl/gsl-lite.hpp>
+//
+// namespace foo {
+// namespace gsl = ::gsl_lite; // convenience alias
+// double mean( gsl::span<double const> elements )
+// {
+// gsl_Expects( ! elements.empty() ); // instead of Expects()
+// ...
+// }
+// } // namespace foo
+//
+// In a future version, the new <gsl-lite/gsl-lite.hpp> header will only define the `gsl_lite` namespace and no
+// unprefixed `Expects()` and `Ensures()` macros to avoid collision with M-GSL. To ensure backward compatibility, the
+// old header <gsl/gsl-lite.hpp> will keep defining the `gsl` namespace and the `Expects()` and `Ensures()` macros.
+
+namespace gsl_lite {
+
+namespace std11 = ::gsl::std11;
+namespace std14 = ::gsl::std14;
+namespace std17 = ::gsl::std17;
+namespace std20 = ::gsl::std20;
+
+using namespace std11;
+using namespace std14;
+using namespace std17;
+using namespace std20;
+
+using namespace ::gsl::detail::no_adl;
+
+# if gsl_HAVE( SHARED_PTR )
+using std::unique_ptr;
+using std::shared_ptr;
+using std::make_shared;
+# endif
+
+using ::gsl::index;
+using ::gsl::dim;
+using ::gsl::stride;
+using ::gsl::diff;
+
+# if gsl_HAVE( ALIAS_TEMPLATE )
+# if gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 141 ) // VS 2015 and earlier have trouble with `using` for alias templates
+ template< class T
+# if gsl_HAVE( TYPE_TRAITS )
+ , typename = typename std::enable_if< std::is_pointer<T>::value >::type
+# endif
+ >
+ using owner = T;
+# else
+using ::gsl::owner;
+# endif
+# endif
+
+using ::gsl::fail_fast;
+
+using ::gsl::finally;
+# if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+using ::gsl::on_return;
+using ::gsl::on_error;
+# endif // gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD )
+
+using ::gsl::narrow_cast;
+using ::gsl::narrowing_error;
+using ::gsl::narrow;
+using ::gsl::narrow_failfast;
+
+using ::gsl::at;
+
+using ::gsl::not_null;
+using ::gsl::not_null_ic;
+using ::gsl::make_not_null;
+
+using ::gsl::byte;
+
+using ::gsl::to_byte;
+using ::gsl::to_integer;
+using ::gsl::to_uchar;
+using ::gsl::to_string;
+
+using ::gsl::with_container_t;
+using ::gsl::with_container;
+
+using ::gsl::span;
+using ::gsl::make_span;
+using ::gsl::byte_span;
+using ::gsl::copy;
+using ::gsl::as_bytes;
+using ::gsl::as_writable_bytes;
+# if ! gsl_DEPRECATE_TO_LEVEL( 6 )
+using ::gsl::as_writeable_bytes;
+# endif
+
+using ::gsl::basic_string_span;
+using ::gsl::string_span;
+using ::gsl::cstring_span;
+
+using ::gsl::basic_zstring_span;
+using ::gsl::zstring_span;
+using ::gsl::czstring_span;
+
+using ::gsl::zstring;
+using ::gsl::czstring;
+
+# if gsl_HAVE( WCHAR )
+using ::gsl::wzstring;
+using ::gsl::cwzstring;
+
+using ::gsl::wzstring_span;
+using ::gsl::cwzstring_span;
+# endif // gsl_HAVE( WCHAR )
+
+using ::gsl::ensure_z;
+
+} // namespace gsl_lite
+
+#endif // gsl_FEATURE( GSL_LITE_NAMESPACE )
+
+gsl_RESTORE_MSVC_WARNINGS()
+
+// #undef internal macros
+#undef gsl_STATIC_ASSERT_
+#undef gsl_ENABLE_IF_
+#undef gsl_TRAILING_RETURN_TYPE_
+#undef gsl_RETURN_DECLTYPE_
+
+#endif // GSL_GSL_LITE_HPP_INCLUDED
+
+// end of file
diff --git a/vbz/CMakeLists.txt b/vbz/CMakeLists.txt
index d519f7d..4526474 100644
--- a/vbz/CMakeLists.txt
+++ b/vbz/CMakeLists.txt
@@ -33,7 +33,9 @@ target_link_libraries(vbz
# This explicit dependency is required to make sure the header files are installed into the right
# location before we try building against them.
-if (WIN32 OR APPLE OR "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86_64")
+if (WIN32 OR
+ (APPLE AND NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm64") OR
+ "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86_64")
if(NOT MSVC)
target_compile_options(vbz PRIVATE -mssse3)
endif()
diff --git a/vbz/perf/test_data_generator.h b/vbz/perf/test_data_generator.h
index 4b13d81..1bb593b 100644
--- a/vbz/perf/test_data_generator.h
+++ b/vbz/perf/test_data_generator.h
@@ -2,7 +2,7 @@
#include "../test/test_data.h"
-#include <gsl/gsl>
+#include <gsl/gsl-lite.hpp>
#include <numeric>
#include <random>
diff --git a/vbz/test/CMakeLists.txt b/vbz/test/CMakeLists.txt
index 5c8a3df..0e1b48c 100644
--- a/vbz/test/CMakeLists.txt
+++ b/vbz/test/CMakeLists.txt
@@ -9,13 +9,16 @@ add_sanitizers(vbz_test)
set_property(TARGET vbz_test PROPERTY CXX_STANDARD 11)
+find_package( Threads )
+
target_link_libraries(vbz_test
PUBLIC
vbz
+ ${CMAKE_THREAD_LIBS_INIT}
)
add_test(
NAME vbz_test
COMMAND vbz_test
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-) \ No newline at end of file
+)
diff --git a/vbz/test/test_utils.h b/vbz/test/test_utils.h
index 596c1b0..138ffe9 100644
--- a/vbz/test/test_utils.h
+++ b/vbz/test/test_utils.h
@@ -1,6 +1,6 @@
#pragma once
-#include <gsl/gsl>
+#include <gsl/gsl-lite.hpp>
#include <iostream>
diff --git a/vbz/v0/vbz_streamvbyte.cpp b/vbz/v0/vbz_streamvbyte.cpp
index 9ffeb01..609075e 100644
--- a/vbz/v0/vbz_streamvbyte.cpp
+++ b/vbz/v0/vbz_streamvbyte.cpp
@@ -2,7 +2,7 @@
#include "vbz_streamvbyte_impl.h"
#include "vbz.h"
-#include <gsl/gsl>
+#include <gsl/gsl-lite.hpp>
vbz_size_t vbz_max_streamvbyte_compressed_size_v0(
std::size_t integer_size,
diff --git a/vbz/v0/vbz_streamvbyte_impl.h b/vbz/v0/vbz_streamvbyte_impl.h
index 015ad13..357cb61 100644
--- a/vbz/v0/vbz_streamvbyte_impl.h
+++ b/vbz/v0/vbz_streamvbyte_impl.h
@@ -5,7 +5,9 @@
#include "streamvbyte.h"
#include "streamvbyte_zigzag.h"
-#include <gsl/gsl>
+#include <gsl/gsl-lite.hpp>
+
+#include <vector>
/// \brief Generic implementation, safe for all integer types, and platforms.
template <typename T, bool UseZigZag>
@@ -53,14 +55,14 @@ struct StreamVByteWorkerV0
if (!UseZigZag)
{
- cast(gsl::make_span(intermediate_buffer), gsl::make_span(output));
+ cast(gsl::make_span(intermediate_buffer), output);
return vbz_size_t(output.size() * sizeof(T));
}
std::vector<std::int32_t> output_buffer(output.size());
zigzag_delta_decode(intermediate_buffer.data(), output_buffer.data(), output_buffer.size(), 0);
- cast(gsl::make_span(output_buffer), gsl::make_span(output));
+ cast(gsl::make_span(output_buffer), output);
return vbz_size_t(output.size() * sizeof(T));
}
diff --git a/vbz/v1/vbz_streamvbyte.cpp b/vbz/v1/vbz_streamvbyte.cpp
index 9fc3414..d2d9a67 100644
--- a/vbz/v1/vbz_streamvbyte.cpp
+++ b/vbz/v1/vbz_streamvbyte.cpp
@@ -3,7 +3,7 @@
#include "../v0/vbz_streamvbyte_impl.h" // for 4 byte case
#include "vbz.h"
-#include <gsl/gsl>
+#include <gsl/gsl-lite.hpp>
vbz_size_t vbz_max_streamvbyte_compressed_size_v1(
std::size_t integer_size,
diff --git a/vbz/v1/vbz_streamvbyte_impl.h b/vbz/v1/vbz_streamvbyte_impl.h
index be306f9..b3bce88 100644
--- a/vbz/v1/vbz_streamvbyte_impl.h
+++ b/vbz/v1/vbz_streamvbyte_impl.h
@@ -5,9 +5,10 @@
#include "streamvbyte.h"
#include "streamvbyte_zigzag.h"
-#include <gsl/gsl>
+#include <gsl/gsl-lite.hpp>
#include <cassert>
+#include <vector>
#ifdef _MSC_VER
# define VBZ_RESTRICT __restrict
@@ -224,14 +225,14 @@ struct StreamVByteWorkerV1
if (!UseZigZag)
{
- cast(gsl::make_span(intermediate_buffer), gsl::make_span(output));
+ cast(gsl::make_span(intermediate_buffer), output);
return vbz_size_t(output.size() * sizeof(T));
}
std::vector<std::int32_t> output_buffer(output.size());
zigzag_delta_decode(intermediate_buffer.data(), output_buffer.data(), output_buffer.size(), 0);
- cast(gsl::make_span(output_buffer), gsl::make_span(output));
+ cast(gsl::make_span(output_buffer), output);
return vbz_size_t(output.size() * sizeof(T));
}
diff --git a/vbz/vbz.cpp b/vbz/vbz.cpp
index 56dbe8b..8ae0b74 100644
--- a/vbz/vbz.cpp
+++ b/vbz/vbz.cpp
@@ -1,7 +1,7 @@
#include "v0/vbz_streamvbyte.h"
#include "v1/vbz_streamvbyte.h"
-#include <gsl/gsl>
+#include <gsl/gsl-lite.hpp>
#include <zstd.h>
#include <cassert>
diff --git a/vbz_plugin/CMakeLists.txt b/vbz_plugin/CMakeLists.txt
index cfc73e5..565c179 100644
--- a/vbz_plugin/CMakeLists.txt
+++ b/vbz_plugin/CMakeLists.txt
@@ -1,5 +1,5 @@
-add_library(vbz_hdf_plugin SHARED
+add_library(vbz_hdf_plugin
vbz_plugin_user_utils.h
vbz_plugin.cpp
vbz_plugin.h
@@ -11,6 +11,16 @@ generate_export_header(vbz_hdf_plugin EXPORT_FILE_NAME vbz_plugin/vbz_hdf_plugin
set_property(TARGET vbz_hdf_plugin PROPERTY CXX_STANDARD 11)
+if(WIN32 AND HDF5_USE_STATIC_LIBRARIES)
+ # See vbz_plugin.cpp -- if also building with Python on Windows then the runtime
+ # used is determined by that Python version, so we only support dynamic builds.
+ if(ENABLE_PYTHON)
+ message(FATAL_ERROR "Cannot enable HDF5_USE_STATIC_LIBRARIES as well as ENABLE_PYTHON")
+ else()
+ add_definitions(-DHDF5_USE_STATIC_LIBRARIES)
+ endif()
+endif()
+
target_include_directories(
vbz_hdf_plugin
PUBLIC
diff --git a/vbz_plugin/vbz_plugin.cpp b/vbz_plugin/vbz_plugin.cpp
index 4e39dd1..75e1612 100644
--- a/vbz_plugin/vbz_plugin.cpp
+++ b/vbz_plugin/vbz_plugin.cpp
@@ -2,7 +2,7 @@
#include "vbz_plugin.h"
#include "vbz.h"
-#include <gsl/gsl>
+#include <gsl/gsl-lite.hpp>
#include <hdf5/hdf5_plugin_types.h>
#include <array>
@@ -32,7 +32,7 @@ int checksum(gsl::span<char const> input)
}
#endif
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(HDF5_USE_STATIC_LIBRARIES)
HMODULE get_hdf_module()
{
static HMODULE module = nullptr;
@@ -64,7 +64,7 @@ HMODULE get_hdf_module()
//
void* h5_malloc(std::size_t size)
{
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(HDF5_USE_STATIC_LIBRARIES)
static auto module = get_hdf_module();
static auto malloc_memory = (void*(*)(size_t, bool))GetProcAddress(module, "H5allocate_memory");
@@ -76,7 +76,7 @@ void* h5_malloc(std::size_t size)
void h5_free(void* memory)
{
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(HDF5_USE_STATIC_LIBRARIES)
static auto module = get_hdf_module();
static auto free_hdf5 = (int(*)(void *))GetProcAddress(module, "H5free_memory");