From d452c3b061549008404b81e359c8a8e3f2f043de Mon Sep 17 00:00:00 2001 From: Stefan Reinhold Date: Tue, 17 Jul 2018 10:23:44 +0200 Subject: [PATCH 01/81] Make library importable by CMake using find_package --- CMakeLists.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b0de85d..8259516 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,9 @@ project(GSL CXX) include(ExternalProject) find_package(Git) +# Use GNUInstallDirs to provide the right locations on all platforms +include(GNUInstallDirs) + # creates a library GSL which is an interface (header files only) add_library(GSL INTERFACE) @@ -55,6 +58,7 @@ target_include_directories(GSL INTERFACE $ + $ ) if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9)) @@ -72,10 +76,18 @@ if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9)) endif() endif() +install(TARGETS GSL EXPORT GSLConfig + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) install( DIRECTORY include/gsl - DESTINATION include + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +# Make library importable by other projects +install(EXPORT GSLConfig DESTINATION share/GSL/cmake) +export(TARGETS GSL FILE GSLConfig.cmake) option(GSL_TEST "Generate tests." ${GSL_STANDALONE_PROJECT}) if (GSL_TEST) From 030454e3e9b6cbb46e6be5bb31c730bca715b1b0 Mon Sep 17 00:00:00 2001 From: Stefan Reinhold Date: Tue, 17 Jul 2018 11:09:58 +0200 Subject: [PATCH 02/81] Fix for Windows: CMake complains about INTERFACE_SOURCES directory --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8259516..1693069 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,9 @@ target_include_directories(GSL INTERFACE $ - $ + $ ) if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9)) From 0a31a14d0939f6cb1f6b92bb73429b9165a1b0bc Mon Sep 17 00:00:00 2001 From: Stefan Reinhold Date: Tue, 17 Jul 2018 11:56:38 +0200 Subject: [PATCH 03/81] Fix INSTALL_INTERFACE for exported target CMake war reporting: 'Target "GSL" INTERFACE_SOURCES property contains path: "..." which is prefixed in the source directory'. CMake was confused because the $ had linebreaks in it. Putting everything in one line fixed the issue. --- CMakeLists.txt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1693069..f9b0454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,12 +55,8 @@ target_compile_definitions(GSL INTERFACE # add include folders to the library and targets that consume it target_include_directories(GSL INTERFACE - $ - $ + $ + $ ) if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9)) @@ -79,9 +75,7 @@ if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9)) endif() install(TARGETS GSL EXPORT GSLConfig - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install( DIRECTORY include/gsl From 9e1645b990e6476e40a531f7964d9f2b33f7e7e4 Mon Sep 17 00:00:00 2001 From: Stefan Reinhold Date: Tue, 17 Jul 2018 13:07:27 +0200 Subject: [PATCH 04/81] Do not install .natvis files. This fixes an issue where CMake complains about INTERFACE_SOURCES containing a path which is prefixed in source directory on windows. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f9b0454..077160c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,7 @@ if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9)) # add natvis file to the library so it will automatically be loaded into Visual Studio if(VS_ADD_NATIVE_VISUALIZERS) target_sources(GSL INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/GSL.natvis + $ ) endif() endif() From e2b57d16f92b7d4fa8363dfefcced940dd658645 Mon Sep 17 00:00:00 2001 From: Stefan Reinhold Date: Tue, 17 Jul 2018 17:43:54 +0200 Subject: [PATCH 05/81] Export target GSL in namespace Microsoft.GSL This is to avoid conflicts with GNU Scientific Library which also has an exported target named GSL. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 077160c..7cf29a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9)) endif() endif() -install(TARGETS GSL EXPORT GSLConfig +install(TARGETS GSL EXPORT Microsoft.GSLConfig PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install( @@ -82,8 +82,8 @@ install( DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) # Make library importable by other projects -install(EXPORT GSLConfig DESTINATION share/GSL/cmake) -export(TARGETS GSL FILE GSLConfig.cmake) +install(EXPORT Microsoft.GSLConfig NAMESPACE Microsoft.GSL:: DESTINATION share/Microsoft.GSL/cmake) +export(TARGETS GSL NAMESPACE Microsoft.GSL:: FILE GSLConfig.cmake) option(GSL_TEST "Generate tests." ${GSL_STANDALONE_PROJECT}) if (GSL_TEST) From e3ffe1c5cbc11b01c535365acdde0a3e2fc6c2a3 Mon Sep 17 00:00:00 2001 From: Stefan Reinhold Date: Tue, 17 Jul 2018 17:56:11 +0200 Subject: [PATCH 06/81] Fix naming of exported CMake configuration file --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cf29a7..c10d025 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,7 @@ install( ) # Make library importable by other projects install(EXPORT Microsoft.GSLConfig NAMESPACE Microsoft.GSL:: DESTINATION share/Microsoft.GSL/cmake) -export(TARGETS GSL NAMESPACE Microsoft.GSL:: FILE GSLConfig.cmake) +export(TARGETS GSL NAMESPACE Microsoft.GSL:: FILE Microsoft.GSLConfig.cmake) option(GSL_TEST "Generate tests." ${GSL_STANDALONE_PROJECT}) if (GSL_TEST) From ffe8ffb452a52305863d9aab6499fd621b1eab25 Mon Sep 17 00:00:00 2001 From: Stefan Reinhold Date: Wed, 18 Jul 2018 09:35:03 +0200 Subject: [PATCH 07/81] Dummy commit to force CI re-run From 186f5d21c13c2b8dffa86ba5610afedfafebd13b Mon Sep 17 00:00:00 2001 From: Roelf-Jilling Date: Tue, 14 Jan 2020 17:09:27 +0100 Subject: [PATCH 08/81] Move compiler warning suppression for tests from cpp files to CMake --- tests/CMakeLists.txt | 17 ++++++++++++++++- tests/algorithm_tests.cpp | 17 ----------------- tests/assertion_tests.cpp | 17 ----------------- tests/at_tests.cpp | 17 ----------------- tests/bounds_tests.cpp | 19 ------------------- tests/byte_tests.cpp | 17 ----------------- tests/multi_span_tests.cpp | 19 ------------------- tests/notnull_tests.cpp | 17 ----------------- tests/owner_tests.cpp | 17 ----------------- tests/span_tests.cpp | 19 ------------------- tests/strict_notnull_tests.cpp | 17 ----------------- tests/strided_span_tests.cpp | 18 ------------------ tests/string_span_tests.cpp | 17 ----------------- tests/utils_tests.cpp | 18 ------------------ 14 files changed, 16 insertions(+), 230 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5c93a9a..1d74c45 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -49,9 +49,16 @@ if(MSVC) # MSVC or simulating MSVC -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic + -Wno-covered-switch-default # GTest + -Wno-deprecated-declarations # Allow tests for [[deprecated]] elements + -Wno-global-constructors # GTest + -Wno-language-extension-token # GTest gtest-port.h -Wno-missing-braces -Wno-missing-prototypes - -Wno-unknown-attributes + -Wno-shift-sign-overflow # GTest gtest-port.h + -Wno-undef # GTest + -Wno-unused-variable + -Wno-used-but-marked-unused # GTest EXPECT_DEATH $<$:-Wno-unused-member-function> > ) @@ -67,20 +74,28 @@ else() -Wpedantic -Wshadow -Wsign-conversion + -Wno-deprecated-declarations # Allow tests for [[deprecated]] elements $<$,$>: -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-missing-braces + -Wno-covered-switch-default # GTest + -Wno-global-constructors # GTest -Wno-missing-prototypes -Wno-padded -Wno-unknown-attributes + -Wno-unused-variable + -Wno-used-but-marked-unused # GTest EXPECT_DEATH $<$:-Wno-unused-member-function> -Wno-weak-vtables > $<$: $<$:-Wno-undefined-func-template> > + $<$: + -Wno-unused-variable + > ) endif(MSVC) diff --git a/tests/algorithm_tests.cpp b/tests/algorithm_tests.cpp index 50bff11..cf6eb01 100644 --- a/tests/algorithm_tests.cpp +++ b/tests/algorithm_tests.cpp @@ -20,19 +20,6 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#if __clang__ || __GNUC__ -// disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for copy #include // for span @@ -244,7 +231,3 @@ TEST(algorithm_tests, small_destination_span) copy(src_span_static, dst_span_static); #endif } - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/assertion_tests.cpp b/tests/assertion_tests.cpp index 598c7dc..da45128 100644 --- a/tests/assertion_tests.cpp +++ b/tests/assertion_tests.cpp @@ -20,19 +20,6 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for fail_fast (ptr only), Ensures, Expects @@ -78,7 +65,3 @@ TEST(assertion_tests, ensures) EXPECT_TRUE(g(2) == 3); EXPECT_DEATH(g(9), deathstring); } - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index cbed5ba..370350c 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -20,19 +20,6 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for at @@ -152,7 +139,3 @@ static constexpr bool test_constexpr() static_assert(test_constexpr(), "FAIL"); #endif - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/bounds_tests.cpp b/tests/bounds_tests.cpp index 4291ae1..d7fc33b 100644 --- a/tests/bounds_tests.cpp +++ b/tests/bounds_tests.cpp @@ -21,21 +21,6 @@ #pragma warning(disable : 4996) // use of function or classes marked [[deprecated]] #endif -#if __clang__ || __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - -//disable warnings from gtest -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for static_bounds, static_bounds_dynamic_range_t @@ -122,7 +107,3 @@ TEST(bounds_tests, bounds_convertible) #ifdef CONFIRM_COMPILATION_ERRORS copy(src_span_static, dst_span_static); #endif - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp index ab243a7..45ba66d 100644 --- a/tests/byte_tests.cpp +++ b/tests/byte_tests.cpp @@ -20,19 +20,6 @@ #pragma warning(disable : 26440 26426) #endif // _MSC_VER -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for to_byte, to_integer, byte, operator&, ope... @@ -146,7 +133,3 @@ TEST(byte_tests, aliasing) #ifdef CONFIRM_COMPILATION_ERRORS copy(src_span_static, dst_span_static); #endif - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/multi_span_tests.cpp b/tests/multi_span_tests.cpp index f2e040f..6940c28 100644 --- a/tests/multi_span_tests.cpp +++ b/tests/multi_span_tests.cpp @@ -22,21 +22,6 @@ // Suppressing warnings until it is completely removed #endif -#if __clang__ || __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - -//disable warnings from gtest -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for byte @@ -1884,7 +1869,3 @@ TEST(multi_span_test, iterator) #ifdef CONFIRM_COMPILATION_ERRORS copy(src_span_static, dst_span_static); #endif - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 038119e..3e91cfd 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -23,19 +23,6 @@ #pragma warning(disable : 4702) // unreachable code #endif -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for not_null, operator<, operator<=, operator> @@ -558,7 +545,3 @@ TEST(notnull_tests, TestMakeNotNull) static_assert(std::is_nothrow_move_constructible>::value, "not_null must be no-throw move constructible"); - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index 8756596..16134e8 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -21,19 +21,6 @@ #endif -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for owner @@ -61,7 +48,3 @@ TEST(owner_tests, check_pointer_constraint) } #endif } - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 28c97f5..d0da49d 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -20,21 +20,6 @@ #pragma warning(disable : 26440 26426 26497 4189 4996) #endif -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for byte @@ -1698,7 +1683,3 @@ TEST(span_test, from_array_constructor) EXPECT_DEATH(s2.front(), deathstring); EXPECT_DEATH(s2.back(), deathstring); } - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/strict_notnull_tests.cpp b/tests/strict_notnull_tests.cpp index 3c971db..f06542b 100644 --- a/tests/strict_notnull_tests.cpp +++ b/tests/strict_notnull_tests.cpp @@ -23,19 +23,6 @@ #pragma warning(disable : 4702) // unreachable code #endif -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for not_null, operator<, operator<=, operator> @@ -213,7 +200,3 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) static_assert(std::is_nothrow_move_constructible>::value, "strict_not_null must be no-throw move constructible"); - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/strided_span_tests.cpp b/tests/strided_span_tests.cpp index f5f3704..2773ac1 100644 --- a/tests/strided_span_tests.cpp +++ b/tests/strided_span_tests.cpp @@ -22,20 +22,6 @@ // Suppressing warnings until it is completely removed #endif -#if __clang__ || __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -//disable warnings from gtest -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for byte #include // for narrow_cast @@ -810,7 +796,3 @@ TEST(strided_span_tests, strided_span_conversion) i++; } } - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index 24bf140..0e90b85 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -21,19 +21,6 @@ #endif -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - #include #include // for Expects, fail_fast (ptr only) @@ -1235,7 +1222,3 @@ TEST(string_span_tests, as_writeable_bytes) EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index db6e8c5..54f2882 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -21,20 +21,6 @@ #endif -#if __clang__ || __GNUC__ -//disable warnings from gtest -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#endif // __clang__ || __GNUC__ - -#if __clang__ -#pragma GCC diagnostic ignored "-Wglobal-constructors" -#pragma GCC diagnostic ignored "-Wused-but-marked-unused" -#pragma GCC diagnostic ignored "-Wcovered-switch-default" -#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" -#endif // __clang__ - - #include #include // for narrow, finally, narrow_cast, narrowing_e... @@ -154,7 +140,3 @@ TEST(utils_tests, narrow) #endif } - -#if __clang__ || __GNUC__ -#pragma GCC diagnostic pop -#endif // __clang__ || __GNUC__ From d08ff53e612c18e7cc3622b0ffb9476353b9d9d9 Mon Sep 17 00:00:00 2001 From: Roelf-Jilling Date: Tue, 14 Jan 2020 17:38:42 +0100 Subject: [PATCH 09/81] Use [[maybe_unused]] with C++17 --- tests/CMakeLists.txt | 18 +++++++++++++----- tests/span_tests.cpp | 12 ++++++++++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1d74c45..973403f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,9 +57,11 @@ if(MSVC) # MSVC or simulating MSVC -Wno-missing-prototypes -Wno-shift-sign-overflow # GTest gtest-port.h -Wno-undef # GTest - -Wno-unused-variable -Wno-used-but-marked-unused # GTest EXPECT_DEATH - $<$:-Wno-unused-member-function> + $<$: # no support for [[maybe_unused]] + -Wno-unused-member-function + -Wno-unused-variable + > > ) else() @@ -85,16 +87,22 @@ else() -Wno-missing-prototypes -Wno-padded -Wno-unknown-attributes - -Wno-unused-variable -Wno-used-but-marked-unused # GTest EXPECT_DEATH - $<$:-Wno-unused-member-function> -Wno-weak-vtables + $<$: # no support for [[maybe_unused]] + -Wno-unused-member-function + -Wno-unused-variable + > > $<$: $<$:-Wno-undefined-func-template> > $<$: - -Wno-unused-variable + $<$,6>>: + $<$: # no support for [[maybe_unused]] + -Wno-unused-variable + > + > > ) endif(MSVC) diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index d0da49d..20c8bc0 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1287,7 +1287,11 @@ TEST(span_test, from_array_constructor) auto beyond = s.rend(); EXPECT_TRUE(it != beyond); - EXPECT_DEATH(auto _ = *beyond , deathstring); +#if (__cplusplus > 201402L) + EXPECT_DEATH([[maybe_unused]] auto _ = *beyond , deathstring); +#else + EXPECT_DEATH(auto _ = *beyond , deathstring); +#endif EXPECT_TRUE(beyond - first == 4); EXPECT_TRUE(first - first == 0); @@ -1332,7 +1336,11 @@ TEST(span_test, from_array_constructor) auto beyond = s.crend(); EXPECT_TRUE(it != beyond); - EXPECT_DEATH(auto _ = *beyond, deathstring); +#if (__cplusplus > 201402L) + EXPECT_DEATH([[maybe_unused]] auto _ = *beyond, deathstring); +#else + EXPECT_DEATH(auto _ = *beyond, deathstring); +#endif EXPECT_TRUE(beyond - first == 4); EXPECT_TRUE(first - first == 0); From 4cbd8948125a9070d8f342b6cb51bc02d108ca82 Mon Sep 17 00:00:00 2001 From: Roelf-Jilling Date: Wed, 15 Jan 2020 19:55:39 +0100 Subject: [PATCH 10/81] Enable more warnings in GCC --- tests/CMakeLists.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 973403f..c3a7327 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -98,11 +98,19 @@ else() $<$:-Wno-undefined-func-template> > $<$: + -Wdouble-promotion # float implicit to double + -Wlogical-op # suspicious uses of logical operators $<$,6>>: + -Wduplicated-cond # duplicated if-else conditions + -Wmisleading-indentation + -Wnull-dereference $<$: # no support for [[maybe_unused]] -Wno-unused-variable > > + $<$,7>>: + -Wduplicated-branches # identical if-else branches + > > ) endif(MSVC) @@ -194,6 +202,22 @@ else() -Wno-unknown-attributes -Wno-weak-vtables > + $<$: + -Wdouble-promotion # float implicit to double + -Wlogical-op # suspicious uses of logical operators + -Wuseless-cast # casting to its own type + $<$,6>>: + -Wduplicated-cond # duplicated if-else conditions + -Wmisleading-indentation + -Wnull-dereference + > + $<$,7>>: + -Wduplicated-branches # identical if-else branches + > + $<$,8>>: + -Wcast-align=strict # increase alignment (i.e. char* to int*) + > + > ) endif(MSVC) From 81f56796a1c844eada87c4bf91a479a29715703e Mon Sep 17 00:00:00 2001 From: Roelf-Jilling Date: Wed, 15 Jan 2020 18:33:37 +0100 Subject: [PATCH 11/81] MSVC and CoreChecker warning suppression for tests to CMake Suppress CppCoreCheck warnings on GTest macros. Suppress CppCoreCheck advice to use the GSL --- tests/CMakeLists.txt | 17 +++++++++++++++++ tests/algorithm_tests.cpp | 6 ------ tests/assertion_tests.cpp | 6 ------ tests/at_tests.cpp | 6 ------ tests/bounds_tests.cpp | 7 ------- tests/byte_tests.cpp | 6 ------ tests/multi_span_tests.cpp | 8 -------- tests/notnull_tests.cpp | 9 --------- tests/owner_tests.cpp | 7 ------- tests/span_tests.cpp | 6 ------ tests/strict_notnull_tests.cpp | 9 --------- tests/strided_span_tests.cpp | 8 -------- tests/string_span_tests.cpp | 7 ------- tests/utils_tests.cpp | 7 ------- 14 files changed, 17 insertions(+), 92 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c3a7327..eaa4c86 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,6 +45,21 @@ if(MSVC) # MSVC or simulating MSVC /EHsc /W4 /WX + $<$: + /wd4996 # Use of function or classes marked [[deprecated]] + /wd26409 # CppCoreCheck - GTest + /wd26426 # CppCoreCheck - GTest + /wd26440 # CppCoreCheck - GTest + /wd26446 # CppCoreCheck - prefer gsl::at() + /wd26472 # CppCoreCheck - use gsl::narrow(_cast) + /wd26481 # CppCoreCheck - use span instead of pointer arithmetic + $<$,1920>: # VS2015 + /wd4189 # variable is initialized but not referenced + $<$>: # Release, RelWithDebInfo + /wd4702 # Unreachable code + > + > + > $<$: -Weverything -Wno-c++98-compat @@ -172,6 +187,8 @@ if(MSVC) # MSVC or simulating MSVC $<$: /wd4577 /wd4702 + /wd26440 # CppCoreCheck - GTest + /wd26446 # CppCoreCheck - prefer gsl::at() > $<$: -Weverything diff --git a/tests/algorithm_tests.cpp b/tests/algorithm_tests.cpp index cf6eb01..ec9b2d1 100644 --- a/tests/algorithm_tests.cpp +++ b/tests/algorithm_tests.cpp @@ -14,12 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch -#endif - #include #include // for copy #include // for span diff --git a/tests/assertion_tests.cpp b/tests/assertion_tests.cpp index da45128..c45b00c 100644 --- a/tests/assertion_tests.cpp +++ b/tests/assertion_tests.cpp @@ -14,12 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch -#endif - #include #include // for fail_fast (ptr only), Ensures, Expects diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index 370350c..be2c7b8 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -14,12 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch -#endif - #include #include // for at diff --git a/tests/bounds_tests.cpp b/tests/bounds_tests.cpp index d7fc33b..9c2fb96 100644 --- a/tests/bounds_tests.cpp +++ b/tests/bounds_tests.cpp @@ -14,13 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch -#pragma warning(disable : 4996) // use of function or classes marked [[deprecated]] -#endif - #include #include // for static_bounds, static_bounds_dynamic_range_t diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp index 45ba66d..f2850ad 100644 --- a/tests/byte_tests.cpp +++ b/tests/byte_tests.cpp @@ -14,12 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) -#endif // _MSC_VER - #include #include // for to_byte, to_integer, byte, operator&, ope... diff --git a/tests/multi_span_tests.cpp b/tests/multi_span_tests.cpp index 6940c28..6425928 100644 --- a/tests/multi_span_tests.cpp +++ b/tests/multi_span_tests.cpp @@ -14,14 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch -#pragma warning(disable : 4996) // multi_span is in the process of being deprecated. - // Suppressing warnings until it is completely removed -#endif - #include #include // for byte diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 3e91cfd..d4c8cf4 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -14,15 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch - -// Fix VS2015 build breaks in Release -#pragma warning(disable : 4702) // unreachable code -#endif - #include #include // for not_null, operator<, operator<=, operator> diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index 16134e8..ca8222f 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -14,13 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch - -#endif - #include #include // for owner diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 20c8bc0..c41e013 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -14,12 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426 26497 4189 4996) -#endif - #include #include // for byte diff --git a/tests/strict_notnull_tests.cpp b/tests/strict_notnull_tests.cpp index f06542b..a568e95 100644 --- a/tests/strict_notnull_tests.cpp +++ b/tests/strict_notnull_tests.cpp @@ -14,15 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch - -// Fix VS2015 build breaks in Release -#pragma warning(disable : 4702) // unreachable code -#endif - #include #include // for not_null, operator<, operator<=, operator> diff --git a/tests/strided_span_tests.cpp b/tests/strided_span_tests.cpp index 2773ac1..5a18f1b 100644 --- a/tests/strided_span_tests.cpp +++ b/tests/strided_span_tests.cpp @@ -14,14 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch deprecated -#pragma warning(disable : 4996) // strided_span is in the process of being deprecated. - // Suppressing warnings until it is completely removed -#endif - #include #include // for byte #include // for narrow_cast diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index 0e90b85..e501bba 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -14,13 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch - -#endif - #include #include // for Expects, fail_fast (ptr only) diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 54f2882..b6b5fc9 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -14,13 +14,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch - -#endif - #include #include // for narrow, finally, narrow_cast, narrowing_e... From 72312b64749b4f087fc30d513eb4a2f99ed1aaf5 Mon Sep 17 00:00:00 2001 From: Roelf-Jilling Date: Thu, 16 Jan 2020 19:29:36 +0100 Subject: [PATCH 12/81] Revert "adding /EHsc for msvc cmake target gsl_test_config_noexcept" This reverts commit 3539bd8008ed872f63d3ca71319cf4e5abbfe6c9. --- tests/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5c93a9a..ef70547 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -135,7 +135,6 @@ add_library(gsl_tests_config_noexcept INTERFACE) if(MSVC) # MSVC or simulating MSVC target_compile_options(gsl_tests_config_noexcept INTERFACE ${GSL_CPLUSPLUS_OPT} - /EHsc /W4 /WX $<$: From 95730a80c4ddb0c565f5bb2e44fe1bf1d4acc971 Mon Sep 17 00:00:00 2001 From: Roelf-Jilling Date: Thu, 16 Jan 2020 19:10:02 +0100 Subject: [PATCH 13/81] Restore disabling of exceptions for Microsoft STL in "no exception tests" --- tests/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ef70547..1304688 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -133,6 +133,9 @@ endforeach(flag_var) # please try to keep entries ordered =) add_library(gsl_tests_config_noexcept INTERFACE) if(MSVC) # MSVC or simulating MSVC + target_compile_definitions(gsl_tests_config_noexcept INTERFACE + _HAS_EXCEPTIONS=0 # disable exceptions in the Microsoft STL + ) target_compile_options(gsl_tests_config_noexcept INTERFACE ${GSL_CPLUSPLUS_OPT} /W4 From 26a68c882bbb9e418de26acfbeec802a1d55201e Mon Sep 17 00:00:00 2001 From: Kunal Tyagi Date: Fri, 17 Jan 2020 14:32:37 +0900 Subject: [PATCH 14/81] Correct spelling error in docs --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 3daf16f..b3e5349 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -58,7 +58,7 @@ // GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t) // While there is a conversion from signed to unsigned, it happens at -// compiletime, so the compiler wouldn't have to warn indiscriminently, but +// compiletime, so the compiler wouldn't have to warn indiscriminately, but // could check if the source value actually doesn't fit into the target type // and only warn in those cases. #if defined(__GNUC__) && __GNUC__ > 6 From c61b1503ad02207e9fae405c12569e3fe5529953 Mon Sep 17 00:00:00 2001 From: NancyLi1013 Date: Sat, 18 Jan 2020 23:12:13 -0800 Subject: [PATCH 15/81] Add vcpkg installation instructions --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index c83db54..a2f783e 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,18 @@ These steps assume the source code of this repository has been cloned into a dir All tests should pass - indicating your platform is fully supported and you are ready to use the GSL types! +## Building GSL - Using vcpkg + +You can download and install GSL using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + vcpkg install gsl + +The GSL port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + ## Using the libraries As the types are entirely implemented inline in headers, there are no linking requirements. From 6b23937bafca79ddd9b544e337aaba36a06ce339 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Thu, 30 Jan 2020 17:00:13 -0800 Subject: [PATCH 16/81] remove move constructor for not_null. --- include/gsl/pointers | 1 - tests/notnull_tests.cpp | 3 --- tests/strict_notnull_tests.cpp | 3 --- 3 files changed, 7 deletions(-) diff --git a/include/gsl/pointers b/include/gsl/pointers index 7afed1c..1caf294 100644 --- a/include/gsl/pointers +++ b/include/gsl/pointers @@ -88,7 +88,6 @@ public: { } - not_null(not_null&& other) = default; not_null(const not_null& other) = default; not_null& operator=(const not_null& other) = default; diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index d4c8cf4..0578131 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -533,6 +533,3 @@ TEST(notnull_tests, TestMakeNotNull) } #endif } - -static_assert(std::is_nothrow_move_constructible>::value, - "not_null must be no-throw move constructible"); diff --git a/tests/strict_notnull_tests.cpp b/tests/strict_notnull_tests.cpp index a568e95..3cf6911 100644 --- a/tests/strict_notnull_tests.cpp +++ b/tests/strict_notnull_tests.cpp @@ -188,6 +188,3 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) #endif } #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) - -static_assert(std::is_nothrow_move_constructible>::value, - "strict_not_null must be no-throw move constructible"); From 8579165d0a0ec8cbf90a20d2b84ed33def97868b Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 10:56:31 -0800 Subject: [PATCH 17/81] change span from signed to unsigned to align to std --- include/gsl/span | 206 +++++++++++++++++++++------------------- include/gsl/string_span | 151 +++++++++++++++-------------- tests/span_tests.cpp | 48 +++++----- 3 files changed, 212 insertions(+), 193 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index b3e5349..1b06fb3 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -26,16 +26,18 @@ #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... #include +#include // for std::addressof #include #include // for enable_if_t, declval, is_convertible, inte... #include -#include // for std::addressof #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) // turn off some warnings that are noisy about our Expects statements #pragma warning(disable : 4127) // conditional expression is constant +#pragma warning( \ + disable : 4146) // unary minus operator applied to unsigned type, result still unsigned #pragma warning(disable : 4702) // unreachable code // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. @@ -70,9 +72,9 @@ namespace gsl { // [views.constants], constants -constexpr const std::ptrdiff_t dynamic_extent = -1; +constexpr const std::size_t dynamic_extent = std::numeric_limits::max(); -template +template class span; // implementation details @@ -83,7 +85,7 @@ namespace details { }; - template + template struct is_span_oracle> : std::true_type { }; @@ -108,7 +110,7 @@ namespace details { }; - template + template struct is_allowed_extent_conversion : public std::integral_constant @@ -151,10 +153,10 @@ namespace details : span_iterator(other.span_, other.index_) {} - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr reference operator*() const { - Expects(index_ != span_->size()); + Expects(static_cast(index_) != span_->size()); return *(span_->data() + index_); } @@ -166,7 +168,7 @@ namespace details constexpr span_iterator& operator++() noexcept { - Expects(0 <= index_ && index_ != span_->size()); + Expects(0 <= index_ && static_cast(index_) != span_->size()); ++index_; return *this; } @@ -180,7 +182,7 @@ namespace details constexpr span_iterator& operator--() noexcept { - Expects(index_ != 0 && index_ <= span_->size()); + Expects(index_ != 0 && static_cast(index_) <= span_->size()); --index_; return *this; } @@ -198,7 +200,8 @@ namespace details return ret += n; } - friend constexpr span_iterator operator+(difference_type n, span_iterator const& rhs) noexcept + friend constexpr span_iterator operator+(difference_type n, + span_iterator const& rhs) noexcept { return rhs + n; } @@ -272,7 +275,7 @@ namespace details Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); } - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw @@ -287,7 +290,7 @@ namespace details #else static constexpr bool _Unwrap_when_unverified = false; #endif - GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive + GSL_SUPPRESS(con .3) // NO-FORMAT: attribute // TODO: false positive constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped @@ -300,11 +303,11 @@ namespace details std::ptrdiff_t index_ = 0; }; - template + template class extent_type { public: - using index_type = std::ptrdiff_t; + using index_type = std::size_t; static_assert(Ext >= 0, "A fixed-size span must be >= 0 in size."); @@ -327,13 +330,16 @@ namespace details class extent_type { public: - using index_type = std::ptrdiff_t; + using index_type = std::size_t; template explicit constexpr extent_type(extent_type ext) : size_(ext.size()) {} - explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); } + explicit constexpr extent_type(index_type size) : size_(size) + { + Expects(size != dynamic_extent); + } constexpr index_type size() const noexcept { return size_; } @@ -341,7 +347,7 @@ namespace details index_type size_; }; - template + template struct calculate_subspan_type { using type = span +template class span { public: // constants and types using element_type = ElementType; using value_type = std::remove_cv_t; - using index_type = std::ptrdiff_t; + using index_type = std::size_t; using pointer = element_type*; using reference = element_type&; + using difference_type = std::ptrdiff_t; using iterator = details::span_iterator, false>; using const_iterator = details::span_iterator, true>; @@ -379,11 +386,11 @@ public: template " SFINAE, // since "std::enable_if_t" is ill-formed when Extent is greater than 0. - class = std::enable_if_t<(Dependent || Extent <= 0)>> + class = std::enable_if_t<(Dependent || Extent == 0 || Extent == dynamic_extent)>> constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) {} - constexpr span(pointer ptr, index_type count) noexcept: storage_(ptr, count) {} + constexpr span(pointer ptr, index_type count) noexcept : storage_(ptr, count) {} constexpr span(pointer firstElem, pointer lastElem) noexcept : storage_(firstElem, std::distance(firstElem, lastElem)) @@ -397,24 +404,20 @@ public: template 0)>> constexpr span(std::array, N>& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type()) - { - } + {} constexpr span(std::array, 0>&) noexcept : storage_(static_cast(nullptr), details::extent_type<0>()) - { - } + {} template 0)>> constexpr span(const std::array, N>& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type()) - { - } + {} constexpr span(const std::array, 0>&) noexcept : storage_(static_cast(nullptr), details::extent_type<0>()) - { - } + {} // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement // on Container to be a contiguous sequence container. @@ -433,13 +436,14 @@ public: std::is_convertible::value && std::is_convertible().data())>::value>> - constexpr span(const Container& cont) noexcept : span(cont.data(), narrow(cont.size())) + constexpr span(const Container& cont) noexcept + : span(cont.data(), narrow(cont.size())) {} constexpr span(const span& other) noexcept = default; template < - class OtherElementType, std::ptrdiff_t OtherExtent, + class OtherElementType, std::size_t OtherExtent, class = std::enable_if_t< details::is_allowed_extent_conversion::value && details::is_allowed_element_type_conversion::value>> @@ -451,27 +455,27 @@ public: constexpr span& operator=(const span& other) noexcept = default; // [span.sub], span subviews - template + template constexpr span first() const noexcept { - Expects(Count >= 0 && Count <= size()); + Expects(Count <= size()); return {data(), Count}; } - template - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + template + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr span last() const noexcept { - Expects(Count >= 0 && size() - Count >= 0); + Expects(size() >= Count); return {data() + (size() - Count), Count}; } - template - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + template + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr auto subspan() const noexcept -> typename details::calculate_subspan_type::type { - Expects((Offset >= 0 && size() - Offset >= 0) && + Expects((size() >= Offset) && (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size()))); return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; @@ -479,17 +483,19 @@ public: constexpr span first(index_type count) const noexcept { - Expects(count >= 0 && count <= size()); + Expects(count <= size()); return {data(), count}; } constexpr span last(index_type count) const noexcept { + Expects(count <= size()); return make_subspan(size() - count, dynamic_extent, subspan_selector{}); } constexpr span subspan(index_type offset, - index_type count = dynamic_extent) const noexcept + index_type count = dynamic_extent) const + noexcept { return make_subspan(offset, count, subspan_selector{}); } @@ -503,7 +509,7 @@ public: constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr reference operator[](index_type idx) const noexcept { Expects(CheckRange(idx, storage_.size())); @@ -512,23 +518,25 @@ public: constexpr reference front() const noexcept { - Expects(size() > 0); + Expects(size() != dynamic_extent && size() > 0); return data()[0]; } constexpr reference back() const noexcept { - Expects(size() > 0); + Expects(size() != dynamic_extent && size() > 0); return data()[size() - 1]; } - + // at and operator() are deprecated to align to the public member functions of std::span - [[deprecated("Use operator[]")]] - constexpr reference at(index_type idx) const noexcept{ return this->operator[](idx); } - [[deprecated("Use operator[]")]] - constexpr reference operator()(index_type idx) const noexcept{ return this->operator[](idx); } - - + [[deprecated("Use operator[]")]] constexpr reference at(index_type idx) const noexcept + { + return this->operator[](idx); + } + [[deprecated("Use operator[]")]] constexpr reference operator()(index_type idx) const noexcept + { + return this->operator[](idx); + } constexpr pointer data() const noexcept { return storage_.data(); } @@ -556,7 +564,7 @@ public: constexpr pointer _Unchecked_begin() const noexcept { return data(); } constexpr pointer _Unchecked_end() const noexcept { - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute return data() + size(); } #endif // _MSC_VER @@ -607,13 +615,13 @@ private: constexpr storage_type(KnownNotNull data, OtherExtentType ext) : ExtentType(ext), data_(data.p) { - Expects(ExtentType::size() >= 0); + Expects(ExtentType::size() != dynamic_extent); } template constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) { - Expects(ExtentType::size() >= 0); + Expects(ExtentType::size() != dynamic_extent); Expects(data || ExtentType::size() == 0); } @@ -629,12 +637,12 @@ private: // in subspans and constructors from arrays constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {} - template + template class subspan_selector { }; - template + template span make_subspan(index_type offset, index_type count, subspan_selector) const { @@ -642,56 +650,56 @@ private: return tmp.subspan(offset, count); } - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute span make_subspan(index_type offset, index_type count, subspan_selector) const { - Expects(offset >= 0 && size() - offset >= 0); + Expects(offset >= 0 && size() >= offset && size() != dynamic_extent); if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; } - Expects(count >= 0 && size() - offset >= count); + Expects(size() - offset >= count); return {KnownNotNull{data() + offset}, count}; } }; #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) -template +template constexpr const typename span::index_type span::extent; #endif // [span.comparison], span comparison operators -template +template constexpr bool operator==(span l, span r) { return std::equal(l.begin(), l.end(), r.begin(), r.end()); } -template +template constexpr bool operator!=(span l, span r) { return !(l == r); } -template +template constexpr bool operator<(span l, span r) { return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); } -template +template constexpr bool operator<=(span l, span r) { return !(l > r); } -template +template constexpr bool operator>(span l, span r) { return r < l; } -template +template constexpr bool operator>=(span l, span r) { return !(l < r); @@ -705,36 +713,33 @@ namespace details // we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as // constexpr // and so will fail compilation of the template - template - struct calculate_byte_size - : std::integral_constant(sizeof(ElementType) * - static_cast(Extent))> + template + struct calculate_byte_size : std::integral_constant { }; template struct calculate_byte_size - : std::integral_constant + : std::integral_constant { }; } // namespace details // [span.objectrep], views of object representation -template +template span::value> as_bytes(span s) noexcept { - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + GSL_SUPPRESS(type .1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } -template ::value>> span::value> as_writeable_bytes(span s) noexcept { - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + GSL_SUPPRESS(type .1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } @@ -773,7 +778,7 @@ constexpr span make_span(const Container& } template -constexpr span make_span(Ptr& cont, std::ptrdiff_t count) +constexpr span make_span(Ptr& cont, std::size_t count) { return span(cont, count); } @@ -785,7 +790,7 @@ constexpr span make_span(Ptr& cont) } // Specialization of gsl::at for span -template +template constexpr ElementType& at(span s, index i) { // No bounds checking here because it is done in span::operator[] called below @@ -793,57 +798,66 @@ constexpr ElementType& at(span s, index i) } // [span.obs] Free observer functions -template -constexpr typename span::index_type ssize(const span &span) noexcept +template +constexpr typename span::index_type +ssize(const span& span) noexcept { return span.size(); } // [span.iter] Free functions for begin/end functions -template -constexpr typename span::iterator begin(const span &span) noexcept +template +constexpr typename span::iterator +begin(const span& span) noexcept { return span.begin(); } -template -constexpr typename span::iterator end(const span &span) noexcept +template +constexpr typename span::iterator +end(const span& span) noexcept { return span.end(); } -template -constexpr typename span::const_iterator cbegin(const span &span) noexcept +template +constexpr typename span::const_iterator +cbegin(const span& span) noexcept { return span.cbegin(); } -template -constexpr typename span::const_iterator cend(const span &span) noexcept +template +constexpr typename span::const_iterator +cend(const span& span) noexcept { return span.cend(); } -template -constexpr typename span::reverse_iterator rbegin(const span &span) noexcept +template +constexpr typename span::reverse_iterator +rbegin(const span& span) noexcept { return span.rbegin(); } -template -constexpr typename span::reverse_iterator rend(const span &span) noexcept +template +constexpr typename span::reverse_iterator +rend(const span& span) noexcept { return span.rend(); } -template -constexpr typename span::const_reverse_iterator crbegin(const span &span) noexcept +template +constexpr typename span::const_reverse_iterator +crbegin(const span& span) noexcept { return span.crbegin(); } -template -constexpr typename span::const_reverse_iterator crend(const span &span) noexcept +template +constexpr typename span::const_reverse_iterator +crend(const span& span) noexcept { return span.crend(); } diff --git a/include/gsl/string_span b/include/gsl/string_span index 37cbe15..a1d2bb2 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -23,7 +23,7 @@ #include // for equal, lexicographical_compare #include // for array -#include // for ptrdiff_t, size_t, nullptr_t +#include // for size_t, nullptr_t #include // for PTRDIFF_MAX #include #include // for basic_string, allocator, char_traits @@ -56,43 +56,43 @@ namespace gsl // (sometimes needlessly) break existing programs when introduced. // -template +template using basic_zstring = CharT*; -template +template using czstring = basic_zstring; -template +template using cwzstring = basic_zstring; -template +template using cu16zstring = basic_zstring; -template +template using cu32zstring = basic_zstring; -template +template using zstring = basic_zstring; -template +template using wzstring = basic_zstring; -template +template using u16zstring = basic_zstring; -template +template using u32zstring = basic_zstring; namespace details { template - std::ptrdiff_t string_length(const CharT* str, std::ptrdiff_t n) + std::size_t string_length(const CharT* str, std::size_t n) { - if (str == nullptr || n <= 0) return 0; + if (str == nullptr || n == dynamic_extent) return 0; const span str_span{str, n}; - std::ptrdiff_t len = 0; + std::size_t len = 0; while (len < n && str_span[len]) len++; return len; @@ -108,18 +108,20 @@ namespace details // Will fail-fast if sentinel cannot be found before max elements are examined. // template -span ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX) +span ensure_sentinel(T* seq, + std::size_t max = std::numeric_limits::max()) { Ensures(seq != nullptr); - GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // TODO: false positive // TODO: suppress does not work + GSL_SUPPRESS( + f .23) // NO-FORMAT: attribute // TODO: false positive // TODO: suppress does not work auto cur = seq; Ensures(cur != nullptr); // workaround for removing the warning - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // TODO: suppress does not work - while ((cur - seq) < max && *cur != Sentinel) ++cur; + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute // TODO: suppress does not work + while (static_cast(cur - seq) < max && *cur != Sentinel) ++cur; Ensures(*cur == Sentinel); - return {seq, cur - seq}; + return {seq, static_cast(cur - seq)}; } // @@ -128,7 +130,8 @@ span ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX // the limit of size_type. // template -span ensure_z(CharT* const& sz, std::ptrdiff_t max = PTRDIFF_MAX) +span ensure_z(CharT* const& sz, + std::size_t max = std::numeric_limits::max()) { return ensure_sentinel(sz, max); } @@ -136,26 +139,27 @@ span ensure_z(CharT* const& sz, std::ptrdiff_t max = PTRD template span ensure_z(CharT (&sz)[N]) { - return ensure_z(&sz[0], narrow_cast(N)); + return ensure_z(&sz[0], N); } template span::type, dynamic_extent> ensure_z(Cont& cont) { - return ensure_z(cont.data(), narrow_cast(cont.size())); + return ensure_z(cont.data(), cont.size()); } -template +template class basic_string_span; -namespace details { +namespace details +{ template struct is_basic_string_span_oracle : std::false_type { }; - template + template struct is_basic_string_span_oracle> : std::true_type { }; @@ -169,7 +173,7 @@ namespace details { // // string_span and relatives // -template +template class basic_string_span { public: @@ -218,7 +222,7 @@ public: template // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug constexpr basic_string_span(std::basic_string& str) - : span_(&str[0], narrow_cast(str.length())) + : span_(&str[0], str.length()) {} template @@ -247,7 +251,7 @@ public: // from string_span template < - class OtherValueType, std::ptrdiff_t OtherExtent, + class OtherValueType, std::size_t OtherExtent, class = std::enable_if_t::impl_type, impl_type>::value>> constexpr basic_string_span(basic_string_span other) @@ -312,7 +316,7 @@ public: constexpr const_reverse_iterator crend() const noexcept { return span_.crend(); } private: - static impl_type remove_z(pointer const& sz, std::ptrdiff_t max) + static impl_type remove_z(pointer const& sz, std::size_t max) { return {sz, details::string_length(sz, max)}; } @@ -320,41 +324,41 @@ private: template static impl_type remove_z(element_type (&sz)[N]) { - return remove_z(&sz[0], narrow_cast(N)); + return remove_z(&sz[0], N); } impl_type span_; }; -template +template using string_span = basic_string_span; -template +template using cstring_span = basic_string_span; -template +template using wstring_span = basic_string_span; -template +template using cwstring_span = basic_string_span; -template +template using u16string_span = basic_string_span; -template +template using cu16string_span = basic_string_span; -template +template using u32string_span = basic_string_span; -template +template using cu32string_span = basic_string_span; // // to_string() allow (explicit) conversions from string_span to string // -template +template std::basic_string::type> to_string(basic_string_span view) { @@ -362,33 +366,34 @@ to_string(basic_string_span view) } template , - typename Allocator = std::allocator, typename gCharT, std::ptrdiff_t Extent> + typename Allocator = std::allocator, typename gCharT, std::size_t Extent> std::basic_string to_basic_string(basic_string_span view) { return {view.data(), narrow_cast(view.length())}; } -template +template basic_string_span::value> as_bytes(basic_string_span s) noexcept { - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + GSL_SUPPRESS(type .1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } -template ::value>> basic_string_span::value> as_writeable_bytes(basic_string_span s) noexcept { - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + GSL_SUPPRESS(type .1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } // zero-terminated string span, used to convert // zero-terminated spans to legacy strings -template -class basic_zstring_span { +template +class basic_zstring_span +{ public: using value_type = CharT; using const_value_type = std::add_const_t; @@ -435,32 +440,32 @@ private: impl_type span_; }; -template +template using zstring_span = basic_zstring_span; -template +template using wzstring_span = basic_zstring_span; -template +template using u16zstring_span = basic_zstring_span; -template +template using u32zstring_span = basic_zstring_span; -template +template using czstring_span = basic_zstring_span; -template +template using cwzstring_span = basic_zstring_span; -template +template using cu16zstring_span = basic_zstring_span; -template +template using cu32zstring_span = basic_zstring_span; // operator == -template ::value || std::is_convertible>>::value>> @@ -470,7 +475,7 @@ bool operator==(const gsl::basic_string_span& one, const T& other return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); } -template ::value && std::is_convertible>>::value>> @@ -481,7 +486,7 @@ bool operator==(const T& one, const gsl::basic_string_span& other } // operator != -template , Extent>>::value>> bool operator!=(gsl::basic_string_span one, const T& other) @@ -490,7 +495,7 @@ bool operator!=(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> @@ -500,7 +505,7 @@ bool operator!=(const T& one, gsl::basic_string_span other) } // operator< -template , Extent>>::value>> bool operator<(gsl::basic_string_span one, const T& other) @@ -510,7 +515,7 @@ bool operator<(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> @@ -526,7 +531,7 @@ bool operator<(const T& one, gsl::basic_string_span other) // so the cases below are already covered by the previous operators template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && @@ -540,7 +545,7 @@ bool operator<(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && @@ -555,7 +560,7 @@ bool operator<(const T& one, gsl::basic_string_span other) #endif // operator <= -template , Extent>>::value>> bool operator<=(gsl::basic_string_span one, const T& other) @@ -564,7 +569,7 @@ bool operator<=(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> @@ -579,7 +584,7 @@ bool operator<=(const T& one, gsl::basic_string_span other) // so the cases below are already covered by the previous operators template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && @@ -592,7 +597,7 @@ bool operator<=(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && @@ -606,7 +611,7 @@ bool operator<=(const T& one, gsl::basic_string_span other) #endif // operator> -template , Extent>>::value>> bool operator>(gsl::basic_string_span one, const T& other) @@ -615,7 +620,7 @@ bool operator>(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> @@ -630,7 +635,7 @@ bool operator>(const T& one, gsl::basic_string_span other) // so the cases below are already covered by the previous operators template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && @@ -643,7 +648,7 @@ bool operator>(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && @@ -657,7 +662,7 @@ bool operator>(const T& one, gsl::basic_string_span other) #endif // operator >= -template , Extent>>::value>> bool operator>=(gsl::basic_string_span one, const T& other) @@ -666,7 +671,7 @@ bool operator>=(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t< std::is_convertible, Extent>>::value && !gsl::details::is_basic_string_span::value>> @@ -681,7 +686,7 @@ bool operator>=(const T& one, gsl::basic_string_span other) // so the cases below are already covered by the previous operators template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && @@ -694,7 +699,7 @@ bool operator>=(gsl::basic_string_span one, const T& other) } template < - typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, + typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T, typename DataType = typename T::value_type, typename = std::enable_if_t< !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index c41e013..166d64f 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -158,14 +158,14 @@ TEST(span_test, from_pointer_length_constructor) int arr[4] = {1, 2, 3, 4}; { - for (int i = 0; i < 4; ++i) + for (std::size_t i = 0; i < 4; ++i) { { span s = {&arr[0], i}; EXPECT_TRUE(s.size() == i); EXPECT_TRUE(s.data() == &arr[0]); EXPECT_TRUE(s.empty() == (i == 0)); - for (int j = 0; j < i; ++j) + for (std::size_t j = 0; j < i; ++j) { EXPECT_TRUE(arr[j] == s[j]); EXPECT_TRUE(arr[j] == s.at(j)); @@ -173,12 +173,12 @@ TEST(span_test, from_pointer_length_constructor) } } { - span s = {&arr[i], 4 - narrow_cast(i)}; + span s = {&arr[i], 4 - i}; EXPECT_TRUE(s.size() == 4 - i); EXPECT_TRUE(s.data() == &arr[i]); EXPECT_TRUE(s.empty() == ((4 - i) == 0)); - for (int j = 0; j < 4 - i; ++j) + for (std::size_t j = 0; j < 4 - i; ++j) { EXPECT_TRUE(arr[j + i] == s[j]); EXPECT_TRUE(arr[j + i] == s.at(j)); @@ -457,21 +457,21 @@ TEST(span_test, from_array_constructor) { span s{arr}; - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); span cs{arr}; - EXPECT_TRUE(cs.size() == narrow_cast(arr.size())); + EXPECT_TRUE(cs.size() == arr.size()); EXPECT_TRUE(cs.data() == arr.data()); } { span s{arr}; - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); span cs{arr}; - EXPECT_TRUE(cs.size() == narrow_cast(arr.size())); + EXPECT_TRUE(cs.size() == arr.size()); EXPECT_TRUE(cs.data() == arr.data()); } @@ -486,7 +486,7 @@ TEST(span_test, from_array_constructor) { span fs{ao_arr}; - EXPECT_TRUE(fs.size() == narrow_cast(ao_arr.size())); + EXPECT_TRUE(fs.size() == ao_arr.size()); EXPECT_TRUE(ao_arr.data() == fs.data()); } @@ -532,7 +532,7 @@ TEST(span_test, from_array_constructor) { auto s = make_span(arr); - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } @@ -561,13 +561,13 @@ TEST(span_test, from_array_constructor) { span s{arr}; - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } { span s{arr}; - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } @@ -575,7 +575,7 @@ TEST(span_test, from_array_constructor) { span s{ao_arr}; - EXPECT_TRUE(s.size() == narrow_cast(ao_arr.size())); + EXPECT_TRUE(s.size() == ao_arr.size()); EXPECT_TRUE(s.data() == ao_arr.data()); } @@ -606,7 +606,7 @@ TEST(span_test, from_array_constructor) { auto s = make_span(arr); - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } } @@ -617,13 +617,13 @@ TEST(span_test, from_array_constructor) { span s{arr}; - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } { span s{arr}; - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } @@ -651,7 +651,7 @@ TEST(span_test, from_array_constructor) { auto s = make_span(arr); - EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.size() == arr.size()); EXPECT_TRUE(s.data() == arr.data()); } } @@ -663,11 +663,11 @@ TEST(span_test, from_array_constructor) { span s{v}; - EXPECT_TRUE(s.size() == narrow_cast(v.size())); + EXPECT_TRUE(s.size() == v.size()); EXPECT_TRUE(s.data() == v.data()); span cs{v}; - EXPECT_TRUE(cs.size() == narrow_cast(v.size())); + EXPECT_TRUE(cs.size() == v.size()); EXPECT_TRUE(cs.data() == v.data()); } @@ -677,11 +677,11 @@ TEST(span_test, from_array_constructor) { #ifdef CONFIRM_COMPILATION_ERRORS span s{str}; - EXPECT_TRUE(s.size() == narrow_cast(str.size())); + EXPECT_TRUE(s.size() == str.size()); EXPECT_TRUE(s.data() == str.data())); #endif span cs{str}; - EXPECT_TRUE(cs.size() == narrow_cast(str.size())); + EXPECT_TRUE(cs.size() == str.size()); EXPECT_TRUE(cs.data() == str.data()); } @@ -690,7 +690,7 @@ TEST(span_test, from_array_constructor) span s{cstr}; #endif span cs{cstr}; - EXPECT_TRUE(cs.size() == narrow_cast(cstr.size())); + EXPECT_TRUE(cs.size() == cstr.size()); EXPECT_TRUE(cs.data() == cstr.data()); } @@ -745,11 +745,11 @@ TEST(span_test, from_array_constructor) { auto s = make_span(v); - EXPECT_TRUE(s.size() == narrow_cast(v.size())); + EXPECT_TRUE(s.size() == v.size()); EXPECT_TRUE(s.data() == v.data()); auto cs = make_span(cv); - EXPECT_TRUE(cs.size() == narrow_cast(cv.size())); + EXPECT_TRUE(cs.size() == cv.size()); EXPECT_TRUE(cs.data() == cv.data()); } } From c31593dd0df8badff394ca81b2344f353774728e Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 11:01:24 -0800 Subject: [PATCH 18/81] updating from test loop from int to size_t --- tests/span_tests.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 166d64f..d94ed20 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -966,7 +966,7 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(av.subspan(5).size() == 0); EXPECT_DEATH(av.subspan(6).size(), deathstring); const auto av2 = av.subspan(1); - for (int i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); + for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); } { @@ -977,7 +977,7 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(av.subspan(5).size() == 0); EXPECT_DEATH(av.subspan(6).size(), deathstring); const auto av2 = av.subspan(1); - for (int i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); + for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); } } @@ -1067,28 +1067,28 @@ TEST(span_test, from_array_constructor) { int a[] = {1, 2, 3, 4}; span s{a}; - + EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); - + EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); - + EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); - + EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); - + EXPECT_TRUE(s.begin() == begin(s)); EXPECT_TRUE(s.end() == end(s)); - + EXPECT_TRUE(s.cbegin() == cbegin(s)); EXPECT_TRUE(s.cend() == cend(s)); - + EXPECT_TRUE(s.rbegin() == rbegin(s)); EXPECT_TRUE(s.rend() == rend(s)); - + EXPECT_TRUE(s.crbegin() == crbegin(s)); EXPECT_TRUE(s.crend() == crend(s)); } @@ -1097,7 +1097,7 @@ TEST(span_test, from_array_constructor) { int a[] = {1, 2, 3, 4}; span s{a}; - + EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE(s.size() == ssize(s)); } From ad71477183635a9fcd9f7d65d1a9b84ef4360997 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 12:26:15 -0800 Subject: [PATCH 19/81] fix build breaks --- include/gsl/gsl_algorithm | 4 ++-- include/gsl/span | 2 +- tests/span_tests.cpp | 4 ++-- tests/string_span_tests.cpp | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/gsl/gsl_algorithm b/include/gsl/gsl_algorithm index c2ba31f..6813b6c 100644 --- a/include/gsl/gsl_algorithm +++ b/include/gsl/gsl_algorithm @@ -37,8 +37,8 @@ namespace gsl { // Note: this will generate faster code than std::copy using span iterator in older msvc+stl // not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915) -template +template void copy(span src, span dest) { static_assert(std::is_assignable::value, diff --git a/include/gsl/span b/include/gsl/span index 1b06fb3..6e7e791 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -592,7 +592,7 @@ private: } else { - return idx >= 0 && idx < size; + return idx < size; } } diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index d94ed20..ac05af1 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -966,7 +966,7 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(av.subspan(5).size() == 0); EXPECT_DEATH(av.subspan(6).size(), deathstring); const auto av2 = av.subspan(1); - for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); + for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast(i) + 2); } { @@ -977,7 +977,7 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(av.subspan(5).size() == 0); EXPECT_DEATH(av.subspan(6).size(), deathstring); const auto av2 = av.subspan(1); - for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); + for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast(i) + 2); } } diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index e501bba..dd5a0de 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -84,7 +84,7 @@ czstring_span<> CreateTempName(string_span<> span) { Expects(span.size() > 1); - int last = 0; + std::size_t last = 0; if (span.size() > 4) { span[0] = 't'; span[1] = 'm'; @@ -101,7 +101,7 @@ cwzstring_span<> CreateTempNameW(wstring_span<> span) { Expects(span.size() > 1); - int last = 0; + std::size_t last = 0; if (span.size() > 4) { span[0] = L't'; span[1] = L'm'; @@ -118,7 +118,7 @@ cu16zstring_span<> CreateTempNameU16(u16string_span<> span) { Expects(span.size() > 1); - int last = 0; + std::size_t last = 0; if (span.size() > 4) { span[0] = u't'; span[1] = u'm'; @@ -135,7 +135,7 @@ cu32zstring_span<> CreateTempNameU32(u32string_span<> span) { Expects(span.size() > 1); - int last = 0; + std::size_t last = 0; if (span.size() > 4) { span[0] = U't'; span[1] = U'm'; From eabd9358f010ebe0c36b9238807a5a8fcaa002f6 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 12:46:37 -0800 Subject: [PATCH 20/81] addressing some comments --- include/gsl/span | 7 +++---- tests/span_tests.cpp | 5 ----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 6e7e791..52af1f7 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -25,7 +25,6 @@ #include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... -#include #include // for std::addressof #include #include // for enable_if_t, declval, is_convertible, inte... @@ -72,7 +71,7 @@ namespace gsl { // [views.constants], constants -constexpr const std::size_t dynamic_extent = std::numeric_limits::max(); +constexpr const std::size_t dynamic_extent = -1; template class span; @@ -476,7 +475,7 @@ public: typename details::calculate_subspan_type::type { Expects((size() >= Offset) && - (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size()))); + (Count == dynamic_extent || (Offset + Count <= size()))); return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; } @@ -654,7 +653,7 @@ private: span make_subspan(index_type offset, index_type count, subspan_selector) const { - Expects(offset >= 0 && size() >= offset && size() != dynamic_extent); + Expects(size() >= offset && size() != dynamic_extent); if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; } diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index ac05af1..8d9fadd 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -30,11 +30,6 @@ #include // for integral_constant<>::value, is_default_co... #include // for vector -namespace gsl -{ -struct fail_fast; -} // namespace gsl - using namespace std; using namespace gsl; From 5b8cf5422b0d5330acb033872fa64150eedf4c8d Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 12:49:57 -0800 Subject: [PATCH 21/81] casting -1 for dynamic extent --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 52af1f7..b060113 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -71,7 +71,7 @@ namespace gsl { // [views.constants], constants -constexpr const std::size_t dynamic_extent = -1; +constexpr const std::size_t dynamic_extent = static_cast(-1); template class span; From 17e372c155bb9e71981f42c42349cb7947eac817 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 13:45:56 -0800 Subject: [PATCH 22/81] Update include/gsl/span Co-Authored-By: Casey Carter --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index b060113..1483762 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -25,7 +25,7 @@ #include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... -#include // for std::addressof +#include // for std::addressof #include #include // for enable_if_t, declval, is_convertible, inte... #include From 9bb900e834ba915f2a2f3abbfc4b5ef3828236d6 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 13:46:18 -0800 Subject: [PATCH 23/81] Update include/gsl/span Co-Authored-By: Casey Carter --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 1483762..e96d644 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -475,7 +475,7 @@ public: typename details::calculate_subspan_type::type { Expects((size() >= Offset) && - (Count == dynamic_extent || (Offset + Count <= size()))); + (Count == dynamic_extent || (Count <= size() - Offset))); return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; } From a430823b43bc32f51022fe16fc23d6325dfe5fce Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 13:47:34 -0800 Subject: [PATCH 24/81] Update include/gsl/string_span Co-Authored-By: Casey Carter --- include/gsl/string_span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/string_span b/include/gsl/string_span index a1d2bb2..fc0dfeb 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -26,7 +26,7 @@ #include // for size_t, nullptr_t #include // for PTRDIFF_MAX #include -#include // for basic_string, allocator, char_traits +#include // for basic_string, allocator, char_traits #include // for declval, is_convertible, enable_if_t, add_... #if defined(_MSC_VER) && !defined(__clang__) From d0fdbdbffae2fb3f0cf2296d90749fc08e29517a Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 13:52:00 -0800 Subject: [PATCH 25/81] fixing suppress spacing --- include/gsl/span | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index b060113..2fb5bbd 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -152,7 +152,7 @@ namespace details : span_iterator(other.span_, other.index_) {} - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr reference operator*() const { Expects(static_cast(index_) != span_->size()); @@ -274,7 +274,7 @@ namespace details Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); } - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw @@ -289,7 +289,7 @@ namespace details #else static constexpr bool _Unwrap_when_unverified = false; #endif - GSL_SUPPRESS(con .3) // NO-FORMAT: attribute // TODO: false positive + GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped @@ -462,7 +462,7 @@ public: } template - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr span last() const noexcept { Expects(size() >= Count); @@ -470,7 +470,7 @@ public: } template - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr auto subspan() const noexcept -> typename details::calculate_subspan_type::type { @@ -508,7 +508,7 @@ public: constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr reference operator[](index_type idx) const noexcept { Expects(CheckRange(idx, storage_.size())); @@ -563,7 +563,7 @@ public: constexpr pointer _Unchecked_begin() const noexcept { return data(); } constexpr pointer _Unchecked_end() const noexcept { - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute return data() + size(); } #endif // _MSC_VER @@ -649,7 +649,7 @@ private: return tmp.subspan(offset, count); } - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute span make_subspan(index_type offset, index_type count, subspan_selector) const { @@ -729,7 +729,7 @@ template span::value> as_bytes(span s) noexcept { - GSL_SUPPRESS(type .1) // NO-FORMAT: attribute + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } @@ -738,7 +738,7 @@ template ::value> as_writeable_bytes(span s) noexcept { - GSL_SUPPRESS(type .1) // NO-FORMAT: attribute + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } From d9d6ea81966fba0905a1c311433cf4aea24ed357 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 13:53:38 -0800 Subject: [PATCH 26/81] remove comparison to dynamic_extent --- include/gsl/span | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 7c5b24d..377181c 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -517,13 +517,13 @@ public: constexpr reference front() const noexcept { - Expects(size() != dynamic_extent && size() > 0); + Expects(size() > 0); return data()[0]; } constexpr reference back() const noexcept { - Expects(size() != dynamic_extent && size() > 0); + Expects(size() > 0); return data()[size() - 1]; } From 1815791af8b6fb1aac55a2a6b371719456d4102a Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 16:26:36 -0800 Subject: [PATCH 27/81] Change iterator from Span* & ptrdiff_t to pointer, pointer, pointer --- include/gsl/span | 193 ++++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 84 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 377181c..5f66c6c 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -122,140 +122,165 @@ namespace details { }; - template + template class span_iterator { - using element_type_ = typename Span::element_type; - public: -#ifdef _MSC_VER - // Tell Microsoft standard library that span_iterators are checked. - using _Unchecked_type = typename Span::pointer; -#endif - using iterator_category = std::random_access_iterator_tag; - using value_type = std::remove_cv_t; - using difference_type = typename Span::index_type; + using value_type = std::remove_cv_t; + using difference_type = ptrdiff_t; + using pointer = std::add_pointer_t; + using reference = std::add_lvalue_reference_t; - using reference = std::conditional_t&; - using pointer = std::add_pointer_t; - - span_iterator() = default; - - constexpr span_iterator(const Span* span, difference_type idx) noexcept - : span_(span), index_(idx) - {} - - friend span_iterator; - template * = nullptr> - constexpr span_iterator(const span_iterator& other) noexcept - : span_iterator(other.span_, other.index_) - {} - - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - constexpr reference operator*() const +#ifdef _MSC_VER + using _Unchecked_type = typename pointer; +#endif + constexpr operator span_iterator() const noexcept { - Expects(static_cast(index_) != span_->size()); - return *(span_->data() + index_); + return {begin_, end_, current_}; } - constexpr pointer operator->() const - { - Expects(index_ != span_->size()); - return span_->data() + index_; - } + constexpr reference operator*() const noexcept { return *operator->(); } + constexpr pointer operator->() const noexcept + { + Expects(begin_ && current_ && end_); + Expects(current_ < end_); + return current_; + } constexpr span_iterator& operator++() noexcept { - Expects(0 <= index_ && static_cast(index_) != span_->size()); - ++index_; + Expects(begin_ && current_ && end_); + Expects(current_ < end_); + ++current_; return *this; } constexpr span_iterator operator++(int) noexcept { - auto ret = *this; - ++(*this); + auto ret{*this}; + ++*this; return ret; } constexpr span_iterator& operator--() noexcept { - Expects(index_ != 0 && static_cast(index_) <= span_->size()); - --index_; + Expects(begin_ && current_ && end_); + Expects(current_ > begin_); + --current_; return *this; } constexpr span_iterator operator--(int) noexcept { - auto ret = *this; - --(*this); + auto ret{*this}; + --*this; return ret; } - constexpr span_iterator operator+(difference_type n) const noexcept + constexpr span_iterator& operator+=(const difference_type n) noexcept { - auto ret = *this; + Expects(begin_ && current_ && end_); + if (n > 0) Expects(end_ - current_ >= n); + if (n < 0) Expects(end_ - current_ >= -n); + current_ += n; + return *this; + } + + constexpr span_iterator operator+(const difference_type n) const noexcept + { + auto ret{*this}; return ret += n; } - friend constexpr span_iterator operator+(difference_type n, + friend constexpr span_iterator operator+(const difference_type n, span_iterator const& rhs) noexcept { return rhs + n; } - constexpr span_iterator& operator+=(difference_type n) noexcept + constexpr span_iterator& operator-=(const difference_type n) noexcept { - Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); - index_ += n; + Expects(begin_ && end_ && current_); + if (n > 0) Expects(end_ - current_ >= n); + if (n < 0) Expects(end_ - current_ >= -n); + current_ -= n; return *this; } - constexpr span_iterator operator-(difference_type n) const noexcept + constexpr span_iterator operator-(const difference_type n) const noexcept { - auto ret = *this; + auto ret{*this}; return ret -= n; } - constexpr span_iterator& operator-=(difference_type n) noexcept { return *this += -n; } - - constexpr difference_type operator-(span_iterator rhs) const noexcept + friend constexpr span_iterator operator-(const difference_type n, + span_iterator const& rhs) noexcept { - Expects(span_ == rhs.span_); - return index_ - rhs.index_; + return rhs - n; } - constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); } - - constexpr friend bool operator==(span_iterator lhs, span_iterator rhs) noexcept + template < + class type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr difference_type operator-(const span_iterator& rhs) const noexcept { - return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_; + Expects(begin_ == rhs.begin_); + return current_ - rhs.current_; } - constexpr friend bool operator!=(span_iterator lhs, span_iterator rhs) noexcept + constexpr reference operator[](const difference_type n) const noexcept { - return !(lhs == rhs); + return *(*this + n); } - constexpr friend bool operator<(span_iterator lhs, span_iterator rhs) noexcept + template < + class type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator==(const span_iterator& rhs) const noexcept { - return lhs.index_ < rhs.index_; + return begin_ == rhs.begin_ && current_ == rhs.current_; } - constexpr friend bool operator<=(span_iterator lhs, span_iterator rhs) noexcept + template < + class type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator!=(const span_iterator& rhs) const noexcept { - return !(rhs < lhs); + return !(*this == rhs); } - constexpr friend bool operator>(span_iterator lhs, span_iterator rhs) noexcept + template < + class type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator<(const span_iterator& rhs) const noexcept { - return rhs < lhs; + Expects(begin_ == rhs.begin_); + return current_ < rhs.current_; } - constexpr friend bool operator>=(span_iterator lhs, span_iterator rhs) noexcept + template < + class type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator>(const span_iterator& rhs) const noexcept { - return !(rhs > lhs); + return !(*this < rhs); + } + + template < + class type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator<=(const span_iterator& rhs) const noexcept + { + return *this < rhs || *this == rhs; + } + + template < + class type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator>=(const span_iterator& rhs) const noexcept + { + return *this > rhs || *this == rhs; } #ifdef _MSC_VER @@ -264,14 +289,14 @@ namespace details // algorithm calls friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept { // test that [lhs, rhs) forms a valid range inside an STL algorithm - Expects(lhs.span_ == rhs.span_ // range spans have to match - && lhs.index_ <= rhs.index_); // range must not be transposed + Expects(lhs.begin_ == rhs.begin_ // range spans have to match + && lhs.end_ <= rhs.end_); // range must not be transposed } constexpr void _Verify_offset(const difference_type n) const noexcept { // test that the iterator *this + n is a valid range in an STL // algorithm call - Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); + Expects((current_ + n) >= begin_ && (current_ + n) <= end_); } GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute @@ -279,7 +304,7 @@ namespace details { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw // pointer - return span_->data() + index_; + return current_; } // Tell the STL that span_iterator should not be unwrapped if it can't @@ -293,13 +318,13 @@ namespace details constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped - index_ = p - span_->data(); + current_ = p; } #endif - protected: - const Span* span_ = nullptr; - std::ptrdiff_t index_ = 0; + pointer begin_ = nullptr; + pointer end_ = nullptr; + pointer current_ = nullptr; }; template @@ -368,8 +393,8 @@ public: using reference = element_type&; using difference_type = std::ptrdiff_t; - using iterator = details::span_iterator, false>; - using const_iterator = details::span_iterator, true>; + using iterator = details::span_iterator; + using const_iterator = details::span_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; @@ -540,11 +565,11 @@ public: constexpr pointer data() const noexcept { return storage_.data(); } // [span.iter], span iterator support - constexpr iterator begin() const noexcept { return {this, 0}; } - constexpr iterator end() const noexcept { return {this, size()}; } + constexpr iterator begin() const noexcept { return {data(), data() + size(), data()}; } + constexpr iterator end() const noexcept { return {data(), data() + size(), data() + size()}; } - constexpr const_iterator cbegin() const noexcept { return {this, 0}; } - constexpr const_iterator cend() const noexcept { return {this, size()}; } + constexpr const_iterator cbegin() const noexcept { return {data(), data() + size(), data()}; } + constexpr const_iterator cend() const noexcept { return {data(), data() + size(), data() + size()}; } constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } @@ -653,7 +678,7 @@ private: span make_subspan(index_type offset, index_type count, subspan_selector) const { - Expects(size() >= offset && size() != dynamic_extent); + Expects(size() >= offset); if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; } From f4ee6ee73b99ca8586e25c56ed627320144dd55f Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 17:51:25 -0800 Subject: [PATCH 28/81] Update include/gsl/span Co-Authored-By: Casey Carter --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 5f66c6c..4966961 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -294,7 +294,7 @@ namespace details } constexpr void _Verify_offset(const difference_type n) const noexcept - { // test that the iterator *this + n is a valid range in an STL + { // test that *this + n is within the span of this iterator STL // algorithm call Expects((current_ + n) >= begin_ && (current_ + n) <= end_); } From 24646c6f7cef01c817ae3af666efe54c362d5b51 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 17:51:45 -0800 Subject: [PATCH 29/81] Update include/gsl/span Co-Authored-By: Casey Carter --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 4966961..5900da5 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -128,7 +128,7 @@ namespace details public: using iterator_category = std::random_access_iterator_tag; using value_type = std::remove_cv_t; - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = std::add_pointer_t; using reference = std::add_lvalue_reference_t; From 827fafd32c9da89bd521bac9c91a0d6e37be2f1d Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:12:32 -0800 Subject: [PATCH 30/81] Update include/gsl/span Co-Authored-By: Casey Carter --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 5900da5..c480f18 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -182,7 +182,7 @@ namespace details { Expects(begin_ && current_ && end_); if (n > 0) Expects(end_ - current_ >= n); - if (n < 0) Expects(end_ - current_ >= -n); + if (n < 0) Expects(current_ - begin_ >= -n); current_ += n; return *this; } From 81c2a1da15285d5cba3297caf3ad29bd09d0925c Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:12:57 -0800 Subject: [PATCH 31/81] addressing feedback --- include/gsl/span | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 5f66c6c..ef7580c 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -333,7 +333,7 @@ namespace details public: using index_type = std::size_t; - static_assert(Ext >= 0, "A fixed-size span must be >= 0 in size."); + static_assert(Ext != dynamic_extent, "A fixed-size span must be >= 0 in size."); constexpr extent_type() noexcept {} @@ -417,7 +417,7 @@ public: constexpr span(pointer ptr, index_type count) noexcept : storage_(ptr, count) {} constexpr span(pointer firstElem, pointer lastElem) noexcept - : storage_(firstElem, std::distance(firstElem, lastElem)) + : storage_(firstElem, static_cast(std::distance(firstElem, lastElem))) {} template @@ -536,7 +536,7 @@ public: GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr reference operator[](index_type idx) const noexcept { - Expects(CheckRange(idx, storage_.size())); + Expects(idx < size()); return data()[idx]; } @@ -594,32 +594,6 @@ public: #endif // _MSC_VER private: - static constexpr bool CheckRange(index_type idx, index_type size) noexcept - { - // Optimization: - // - // idx >= 0 && idx < size - // => - // static_cast(idx) < static_cast(size) - // - // because size >=0 by span construction, and negative idx will - // wrap around to a value always greater than size when casted. - - // check if we have enough space to wrap around -#if defined(__cpp_if_constexpr) - if constexpr (sizeof(index_type) <= sizeof(size_t)) -#else - if (sizeof(index_type) <= sizeof(size_t)) -#endif - { - return narrow_cast(idx) < narrow_cast(size); - } - else - { - return idx < size; - } - } - // Needed to remove unnecessary null check in subspans struct KnownNotNull { From e0dc8095b3eb30ec4e75bac0b846f612d36d08ef Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:13:14 -0800 Subject: [PATCH 32/81] addressing feedback --- include/gsl/span | 114 ++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index ef7580c..4f3b018 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -71,7 +71,7 @@ namespace gsl { // [views.constants], constants -constexpr const std::size_t dynamic_extent = static_cast(-1); +constexpr std::size_t dynamic_extent = static_cast(-1); template class span; @@ -122,25 +122,30 @@ namespace details { }; - template + template class span_iterator { public: using iterator_category = std::random_access_iterator_tag; - using value_type = std::remove_cv_t; - using difference_type = ptrdiff_t; - using pointer = std::add_pointer_t; - using reference = std::add_lvalue_reference_t; + using value_type = std::remove_cv_t; + using difference_type = std::ptrdiff_t; + using pointer = Type*; + using reference = Type&; #ifdef _MSC_VER - using _Unchecked_type = typename pointer; + using _Unchecked_type = pointer; #endif - constexpr operator span_iterator() const noexcept + constexpr operator span_iterator() const noexcept { return {begin_, end_, current_}; } - constexpr reference operator*() const noexcept { return *operator->(); } + constexpr reference operator*() const noexcept + { + Expects(begin_ && current_ && end_); + Expects(current_ < end_); + return *current_; + } constexpr pointer operator->() const noexcept { @@ -194,7 +199,7 @@ namespace details } friend constexpr span_iterator operator+(const difference_type n, - span_iterator const& rhs) noexcept + const span_iterator& rhs) noexcept { return rhs + n; } @@ -214,18 +219,12 @@ namespace details return ret -= n; } - friend constexpr span_iterator operator-(const difference_type n, - span_iterator const& rhs) noexcept - { - return rhs - n; - } - template < - class type2, - std::enable_if_t, value_type>::value, int> = 0> - constexpr difference_type operator-(const span_iterator& rhs) const noexcept + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr difference_type operator-(const span_iterator& rhs) const noexcept { - Expects(begin_ == rhs.begin_); + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); return current_ - rhs.current_; } @@ -235,52 +234,52 @@ namespace details } template < - class type2, - std::enable_if_t, value_type>::value, int> = 0> - constexpr bool operator==(const span_iterator& rhs) const noexcept + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator==(const span_iterator& rhs) const noexcept { - return begin_ == rhs.begin_ && current_ == rhs.current_; + return begin_ == rhs.begin_ && end_ == rhs.end_ && current_ == rhs.current_; } template < - class type2, - std::enable_if_t, value_type>::value, int> = 0> - constexpr bool operator!=(const span_iterator& rhs) const noexcept + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator!=(const span_iterator& rhs) const noexcept { return !(*this == rhs); } template < - class type2, - std::enable_if_t, value_type>::value, int> = 0> - constexpr bool operator<(const span_iterator& rhs) const noexcept + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator<(const span_iterator& rhs) const noexcept { - Expects(begin_ == rhs.begin_); + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); return current_ < rhs.current_; } template < - class type2, - std::enable_if_t, value_type>::value, int> = 0> - constexpr bool operator>(const span_iterator& rhs) const noexcept + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator>(const span_iterator& rhs) const noexcept { return !(*this < rhs); } template < - class type2, - std::enable_if_t, value_type>::value, int> = 0> - constexpr bool operator<=(const span_iterator& rhs) const noexcept + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator<=(const span_iterator& rhs) const noexcept { - return *this < rhs || *this == rhs; + return !(*this > rhs); } template < - class type2, - std::enable_if_t, value_type>::value, int> = 0> - constexpr bool operator>=(const span_iterator& rhs) const noexcept + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator>=(const span_iterator& rhs) const noexcept { - return *this > rhs || *this == rhs; + return *!(this < rhs); } #ifdef _MSC_VER @@ -289,8 +288,9 @@ namespace details // algorithm calls friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept { // test that [lhs, rhs) forms a valid range inside an STL algorithm - Expects(lhs.begin_ == rhs.begin_ // range spans have to match - && lhs.end_ <= rhs.end_); // range must not be transposed + Expects(lhs.begin_ == rhs.begin_ // range spans have to match + && lhs.end_ == rhs.end_ && + lhs.current_ <= rhs.current_); // range must not be transposed } constexpr void _Verify_offset(const difference_type n) const noexcept @@ -299,7 +299,7 @@ namespace details Expects((current_ + n) >= begin_ && (current_ + n) <= end_); } - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw @@ -314,7 +314,7 @@ namespace details #else static constexpr bool _Unwrap_when_unverified = false; #endif - GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive + GSL_SUPPRESS(con .3) // NO-FORMAT: attribute // TODO: false positive constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped @@ -487,7 +487,7 @@ public: } template - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr span last() const noexcept { Expects(size() >= Count); @@ -495,12 +495,11 @@ public: } template - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr auto subspan() const noexcept -> typename details::calculate_subspan_type::type { - Expects((size() >= Offset) && - (Count == dynamic_extent || (Count <= size() - Offset))); + Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset))); return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; } @@ -533,7 +532,7 @@ public: constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute constexpr reference operator[](index_type idx) const noexcept { Expects(idx < size()); @@ -569,7 +568,10 @@ public: constexpr iterator end() const noexcept { return {data(), data() + size(), data() + size()}; } constexpr const_iterator cbegin() const noexcept { return {data(), data() + size(), data()}; } - constexpr const_iterator cend() const noexcept { return {data(), data() + size(), data() + size()}; } + constexpr const_iterator cend() const noexcept + { + return {data(), data() + size(), data() + size()}; + } constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } @@ -588,7 +590,7 @@ public: constexpr pointer _Unchecked_begin() const noexcept { return data(); } constexpr pointer _Unchecked_end() const noexcept { - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute return data() + size(); } #endif // _MSC_VER @@ -648,7 +650,7 @@ private: return tmp.subspan(offset, count); } - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute span make_subspan(index_type offset, index_type count, subspan_selector) const { @@ -728,7 +730,7 @@ template span::value> as_bytes(span s) noexcept { - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + GSL_SUPPRESS(type .1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } @@ -737,7 +739,7 @@ template ::value> as_writeable_bytes(span s) noexcept { - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + GSL_SUPPRESS(type .1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } From 877816faa4090cbf2d4081397a71e7f24acc0b09 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:16:41 -0800 Subject: [PATCH 33/81] addressing feedback --- include/gsl/string_span | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gsl/string_span b/include/gsl/string_span index fc0dfeb..269f9b3 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -109,7 +109,7 @@ namespace details // template span ensure_sentinel(T* seq, - std::size_t max = std::numeric_limits::max()) + std::size_t max = static_cast(-1)) { Ensures(seq != nullptr); @@ -131,7 +131,7 @@ span ensure_sentinel(T* seq, // template span ensure_z(CharT* const& sz, - std::size_t max = std::numeric_limits::max()) + std::size_t max = static_cast(-1)) { return ensure_sentinel(sz, max); } From 592c28c6d1c8259af0c8d67b22b5030537f163cf Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:18:14 -0800 Subject: [PATCH 34/81] fixing spaces in gsl_suppress --- include/gsl/span | 18 +++++++++--------- include/gsl/string_span | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index f5e850a..16add83 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -299,7 +299,7 @@ namespace details Expects((current_ + n) >= begin_ && (current_ + n) <= end_); } - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw @@ -314,7 +314,7 @@ namespace details #else static constexpr bool _Unwrap_when_unverified = false; #endif - GSL_SUPPRESS(con .3) // NO-FORMAT: attribute // TODO: false positive + GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped @@ -487,7 +487,7 @@ public: } template - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr span last() const noexcept { Expects(size() >= Count); @@ -495,7 +495,7 @@ public: } template - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr auto subspan() const noexcept -> typename details::calculate_subspan_type::type { @@ -532,7 +532,7 @@ public: constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr reference operator[](index_type idx) const noexcept { Expects(idx < size()); @@ -590,7 +590,7 @@ public: constexpr pointer _Unchecked_begin() const noexcept { return data(); } constexpr pointer _Unchecked_end() const noexcept { - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute return data() + size(); } #endif // _MSC_VER @@ -650,7 +650,7 @@ private: return tmp.subspan(offset, count); } - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute span make_subspan(index_type offset, index_type count, subspan_selector) const { @@ -730,7 +730,7 @@ template span::value> as_bytes(span s) noexcept { - GSL_SUPPRESS(type .1) // NO-FORMAT: attribute + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } @@ -739,7 +739,7 @@ template ::value> as_writeable_bytes(span s) noexcept { - GSL_SUPPRESS(type .1) // NO-FORMAT: attribute + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } diff --git a/include/gsl/string_span b/include/gsl/string_span index 269f9b3..c4752db 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -114,11 +114,11 @@ span ensure_sentinel(T* seq, Ensures(seq != nullptr); GSL_SUPPRESS( - f .23) // NO-FORMAT: attribute // TODO: false positive // TODO: suppress does not work + f.23) // NO-FORMAT: attribute // TODO: false positive // TODO: suppress does not work auto cur = seq; Ensures(cur != nullptr); // workaround for removing the warning - GSL_SUPPRESS(bounds .1) // NO-FORMAT: attribute // TODO: suppress does not work + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // TODO: suppress does not work while (static_cast(cur - seq) < max && *cur != Sentinel) ++cur; Ensures(*cur == Sentinel); return {seq, static_cast(cur - seq)}; @@ -376,7 +376,7 @@ template basic_string_span::value> as_bytes(basic_string_span s) noexcept { - GSL_SUPPRESS(type .1) // NO-FORMAT: attribute + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } @@ -385,7 +385,7 @@ template ::value> as_writeable_bytes(basic_string_span s) noexcept { - GSL_SUPPRESS(type .1) // NO-FORMAT: attribute + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; } From 49e7ed1ebfcf80fcfd60c53d35f7a782b6e030a3 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:27:09 -0800 Subject: [PATCH 35/81] updating comparisons --- include/gsl/span | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 16add83..170c746 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -271,7 +271,7 @@ namespace details std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator<=(const span_iterator& rhs) const noexcept { - return !(*this > rhs); + return !(rhs < *this); } template < @@ -279,7 +279,7 @@ namespace details std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator>=(const span_iterator& rhs) const noexcept { - return *!(this < rhs); + return !(*this < rhs); } #ifdef _MSC_VER From 4ec7058b560b0767222fdba9c0f114ebcd58db87 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:31:21 -0800 Subject: [PATCH 36/81] Update include/gsl/span Co-Authored-By: Casey Carter --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 170c746..09a10a9 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -263,7 +263,7 @@ namespace details std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator>(const span_iterator& rhs) const noexcept { - return !(*this < rhs); + return rhs < *this; } template < From e9fea77bcb0608718b14dfa21cb9428244e4d46b Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:31:50 -0800 Subject: [PATCH 37/81] Update include/gsl/span Co-Authored-By: Casey Carter --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 09a10a9..62ea0a0 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -207,7 +207,7 @@ namespace details constexpr span_iterator& operator-=(const difference_type n) noexcept { Expects(begin_ && end_ && current_); - if (n > 0) Expects(end_ - current_ >= n); + if (n > 0) Expects(current_ - begin_ >= n); if (n < 0) Expects(end_ - current_ >= -n); current_ -= n; return *this; From 0c6ce424abe6a75c90d8c3c038736cd12af75b18 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 4 Feb 2020 12:01:27 -0800 Subject: [PATCH 38/81] refactoring index_type to size_type, changing expects --- include/gsl/span | 91 ++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 09a10a9..83a2e02 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -296,7 +296,7 @@ namespace details constexpr void _Verify_offset(const difference_type n) const noexcept { // test that *this + n is within the span of this iterator STL // algorithm call - Expects((current_ + n) >= begin_ && (current_ + n) <= end_); + Expects( n <= (current_ - begin_) && n <= (end_ - current_)); } GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute @@ -331,13 +331,13 @@ namespace details class extent_type { public: - using index_type = std::size_t; + using size_type = std::size_t; static_assert(Ext != dynamic_extent, "A fixed-size span must be >= 0 in size."); constexpr extent_type() noexcept {} - template + template constexpr extent_type(extent_type ext) { static_assert(Other == Ext || Other == dynamic_extent, @@ -345,30 +345,30 @@ namespace details Expects(ext.size() == Ext); } - constexpr extent_type(index_type size) { Expects(size == Ext); } + constexpr extent_type(size_type size) { Expects(size == Ext); } - constexpr index_type size() const noexcept { return Ext; } + constexpr size_type size() const noexcept { return Ext; } }; template <> class extent_type { public: - using index_type = std::size_t; + using size_type = std::size_t; - template + template explicit constexpr extent_type(extent_type ext) : size_(ext.size()) {} - explicit constexpr extent_type(index_type size) : size_(size) + explicit constexpr extent_type(size_type size) : size_(size) { Expects(size != dynamic_extent); } - constexpr index_type size() const noexcept { return size_; } + constexpr size_type size() const noexcept { return size_; } private: - index_type size_; + size_type size_; }; template @@ -388,7 +388,7 @@ public: // constants and types using element_type = ElementType; using value_type = std::remove_cv_t; - using index_type = std::size_t; + using size_type = std::size_t; using pointer = element_type*; using reference = element_type&; using difference_type = std::ptrdiff_t; @@ -398,12 +398,12 @@ public: using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - using size_type = index_type; + using index_type [[deprecated("use size_type instead of index_type")]] = size_type; #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) - static constexpr const index_type extent{Extent}; + static constexpr const size_type extent{Extent}; #else - static constexpr index_type extent{Extent}; + static constexpr size_type extent{Extent}; #endif // [span.cons], span constructors, copy, assignment, and destructor @@ -414,7 +414,7 @@ public: constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) {} - constexpr span(pointer ptr, index_type count) noexcept : storage_(ptr, count) {} + constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count) {} constexpr span(pointer firstElem, pointer lastElem) noexcept : storage_(firstElem, static_cast(std::distance(firstElem, lastElem))) @@ -451,7 +451,7 @@ public: std::is_convertible::value && std::is_convertible().data())>::value>> - constexpr span(Container& cont) noexcept : span(cont.data(), narrow(cont.size())) + constexpr span(Container& cont) noexcept : span(cont.data(), narrow(cont.size())) {} template ().data())>::value>> constexpr span(const Container& cont) noexcept - : span(cont.data(), narrow(cont.size())) + : span(cont.data(), narrow(cont.size())) {} constexpr span(const span& other) noexcept = default; @@ -504,36 +504,36 @@ public: return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; } - constexpr span first(index_type count) const noexcept + constexpr span first(size_type count) const noexcept { Expects(count <= size()); return {data(), count}; } - constexpr span last(index_type count) const noexcept + constexpr span last(size_type count) const noexcept { Expects(count <= size()); return make_subspan(size() - count, dynamic_extent, subspan_selector{}); } - constexpr span subspan(index_type offset, - index_type count = dynamic_extent) const + constexpr span subspan(size_type offset, + size_type count = dynamic_extent) const noexcept { return make_subspan(offset, count, subspan_selector{}); } // [span.obs], span observers - constexpr index_type size() const noexcept { return storage_.size(); } - constexpr index_type size_bytes() const noexcept + constexpr size_type size() const noexcept { return storage_.size(); } + constexpr size_type size_bytes() const noexcept { - return size() * narrow_cast(sizeof(element_type)); + return size() * narrow_cast(sizeof(element_type)); } constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - constexpr reference operator[](index_type idx) const noexcept + constexpr reference operator[](size_type idx) const noexcept { Expects(idx < size()); return data()[idx]; @@ -552,11 +552,11 @@ public: } // at and operator() are deprecated to align to the public member functions of std::span - [[deprecated("Use operator[]")]] constexpr reference at(index_type idx) const noexcept + [[deprecated("Use operator[]")]] constexpr reference at(size_type idx) const noexcept { return this->operator[](idx); } - [[deprecated("Use operator[]")]] constexpr reference operator()(index_type idx) const noexcept + [[deprecated("Use operator[]")]] constexpr reference operator()(size_type idx) const noexcept { return this->operator[](idx); } @@ -564,13 +564,30 @@ public: constexpr pointer data() const noexcept { return storage_.data(); } // [span.iter], span iterator support - constexpr iterator begin() const noexcept { return {data(), data() + size(), data()}; } - constexpr iterator end() const noexcept { return {data(), data() + size(), data() + size()}; } + constexpr iterator begin() const noexcept + { + const auto data = storage_.data(); + return {data, data + size(), data}; + } + + constexpr iterator end() const noexcept + { + const auto data = storage_.data(); + const auto size = storage_.size(); + return {data, data + size, data + size}; + } + + constexpr const_iterator cbegin() const noexcept + { + const auto data = storage_.data(); + return {data, data + size(), data}; + } - constexpr const_iterator cbegin() const noexcept { return {data(), data() + size(), data()}; } constexpr const_iterator cend() const noexcept { - return {data(), data() + size(), data() + size()}; + const auto data = storage_.data(); + const auto size = storage_.size(); + return {data, data + size, data + size}; } constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } @@ -635,7 +652,7 @@ private: // The rest is needed to remove unnecessary null check // in subspans and constructors from arrays - constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {} + constexpr span(KnownNotNull ptr, size_type count) : storage_(ptr, count) {} template class subspan_selector @@ -643,7 +660,7 @@ private: }; template - span make_subspan(index_type offset, index_type count, + span make_subspan(size_type offset, size_type count, subspan_selector) const { const span tmp(*this); @@ -651,7 +668,7 @@ private: } GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - span make_subspan(index_type offset, index_type count, + span make_subspan(size_type offset, size_type count, subspan_selector) const { Expects(size() >= offset); @@ -665,7 +682,7 @@ private: #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) template -constexpr const typename span::index_type span::extent; +constexpr const typename span::size_type span::extent; #endif // [span.comparison], span comparison operators @@ -748,7 +765,7 @@ as_writeable_bytes(span s) noexcept // template constexpr span make_span(ElementType* ptr, - typename span::index_type count) + typename span::size_type count) { return span(ptr, count); } @@ -799,7 +816,7 @@ constexpr ElementType& at(span s, index i) // [span.obs] Free observer functions template -constexpr typename span::index_type +constexpr typename span::size_type ssize(const span& span) noexcept { return span.size(); From 61c6ef8d426dd4869789be9b8432c6cb4454a8bb Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 4 Feb 2020 13:30:03 -0800 Subject: [PATCH 39/81] remove index_type from string_span, update comments --- include/gsl/span | 11 +++++------ include/gsl/string_span | 30 ++++++++++++++---------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index c919f38..737ef80 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -185,7 +185,7 @@ namespace details constexpr span_iterator& operator+=(const difference_type n) noexcept { - Expects(begin_ && current_ && end_); + if (n != 0) Expects(begin_ && current_ && end_); if (n > 0) Expects(end_ - current_ >= n); if (n < 0) Expects(current_ - begin_ >= -n); current_ += n; @@ -206,7 +206,7 @@ namespace details constexpr span_iterator& operator-=(const difference_type n) noexcept { - Expects(begin_ && end_ && current_); + if (n != 0) Expects(begin_ && current_ && end_); if (n > 0) Expects(current_ - begin_ >= n); if (n < 0) Expects(end_ - current_ >= -n); current_ -= n; @@ -294,8 +294,7 @@ namespace details } constexpr void _Verify_offset(const difference_type n) const noexcept - { // test that *this + n is within the span of this iterator STL - // algorithm call + { // test that *this + n is within the range of this call Expects( n <= (current_ - begin_) && n <= (end_ - current_)); } @@ -408,8 +407,8 @@ public: // [span.cons], span constructors, copy, assignment, and destructor template " SFINAE, - // since "std::enable_if_t" is ill-formed when Extent is greater than 0. + // "Dependent" is needed to make "std::enable_if_t" SFINAE, + // since "std::enable_if_t" is ill-formed when Extent is greater than 0. class = std::enable_if_t<(Dependent || Extent == 0 || Extent == dynamic_extent)>> constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) {} diff --git a/include/gsl/string_span b/include/gsl/string_span index c4752db..27b8977 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -184,14 +184,12 @@ public: using const_reference = std::add_lvalue_reference_t>; using impl_type = span; - using index_type = typename impl_type::index_type; + using size_type = typename impl_type::size_type; using iterator = typename impl_type::iterator; using const_iterator = typename impl_type::const_iterator; using reverse_iterator = typename impl_type::reverse_iterator; using const_reverse_iterator = typename impl_type::const_reverse_iterator; - using size_type = index_type; - // default (empty) constexpr basic_string_span() noexcept = default; @@ -201,7 +199,7 @@ public: // assign constexpr basic_string_span& operator=(const basic_string_span& other) noexcept = default; - constexpr basic_string_span(pointer ptr, index_type length) : span_(ptr, length) {} + constexpr basic_string_span(pointer ptr, size_type length) : span_(ptr, length) {} constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {} // From static arrays - if 0-terminated, remove 0 from the view @@ -258,49 +256,49 @@ public: : span_(other.data(), other.length()) {} - template + template constexpr basic_string_span first() const { return {span_.template first()}; } - constexpr basic_string_span first(index_type count) const + constexpr basic_string_span first(size_type count) const { return {span_.first(count)}; } - template + template constexpr basic_string_span last() const { return {span_.template last()}; } - constexpr basic_string_span last(index_type count) const + constexpr basic_string_span last(size_type count) const { return {span_.last(count)}; } - template + template constexpr basic_string_span subspan() const { return {span_.template subspan()}; } constexpr basic_string_span - subspan(index_type offset, index_type count = dynamic_extent) const + subspan(size_type offset, size_type count = dynamic_extent) const { return {span_.subspan(offset, count)}; } - constexpr reference operator[](index_type idx) const { return span_[idx]; } - constexpr reference operator()(index_type idx) const { return span_[idx]; } + constexpr reference operator[](size_type idx) const { return span_[idx]; } + constexpr reference operator()(size_type idx) const { return span_[idx]; } constexpr pointer data() const { return span_.data(); } - constexpr index_type length() const noexcept { return span_.size(); } - constexpr index_type size() const noexcept { return span_.size(); } - constexpr index_type size_bytes() const noexcept { return span_.size_bytes(); } - constexpr index_type length_bytes() const noexcept { return span_.length_bytes(); } + constexpr size_type length() const noexcept { return span_.size(); } + constexpr size_type size() const noexcept { return span_.size(); } + constexpr size_type size_bytes() const noexcept { return span_.size_bytes(); } + constexpr size_type length_bytes() const noexcept { return span_.length_bytes(); } constexpr bool empty() const noexcept { return size() == 0; } constexpr iterator begin() const noexcept { return span_.begin(); } From 5a1e4f39537330c579662a76a9a9b5c8580ad708 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 4 Feb 2020 15:31:33 -0800 Subject: [PATCH 40/81] update index_type to size_type, fix a couple Expects --- include/gsl/span | 10 ++++++---- tests/span_tests.cpp | 14 +++++++------- tests/string_span_tests.cpp | 8 ++++---- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 737ef80..5049b97 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -143,14 +143,14 @@ namespace details constexpr reference operator*() const noexcept { Expects(begin_ && current_ && end_); - Expects(current_ < end_); + Expects(begin_ <= current_ && current_ < end_); return *current_; } constexpr pointer operator->() const noexcept { Expects(begin_ && current_ && end_); - Expects(current_ < end_); + Expects(begin_ <= current_ && current_ < end_); return current_; } constexpr span_iterator& operator++() noexcept @@ -171,7 +171,7 @@ namespace details constexpr span_iterator& operator--() noexcept { Expects(begin_ && current_ && end_); - Expects(current_ > begin_); + Expects(begin_ < current_); --current_; return *this; } @@ -295,7 +295,9 @@ namespace details constexpr void _Verify_offset(const difference_type n) const noexcept { // test that *this + n is within the range of this call - Expects( n <= (current_ - begin_) && n <= (end_ - current_)); + if (n != 0) Expects(begin_ && current_ && end_); + if (n > 0) Expects(end_ - current_ >= n); + if (n < 0) Expects(current_ - begin_ >= -n); } GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 8d9fadd..99ee0d8 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -105,17 +105,17 @@ TEST(span_test, from_nullptr_size_constructor) std::abort(); }); { - span s{nullptr, narrow_cast::index_type>(0)}; + span s{nullptr, narrow_cast::size_type>(0)}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); - span cs{nullptr, narrow_cast::index_type>(0)}; + span cs{nullptr, narrow_cast::size_type>(0)}; EXPECT_TRUE(cs.size() == 0); EXPECT_TRUE(cs.data() == nullptr); } { auto workaround_macro = []() { - const span s{nullptr, narrow_cast::index_type>(0)}; + const span s{nullptr, narrow_cast::size_type>(0)}; }; EXPECT_DEATH(workaround_macro(), deathstring); } @@ -134,11 +134,11 @@ TEST(span_test, from_nullptr_size_constructor) EXPECT_DEATH(const_workaround_macro(), deathstring); } { - span s{nullptr, narrow_cast::index_type>(0)}; + span s{nullptr, narrow_cast::size_type>(0)}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); - span cs{nullptr, narrow_cast::index_type>(0)}; + span cs{nullptr, narrow_cast::size_type>(0)}; EXPECT_TRUE(cs.size() == 0); EXPECT_TRUE(cs.data() == nullptr); } @@ -193,7 +193,7 @@ TEST(span_test, from_pointer_length_constructor) { int* p = nullptr; - span s{p, narrow_cast::index_type>(0)}; + span s{p, narrow_cast::size_type>(0)}; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); } @@ -214,7 +214,7 @@ TEST(span_test, from_pointer_length_constructor) { int* p = nullptr; - auto s = make_span(p, narrow_cast::index_type>(0)); + auto s = make_span(p, narrow_cast::size_type>(0)); EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(s.data() == nullptr); } diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index dd5a0de..c1f8cf4 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -163,14 +163,14 @@ TEST(string_span_tests, TestConstructFromStdString) { std::string s = "Hello there world"; cstring_span<> v = s; - EXPECT_TRUE(v.length() == static_cast::index_type>(s.length())); + EXPECT_TRUE(v.length() == static_cast::size_type>(s.length())); } TEST(string_span_tests, TestConstructFromStdVector) { std::vector vec(5, 'h'); string_span<> v{vec}; - EXPECT_TRUE(v.length() == static_cast::index_type>(vec.size())); + EXPECT_TRUE(v.length() == static_cast::size_type>(vec.size())); } TEST(string_span_tests, TestStackArrayConstruction) @@ -232,7 +232,7 @@ TEST(string_span_tests, TestToString) char stack_string[] = "Hello"; cstring_span<> v = ensure_z(stack_string); auto s2 = gsl::to_string(v); - EXPECT_TRUE(static_cast::index_type>(s2.length()) == v.length()); + EXPECT_TRUE(static_cast::size_type>(s2.length()) == v.length()); EXPECT_TRUE(s2.length() == static_cast(5)); } @@ -245,7 +245,7 @@ TEST(string_span_tests, TestToBasicString) char stack_string[] = "Hello"; cstring_span<> v = ensure_z(stack_string); auto s2 = gsl::to_basic_string, ::std::allocator>(v); - EXPECT_TRUE(static_cast::index_type>(s2.length()) == v.length()); + EXPECT_TRUE(static_cast::size_type>(s2.length()) == v.length()); EXPECT_TRUE(s2.length() == static_cast(5)); } From d7e16111377e5bf0ca9b766f4445fe4754542ed9 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 4 Feb 2020 16:53:43 -0800 Subject: [PATCH 41/81] gsl::index ptrdiff_t -> size_t. remove span::at span::operator(). --- include/gsl/gsl_util | 13 +++++----- include/gsl/span | 48 ++++++++++++++-------------------- tests/at_tests.cpp | 26 +++++++------------ tests/span_tests.cpp | 60 +++---------------------------------------- tests/utils_tests.cpp | 3 ++- 5 files changed, 39 insertions(+), 111 deletions(-) diff --git a/include/gsl/gsl_util b/include/gsl/gsl_util index d1f7f33..53141e6 100644 --- a/include/gsl/gsl_util +++ b/include/gsl/gsl_util @@ -49,7 +49,7 @@ namespace gsl // // index type for all container indexes/subscripts/sizes -using index = std::ptrdiff_t; +using index = std::size_t; // final_action allows you to ensure something gets run at the end of a scope template @@ -129,8 +129,8 @@ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute constexpr T& at(T (&arr)[N], const index i) { - Expects(i >= 0 && i < narrow_cast(N)); - return arr[narrow_cast(i)]; + Expects(i >= 0 && i < N); + return arr[i]; } template @@ -138,16 +138,15 @@ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) { - Expects(i >= 0 && i < narrow_cast(cont.size())); - using size_type = decltype(cont.size()); - return cont[narrow_cast(i)]; + Expects(i >= 0 && i < cont.size()); + return cont[i]; } template GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr T at(const std::initializer_list cont, const index i) { - Expects(i >= 0 && i < narrow_cast(cont.size())); + Expects(i >= 0 && i < cont.size()); return *(cont.begin() + i); } diff --git a/include/gsl/span b/include/gsl/span index 5049b97..548587b 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -552,16 +552,6 @@ public: return data()[size() - 1]; } - // at and operator() are deprecated to align to the public member functions of std::span - [[deprecated("Use operator[]")]] constexpr reference at(size_type idx) const noexcept - { - return this->operator[](idx); - } - [[deprecated("Use operator[]")]] constexpr reference operator()(size_type idx) const noexcept - { - return this->operator[](idx); - } - constexpr pointer data() const noexcept { return storage_.data(); } // [span.iter], span iterator support @@ -817,67 +807,67 @@ constexpr ElementType& at(span s, index i) // [span.obs] Free observer functions template -constexpr typename span::size_type -ssize(const span& span) noexcept +constexpr std::ptrdiff_t +ssize(const span& s) noexcept { - return span.size(); + return static_cast(s.size()); } // [span.iter] Free functions for begin/end functions template constexpr typename span::iterator -begin(const span& span) noexcept +begin(const span& s) noexcept { - return span.begin(); + return s.begin(); } template constexpr typename span::iterator -end(const span& span) noexcept +end(const span& s) noexcept { - return span.end(); + return s.end(); } template constexpr typename span::const_iterator -cbegin(const span& span) noexcept +cbegin(const span& s) noexcept { - return span.cbegin(); + return s.cbegin(); } template constexpr typename span::const_iterator -cend(const span& span) noexcept +cend(const span& s) noexcept { - return span.cend(); + return s.cend(); } template constexpr typename span::reverse_iterator -rbegin(const span& span) noexcept +rbegin(const span& s) noexcept { - return span.rbegin(); + return s.rbegin(); } template constexpr typename span::reverse_iterator -rend(const span& span) noexcept +rend(const span& s) noexcept { - return span.rend(); + return s.rend(); } template constexpr typename span::const_reverse_iterator -crbegin(const span& span) noexcept +crbegin(const span& s) noexcept { - return span.crbegin(); + return s.crbegin(); } template constexpr typename span::const_reverse_iterator -crend(const span& span) noexcept +crend(const span& s) noexcept { - return span.crend(); + return s.crend(); } } // namespace gsl diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index be2c7b8..0580301 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -33,7 +33,7 @@ TEST(at_tests, static_array) int a[4] = {1, 2, 3, 4}; const int(&c_a)[4] = a; - for (int i = 0; i < 4; ++i) { + for (std::size_t i = 0; i < 4; ++i) { EXPECT_TRUE(&gsl::at(a, i) == &a[i]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[i]); } @@ -43,9 +43,7 @@ TEST(at_tests, static_array) std::abort(); }); - EXPECT_DEATH(gsl::at(a, -1), deathstring); EXPECT_DEATH(gsl::at(a, 4), deathstring); - EXPECT_DEATH(gsl::at(c_a, -1), deathstring); EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } @@ -54,7 +52,7 @@ TEST(at_tests, std_array) std::array a = {1, 2, 3, 4}; const std::array& c_a = a; - for (int i = 0; i < 4; ++i) { + for (std::size_t i = 0; i < 4; ++i) { EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); } @@ -64,9 +62,7 @@ TEST(at_tests, std_array) std::abort(); }); - EXPECT_DEATH(gsl::at(a, -1), deathstring); EXPECT_DEATH(gsl::at(a, 4), deathstring); - EXPECT_DEATH(gsl::at(c_a, -1), deathstring); EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } @@ -75,7 +71,7 @@ TEST(at_tests, std_vector) std::vector a = {1, 2, 3, 4}; const std::vector& c_a = a; - for (int i = 0; i < 4; ++i) { + for (std::size_t i = 0; i < 4; ++i) { EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); } @@ -85,9 +81,7 @@ TEST(at_tests, std_vector) std::abort(); }); - EXPECT_DEATH(gsl::at(a, -1), deathstring); EXPECT_DEATH(gsl::at(a, 4), deathstring); - EXPECT_DEATH(gsl::at(c_a, -1), deathstring); EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } @@ -96,8 +90,8 @@ TEST(at_tests, InitializerList) const std::initializer_list a = {1, 2, 3, 4}; for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(gsl::at(a, i) == i + 1); - EXPECT_TRUE(gsl::at({1, 2, 3, 4}, i) == i + 1); + EXPECT_TRUE(gsl::at(a, static_cast(i)) == i + 1); + EXPECT_TRUE(gsl::at({1, 2, 3, 4}, static_cast(i)) == i + 1); } std::set_terminate([] { @@ -105,9 +99,7 @@ TEST(at_tests, InitializerList) std::abort(); }); - EXPECT_DEATH(gsl::at(a, -1), deathstring); EXPECT_DEATH(gsl::at(a, 4), deathstring); - EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), deathstring); EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), deathstring); } @@ -120,12 +112,12 @@ static constexpr bool test_constexpr() const std::array& c_a2 = a2; for (int i = 0; i < 4; ++i) { - if (&gsl::at(a1, i) != &a1[i]) return false; - if (&gsl::at(c_a1, i) != &a1[i]) return false; + if (&gsl::at(a1, static_cast(i)) != &a1[i]) return false; + if (&gsl::at(c_a1, static_cast(i)) != &a1[i]) return false; // requires C++17: // if (&gsl::at(a2, i) != &a2[static_cast(i)]) return false; - if (&gsl::at(c_a2, i) != &c_a2[static_cast(i)]) return false; - if (gsl::at({1, 2, 3, 4}, i) != i + 1) return false; + if (&gsl::at(c_a2, static_cast(i)) != &c_a2[static_cast(i)]) return false; + if (gsl::at({1, 2, 3, 4}, static_cast(i)) != i + 1) return false; } return true; diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 99ee0d8..ce10325 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -25,7 +25,7 @@ #include // for reverse_iterator, operator-, operator== #include // for unique_ptr, shared_ptr, make_unique, allo... #include // for match_results, sub_match, match_results<>... -#include // for ptrdiff_t +#include // for ptrdiff_t #include // for string #include // for integral_constant<>::value, is_default_co... #include // for vector @@ -161,11 +161,7 @@ TEST(span_test, from_pointer_length_constructor) EXPECT_TRUE(s.data() == &arr[0]); EXPECT_TRUE(s.empty() == (i == 0)); for (std::size_t j = 0; j < i; ++j) - { EXPECT_TRUE(arr[j] == s[j]); - EXPECT_TRUE(arr[j] == s.at(j)); - EXPECT_TRUE(arr[j] == s(j)); - } } { span s = {&arr[i], 4 - i}; @@ -174,11 +170,7 @@ TEST(span_test, from_pointer_length_constructor) EXPECT_TRUE(s.empty() == ((4 - i) == 0)); for (std::size_t j = 0; j < 4 - i; ++j) - { EXPECT_TRUE(arr[j + i] == s[j]); - EXPECT_TRUE(arr[j + i] == s.at(j)); - EXPECT_TRUE(arr[j + i] == s(j)); - } } } } @@ -976,52 +968,6 @@ TEST(span_test, from_array_constructor) } } - TEST(span_test, at_call) - { - std::set_terminate([] { - std::cerr << "Expected Death. at_call"; - std::abort(); - }); - int arr[4] = {1, 2, 3, 4}; - - { - span s = arr; - EXPECT_TRUE(s.at(0) == 1); - EXPECT_DEATH(s.at(5), deathstring); - } - - { - int arr2d[2] = {1, 6}; - span s = arr2d; - EXPECT_TRUE(s.at(0) == 1); - EXPECT_TRUE(s.at(1) == 6); - EXPECT_DEATH(s.at(2), deathstring); - } - } - - TEST(span_test, operator_function_call) - { - std::set_terminate([] { - std::cerr << "Expected Death. operator_function_call"; - std::abort(); - }); - int arr[4] = {1, 2, 3, 4}; - - { - span s = arr; - EXPECT_TRUE(s(0) == 1); - EXPECT_DEATH(s(5), deathstring); - } - - { - int arr2d[2] = {1, 6}; - span s = arr2d; - EXPECT_TRUE(s(0) == 1); - EXPECT_TRUE(s(1) == 6); - EXPECT_DEATH(s(2), deathstring); - } - } - TEST(span_test, iterator_default_init) { span::iterator it1; @@ -1093,8 +1039,8 @@ TEST(span_test, from_array_constructor) int a[] = {1, 2, 3, 4}; span s{a}; - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE(s.size() == ssize(s)); + EXPECT_FALSE((std::is_same::value)); + EXPECT_TRUE(s.size() == static_cast(ssize(s))); } TEST(span_test, iterator_comparisons) diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index b6b5fc9..78bf59d 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -23,6 +23,7 @@ #include // for numeric_limits #include // for uint32_t, int32_t #include // for is_same +#include // for std::size_t using namespace gsl; @@ -37,7 +38,7 @@ void g() { j += 1; } TEST(utils_tests, sanity_check_for_gsl_index_typedef) { - static_assert(std::is_same::value, + static_assert(std::is_same::value, "gsl::index represents wrong arithmetic type"); } From 5cf1610cfe10ca083dd9eaf14cf9a12f2cb63692 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 5 Feb 2020 12:58:49 -0800 Subject: [PATCH 42/81] prevent overflow in size_bytes. fix compilation issue for clang 3.6 and 3.7 --- include/gsl/span | 20 ++++++++++++-------- tests/span_tests.cpp | 29 ++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 548587b..fbb3758 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -163,7 +163,7 @@ namespace details constexpr span_iterator operator++(int) noexcept { - auto ret{*this}; + span_iterator ret = {*this}; ++*this; return ret; } @@ -178,7 +178,7 @@ namespace details constexpr span_iterator operator--(int) noexcept { - auto ret{*this}; + span_iterator ret = {*this}; --*this; return ret; } @@ -194,7 +194,7 @@ namespace details constexpr span_iterator operator+(const difference_type n) const noexcept { - auto ret{*this}; + span_iterator ret = {*this}; return ret += n; } @@ -215,7 +215,7 @@ namespace details constexpr span_iterator operator-(const difference_type n) const noexcept { - auto ret{*this}; + span_iterator ret = {*this}; return ret -= n; } @@ -238,7 +238,8 @@ namespace details std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator==(const span_iterator& rhs) const noexcept { - return begin_ == rhs.begin_ && end_ == rhs.end_ && current_ == rhs.current_; + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); + return current_ == rhs.current_; } template < @@ -452,7 +453,7 @@ public: std::is_convertible::value && std::is_convertible().data())>::value>> - constexpr span(Container& cont) noexcept : span(cont.data(), narrow(cont.size())) + constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) {} template ().data())>::value>> constexpr span(const Container& cont) noexcept - : span(cont.data(), narrow(cont.size())) + : span(cont.data(), cont.size()) {} constexpr span(const span& other) noexcept = default; @@ -526,10 +527,13 @@ public: // [span.obs], span observers constexpr size_type size() const noexcept { return storage_.size(); } + constexpr size_type size_bytes() const noexcept { - return size() * narrow_cast(sizeof(element_type)); + Expects(size() < dynamic_extent / sizeof(element_type)); + return size() * sizeof(element_type); } + constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index ce10325..c078f3a 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1090,6 +1090,23 @@ TEST(span_test, from_array_constructor) } } + TEST(span_test, incomparable_iterators) + { + std::set_terminate([] { + std::cerr << "Expected Death. incomparable_iterators"; + std::abort(); + }); + + int a[] = {1, 2, 3, 4}; + int b[] = {1, 2, 3, 4}; + { + span s = a; + span s2 = b; + EXPECT_DEATH(s.begin() == s2.begin(), deathstring); + EXPECT_DEATH(s.begin() <= s2.begin(), deathstring); + } + } + TEST(span_test, begin_end) { std::set_terminate([] { @@ -1425,8 +1442,12 @@ TEST(span_test, from_array_constructor) TEST(span_test, as_bytes) { - int a[] = {1, 2, 3, 4}; + std::set_terminate([] { + std::cerr << "Expected Death. as_bytes"; + std::abort(); + }); + int a[] = {1, 2, 3, 4}; { const span s = a; EXPECT_TRUE(s.size() == 4); @@ -1451,6 +1472,12 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } + + int b[5] = {1, 2, 3, 4, 5}; + { + span sp(begin(b), static_cast(-2)); + EXPECT_DEATH((void) sp.size_bytes(), deathstring); + } } TEST(span_test, as_writeable_bytes) From 432be4852c4cd3807e26f90904e3a4cb397fee3a Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 5 Feb 2020 13:59:48 -0800 Subject: [PATCH 43/81] captureing result of iterator comparisons to address -Wunused-comparison --- tests/span_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index c078f3a..9dbfb42 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1102,8 +1102,8 @@ TEST(span_test, from_array_constructor) { span s = a; span s2 = b; - EXPECT_DEATH(s.begin() == s2.begin(), deathstring); - EXPECT_DEATH(s.begin() <= s2.begin(), deathstring); + EXPECT_DEATH(bool _ = (s.begin() == s2.begin()), deathstring); + EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), deathstring); } } From 7fcc142ffc9c73c891ca96ff3d84c17a03e6d230 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 5 Feb 2020 14:32:08 -0800 Subject: [PATCH 44/81] addressing travis errors --- include/gsl/span | 8 ++++---- tests/span_tests.cpp | 9 +++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index fbb3758..f8dd4a0 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -163,7 +163,7 @@ namespace details constexpr span_iterator operator++(int) noexcept { - span_iterator ret = {*this}; + auto ret{*this}; ++*this; return ret; } @@ -178,7 +178,7 @@ namespace details constexpr span_iterator operator--(int) noexcept { - span_iterator ret = {*this}; + auto ret{*this}; --*this; return ret; } @@ -194,7 +194,7 @@ namespace details constexpr span_iterator operator+(const difference_type n) const noexcept { - span_iterator ret = {*this}; + auto ret{*this}; return ret += n; } @@ -215,7 +215,7 @@ namespace details constexpr span_iterator operator-(const difference_type n) const noexcept { - span_iterator ret = {*this}; + auto ret{*this}; return ret -= n; } diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 9dbfb42..c1dbbef 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1102,8 +1102,13 @@ TEST(span_test, from_array_constructor) { span s = a; span s2 = b; - EXPECT_DEATH(bool _ = (s.begin() == s2.begin()), deathstring); - EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), deathstring); +#if (__cplusplus > 201402L) + EXPECT_DEATH([[maybe_unused]] s.begin() == s2.begin(), deathstring); + EXPECT_DEATH([[maybe_unused]] s.begin() <= s2.begin(), deathstring); +#else + EXPECT_DEATH(s.begin() == s2.begin(), deathstring); + EXPECT_DEATH(s.begin() <= s2.begin(), deathstring); +#endif } } From ff5f7973a28fc360bfd34af90486d784e48bc384 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 5 Feb 2020 14:36:34 -0800 Subject: [PATCH 45/81] remove brackets around this deref for span_iterator operators --- include/gsl/span | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index f8dd4a0..ecbca5d 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -163,7 +163,7 @@ namespace details constexpr span_iterator operator++(int) noexcept { - auto ret{*this}; + span_iterator ret = *this; ++*this; return ret; } @@ -178,7 +178,7 @@ namespace details constexpr span_iterator operator--(int) noexcept { - auto ret{*this}; + span_iterator ret = *this; --*this; return ret; } @@ -194,7 +194,7 @@ namespace details constexpr span_iterator operator+(const difference_type n) const noexcept { - auto ret{*this}; + span_iterator ret = *this; return ret += n; } @@ -215,7 +215,7 @@ namespace details constexpr span_iterator operator-(const difference_type n) const noexcept { - auto ret{*this}; + span_iterator ret = *this; return ret -= n; } From 45f016d96fe4bdc4c56d521509b88991f667c619 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 5 Feb 2020 14:41:41 -0800 Subject: [PATCH 46/81] add back capture variable for comparison in span_test --- tests/span_tests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index c1dbbef..5d9c18b 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1103,11 +1103,11 @@ TEST(span_test, from_array_constructor) span s = a; span s2 = b; #if (__cplusplus > 201402L) - EXPECT_DEATH([[maybe_unused]] s.begin() == s2.begin(), deathstring); - EXPECT_DEATH([[maybe_unused]] s.begin() <= s2.begin(), deathstring); + EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() == s2.begin()), deathstring); + EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() <= s2.begin()), deathstring); #else - EXPECT_DEATH(s.begin() == s2.begin(), deathstring); - EXPECT_DEATH(s.begin() <= s2.begin(), deathstring); + EXPECT_DEATH(bool _ = (s.begin() == s2.begin()), deathstring); + EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), deathstring); #endif } } From 3b9d15f49fe043d42b2715dc5041f23ed7f56c5c Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 5 Feb 2020 17:02:23 -0800 Subject: [PATCH 47/81] reverting changes to gsl::index --- include/gsl/gsl_util | 13 +++++++------ tests/at_tests.cpp | 26 +++++++++++++++++--------- tests/utils_tests.cpp | 2 +- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/include/gsl/gsl_util b/include/gsl/gsl_util index 53141e6..d1f7f33 100644 --- a/include/gsl/gsl_util +++ b/include/gsl/gsl_util @@ -49,7 +49,7 @@ namespace gsl // // index type for all container indexes/subscripts/sizes -using index = std::size_t; +using index = std::ptrdiff_t; // final_action allows you to ensure something gets run at the end of a scope template @@ -129,8 +129,8 @@ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute constexpr T& at(T (&arr)[N], const index i) { - Expects(i >= 0 && i < N); - return arr[i]; + Expects(i >= 0 && i < narrow_cast(N)); + return arr[narrow_cast(i)]; } template @@ -138,15 +138,16 @@ GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) { - Expects(i >= 0 && i < cont.size()); - return cont[i]; + Expects(i >= 0 && i < narrow_cast(cont.size())); + using size_type = decltype(cont.size()); + return cont[narrow_cast(i)]; } template GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr T at(const std::initializer_list cont, const index i) { - Expects(i >= 0 && i < cont.size()); + Expects(i >= 0 && i < narrow_cast(cont.size())); return *(cont.begin() + i); } diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index 0580301..be2c7b8 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -33,7 +33,7 @@ TEST(at_tests, static_array) int a[4] = {1, 2, 3, 4}; const int(&c_a)[4] = a; - for (std::size_t i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) { EXPECT_TRUE(&gsl::at(a, i) == &a[i]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[i]); } @@ -43,7 +43,9 @@ TEST(at_tests, static_array) std::abort(); }); + EXPECT_DEATH(gsl::at(a, -1), deathstring); EXPECT_DEATH(gsl::at(a, 4), deathstring); + EXPECT_DEATH(gsl::at(c_a, -1), deathstring); EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } @@ -52,7 +54,7 @@ TEST(at_tests, std_array) std::array a = {1, 2, 3, 4}; const std::array& c_a = a; - for (std::size_t i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) { EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); } @@ -62,7 +64,9 @@ TEST(at_tests, std_array) std::abort(); }); + EXPECT_DEATH(gsl::at(a, -1), deathstring); EXPECT_DEATH(gsl::at(a, 4), deathstring); + EXPECT_DEATH(gsl::at(c_a, -1), deathstring); EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } @@ -71,7 +75,7 @@ TEST(at_tests, std_vector) std::vector a = {1, 2, 3, 4}; const std::vector& c_a = a; - for (std::size_t i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) { EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); } @@ -81,7 +85,9 @@ TEST(at_tests, std_vector) std::abort(); }); + EXPECT_DEATH(gsl::at(a, -1), deathstring); EXPECT_DEATH(gsl::at(a, 4), deathstring); + EXPECT_DEATH(gsl::at(c_a, -1), deathstring); EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } @@ -90,8 +96,8 @@ TEST(at_tests, InitializerList) const std::initializer_list a = {1, 2, 3, 4}; for (int i = 0; i < 4; ++i) { - EXPECT_TRUE(gsl::at(a, static_cast(i)) == i + 1); - EXPECT_TRUE(gsl::at({1, 2, 3, 4}, static_cast(i)) == i + 1); + EXPECT_TRUE(gsl::at(a, i) == i + 1); + EXPECT_TRUE(gsl::at({1, 2, 3, 4}, i) == i + 1); } std::set_terminate([] { @@ -99,7 +105,9 @@ TEST(at_tests, InitializerList) std::abort(); }); + EXPECT_DEATH(gsl::at(a, -1), deathstring); EXPECT_DEATH(gsl::at(a, 4), deathstring); + EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), deathstring); EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), deathstring); } @@ -112,12 +120,12 @@ static constexpr bool test_constexpr() const std::array& c_a2 = a2; for (int i = 0; i < 4; ++i) { - if (&gsl::at(a1, static_cast(i)) != &a1[i]) return false; - if (&gsl::at(c_a1, static_cast(i)) != &a1[i]) return false; + if (&gsl::at(a1, i) != &a1[i]) return false; + if (&gsl::at(c_a1, i) != &a1[i]) return false; // requires C++17: // if (&gsl::at(a2, i) != &a2[static_cast(i)]) return false; - if (&gsl::at(c_a2, static_cast(i)) != &c_a2[static_cast(i)]) return false; - if (gsl::at({1, 2, 3, 4}, static_cast(i)) != i + 1) return false; + if (&gsl::at(c_a2, i) != &c_a2[static_cast(i)]) return false; + if (gsl::at({1, 2, 3, 4}, i) != i + 1) return false; } return true; diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 78bf59d..1fb0fd2 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -38,7 +38,7 @@ void g() { j += 1; } TEST(utils_tests, sanity_check_for_gsl_index_typedef) { - static_assert(std::is_same::value, + static_assert(std::is_same::value, "gsl::index represents wrong arithmetic type"); } From a49ff1b8df978c1b80738cab3bb25b4140fa6424 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 5 Feb 2020 17:12:31 -0800 Subject: [PATCH 48/81] update span specialization of at, change some tests back to int i with narrowing for the comparisons. --- include/gsl/span | 3 ++- tests/span_tests.cpp | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index ecbca5d..b922576 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -806,7 +806,8 @@ template constexpr ElementType& at(span s, index i) { // No bounds checking here because it is done in span::operator[] called below - return s[i]; + Ensures(i >= 0); + return s[narrow_cast(i)]; } // [span.obs] Free observer functions diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 5d9c18b..790cee0 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -153,24 +153,24 @@ TEST(span_test, from_pointer_length_constructor) int arr[4] = {1, 2, 3, 4}; { - for (std::size_t i = 0; i < 4; ++i) + for (int i = 0; i < 4; ++i) { { - span s = {&arr[0], i}; - EXPECT_TRUE(s.size() == i); + span s = {&arr[0], narrow_cast(i)}; + EXPECT_TRUE(s.size() == narrow_cast(i)); EXPECT_TRUE(s.data() == &arr[0]); EXPECT_TRUE(s.empty() == (i == 0)); - for (std::size_t j = 0; j < i; ++j) - EXPECT_TRUE(arr[j] == s[j]); + for (int j = 0; j < i; ++j) + EXPECT_TRUE(arr[j] == s[narrow_cast(j)]); } { - span s = {&arr[i], 4 - i}; - EXPECT_TRUE(s.size() == 4 - i); + span s = {&arr[i], 4 - narrow_cast(i)}; + EXPECT_TRUE(s.size() == 4 - narrow_cast(i)); EXPECT_TRUE(s.data() == &arr[i]); EXPECT_TRUE(s.empty() == ((4 - i) == 0)); - for (std::size_t j = 0; j < 4 - i; ++j) - EXPECT_TRUE(arr[j + i] == s[j]); + for (int j = 0; j < 4 - i; ++j) + EXPECT_TRUE(arr[j + i] == s[narrow_cast(j)]); } } } From 3f0d733466ab661fe4a1aa5ae9bea765a68fe225 Mon Sep 17 00:00:00 2001 From: cbuchart Date: Fri, 7 Feb 2020 15:25:58 +0100 Subject: [PATCH 49/81] Fix incorrect package name for vcpkg --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a2f783e..632f9b9 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ You can download and install GSL using the [vcpkg](https://github.com/Microsoft/ cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install - vcpkg install gsl + vcpkg install ms-gsl The GSL port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. From 377b2db537f4f0d766f2a66d7a27033f62b19e19 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Fri, 7 Feb 2020 14:09:57 -0800 Subject: [PATCH 50/81] almost parity with std::span --- include/gsl/span | 107 ++++++++++++++++++++++++++++++++----------- tests/span_tests.cpp | 16 ++++++- 2 files changed, 94 insertions(+), 29 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index b922576..6cfc91c 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -111,8 +111,7 @@ namespace details template struct is_allowed_extent_conversion - : public std::integral_constant + : public std::integral_constant { }; @@ -301,7 +300,9 @@ namespace details if (n < 0) Expects(current_ - begin_ >= -n); } + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw @@ -316,7 +317,9 @@ namespace details #else static constexpr bool _Unwrap_when_unverified = false; #endif + // clang-format off GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive + // clang-format on constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped @@ -392,7 +395,9 @@ public: using value_type = std::remove_cv_t; using size_type = std::size_t; using pointer = element_type*; + using const_pointer = const element_type*; using reference = element_type&; + using const_reference = const element_type&; using difference_type = std::ptrdiff_t; using iterator = details::span_iterator; @@ -410,38 +415,48 @@ public: // [span.cons], span constructors, copy, assignment, and destructor template " SFINAE, - // since "std::enable_if_t" is ill-formed when Extent is greater than 0. + // "Dependent" is needed to make "std::enable_if_t" SFINAE, since "std::enable_if_t" is ill-formed when Extent is greater than 0. class = std::enable_if_t<(Dependent || Extent == 0 || Extent == dynamic_extent)>> constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) {} - constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count) {} + constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count) + { + if (Extent != dynamic_extent) Expects(count == Extent); + } constexpr span(pointer firstElem, pointer lastElem) noexcept : storage_(firstElem, static_cast(std::distance(firstElem, lastElem))) - {} + { + if (Extent != dynamic_extent) { Expects(lastElem - firstElem == Extent); } + } template constexpr span(element_type (&arr)[N]) noexcept : storage_(KnownNotNull{std::addressof(arr[0])}, details::extent_type()) {} - template 0)>> - constexpr span(std::array, N>& arr) noexcept + template = 0> + constexpr span(std::array& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type()) {} - constexpr span(std::array, 0>&) noexcept + template ::value), + int> = 0> + constexpr span(const std::array& arr) noexcept + : storage_(KnownNotNull{arr.data()}, details::extent_type()) + {} + + constexpr span(std::array&) noexcept : storage_(static_cast(nullptr), details::extent_type<0>()) {} - template 0)>> - constexpr span(const std::array, N>& arr) noexcept - : storage_(KnownNotNull{arr.data()}, details::extent_type()) - {} - - constexpr span(const std::array, 0>&) noexcept + constexpr span(const std::array&) noexcept : storage_(static_cast(nullptr), details::extent_type<0>()) {} @@ -451,8 +466,8 @@ public: class = std::enable_if_t< !details::is_span::value && !details::is_std_array::value && std::is_convertible::value && - std::is_convertible().data())>::value>> + std::is_convertible::value && + std::is_convertible().data()), pointer>::value>> constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) {} @@ -460,10 +475,8 @@ public: class = std::enable_if_t< std::is_const::value && !details::is_span::value && std::is_convertible::value && - std::is_convertible().data())>::value>> - constexpr span(const Container& cont) noexcept - : span(cont.data(), cont.size()) + std::is_convertible().data()), pointer>::value>> + constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size()) {} constexpr span(const span& other) noexcept = default; @@ -489,16 +502,20 @@ public: } template + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - constexpr span last() const noexcept + // clang-format on + constexpr span last() const noexcept { Expects(size() >= Count); return {data() + (size() - Count), Count}; } template + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - constexpr auto subspan() const noexcept -> + // clang-format on + constexpr auto subspan() const noexcept -> typename details::calculate_subspan_type::type { Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset))); @@ -537,7 +554,9 @@ public: constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on constexpr reference operator[](size_type idx) const noexcept { Expects(idx < size()); @@ -602,7 +621,9 @@ public: constexpr pointer _Unchecked_begin() const noexcept { return data(); } constexpr pointer _Unchecked_end() const noexcept { + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on return data() + size(); } #endif // _MSC_VER @@ -662,7 +683,9 @@ private: return tmp.subspan(offset, count); } + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on span make_subspan(size_type offset, size_type count, subspan_selector) const { @@ -675,6 +698,20 @@ private: } }; +#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) + +// Deduction Guides +template +span(Type (&)[Extent])->span; + +template +span(std::array&)->span; + +template +span(const std::array&)->span; + +#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) + #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) template constexpr const typename span::size_type span::extent; @@ -742,16 +779,32 @@ template span::value> as_bytes(span s) noexcept { + // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on return {reinterpret_cast(s.data()), s.size_bytes()}; } template ::value>> + std::enable_if_t::value, int> = 0> span::value> +as_writable_bytes(span s) noexcept +{ + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template ::value, int> = 0> +[[deprecated( + "use as_writable_bytes")]] span::value> as_writeable_bytes(span s) noexcept { + // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on return {reinterpret_cast(s.data()), s.size_bytes()}; } @@ -759,8 +812,7 @@ as_writeable_bytes(span s) noexcept // make_span() - Utility functions for creating spans // template -constexpr span make_span(ElementType* ptr, - typename span::size_type count) +constexpr span make_span(ElementType* ptr, typename span::size_type count) { return span(ptr, count); } @@ -812,8 +864,7 @@ constexpr ElementType& at(span s, index i) // [span.obs] Free observer functions template -constexpr std::ptrdiff_t -ssize(const span& s) noexcept +constexpr std::ptrdiff_t ssize(const span& s) noexcept { return static_cast(s.size()); } diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 790cee0..8c5ac0d 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1551,11 +1551,15 @@ TEST(span_test, from_array_constructor) // even when done dynamically { span s = arr; + /* + // this now results in a compile-time error, rather than runtime. + // There is no suitable conversion from dynamic span to fixed span. auto f = [&]() { const span s2 = s; static_cast(s2); }; EXPECT_DEATH(f(), deathstring); + */ } // but doing so explicitly is ok @@ -1570,12 +1574,19 @@ TEST(span_test, from_array_constructor) static_cast(s1); } - // ...or dynamically + /* + // this is not a legal operation in std::span, so we are no longer supporting it + // conversion from span to span via call to `first` + // then convert from span to span + // The dynamic to fixed extents are not supported in the standard + // to make this work, span would need to be span. { + // NB: implicit conversion to span from span span s1 = s4.first(1); static_cast(s1); } + */ // initialization or assignment to static span that requires size INCREASE is not ok. int arr2[2] = {1, 2}; @@ -1597,12 +1608,15 @@ TEST(span_test, from_array_constructor) EXPECT_DEATH(f(), deathstring); } + /* + // This no longer compiles. There is no suitable conversion from dynamic span to a fixed size span. // this should fail - we are trying to assign a small dynamic span to a fixed_size larger one span av = arr2; auto f = [&]() { const span _s4 = av; static_cast(_s4); }; EXPECT_DEATH(f(), deathstring); + */ } TEST(span_test, interop_with_std_regex) From b81d6e40e13708a6019ff9758db263c2f385ed80 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Fri, 7 Feb 2020 14:15:44 -0800 Subject: [PATCH 51/81] constexpr the make_subspan calls. --- include/gsl/span | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 6cfc91c..445826c 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -676,7 +676,7 @@ private: }; template - span make_subspan(size_type offset, size_type count, + constexpr span make_subspan(size_type offset, size_type count, subspan_selector) const { const span tmp(*this); @@ -686,7 +686,7 @@ private: // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on - span make_subspan(size_type offset, size_type count, + constexpr span make_subspan(size_type offset, size_type count, subspan_selector) const { Expects(size() >= offset); From d8fa68c4a589e6461c4bb2a58d5ccc1c1075b5ef Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Fri, 7 Feb 2020 14:40:09 -0800 Subject: [PATCH 52/81] address build failures --- include/gsl/span | 2 +- tests/span_tests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 445826c..20f4237 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -430,7 +430,7 @@ public: constexpr span(pointer firstElem, pointer lastElem) noexcept : storage_(firstElem, static_cast(std::distance(firstElem, lastElem))) { - if (Extent != dynamic_extent) { Expects(lastElem - firstElem == Extent); } + if (Extent != dynamic_extent) { Expects(lastElem - firstElem == static_cast(Extent)); } } template diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 8c5ac0d..1f5020b 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1550,10 +1550,10 @@ TEST(span_test, from_array_constructor) // even when done dynamically { - span s = arr; /* // this now results in a compile-time error, rather than runtime. // There is no suitable conversion from dynamic span to fixed span. + span s = arr; auto f = [&]() { const span s2 = s; static_cast(s2); From ebe88443447012a40c8b95742650c78a696ef5ec Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Sat, 8 Feb 2020 12:49:43 +0000 Subject: [PATCH 53/81] Make GSL includes based on CMAKE_INSTALL_INCLUDEDIR This is to avoid inconsistencies with the `install` command which specifies this as the destination for includes. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ff226ef..96ab24b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,12 +58,12 @@ target_compile_definitions(GSL INTERFACE if(GSL_STANDALONE_PROJECT) target_include_directories(GSL INTERFACE $ - $ + $ ) else() target_include_directories(GSL SYSTEM INTERFACE $ - $ + $ ) endif() From 886fc95142ab4156eab45dada3daace1d42c8dd9 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Sat, 8 Feb 2020 12:55:19 +0000 Subject: [PATCH 54/81] Remove PUBLIC_HEADER attribute from `install` command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we already explicitly install `include/gsl`, this doesn’t do anything. --- CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96ab24b..b7c1370 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,9 +83,7 @@ if (CMAKE_VERSION VERSION_GREATER 3.7.8) endif() endif() -install(TARGETS GSL EXPORT Microsoft.GSLConfig - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) +install(TARGETS GSL EXPORT Microsoft.GSLConfig) install( DIRECTORY include/gsl DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} From 9c0c6b246ceeba4d11a024b05ad6c2e8f7d2ca69 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Sat, 8 Feb 2020 12:58:25 +0000 Subject: [PATCH 55/81] Add Microsoft.GSL::GSL alias for GSL This ensures that dependents can be agnostic about whether GSL was added via `add_subdirectory` or `find_package` --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7c1370..e0d704e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,10 @@ install( install(EXPORT Microsoft.GSLConfig NAMESPACE Microsoft.GSL:: DESTINATION share/Microsoft.GSL/cmake) export(TARGETS GSL NAMESPACE Microsoft.GSL:: FILE Microsoft.GSLConfig.cmake) +# Add Microsoft.GSL::GSL alias for GSL so that dependents can be agnostic about +# whether GSL was added via `add_subdirectory` or `find_package` +add_library(Microsoft.GSL::GSL ALIAS GSL) + option(GSL_TEST "Generate tests." ${GSL_STANDALONE_PROJECT}) if (GSL_TEST) enable_testing() From 849f14083a08e1c8bcba1fe4bba94683a333e77b Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Sat, 8 Feb 2020 13:11:11 +0000 Subject: [PATCH 56/81] Add a note on CMake usage of exported target to the README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 183553f..bc43251 100644 --- a/README.md +++ b/README.md @@ -95,5 +95,14 @@ Include the library using: #include +## Usage in CMake + +The library provides a Config file for CMake, once installed it can be found via + + find_package(Microsoft.GSL CONFIG) + +Which, when successful, will add library target called `Microsoft.GSL::GSL` which you can use via the usual +`target_link_libraries` mechanism. + ## Debugging visualization support For Visual Studio users, the file [GSL.natvis](./GSL.natvis) in the root directory of the repository can be added to your project if you would like more helpful visualization of GSL types in the Visual Studio debugger than would be offered by default. From dd78144c2ebcc52cebb3c336743d04ee04968f9f Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 10 Feb 2020 13:17:22 -0800 Subject: [PATCH 57/81] msvc and gcc work locally --- include/gsl/span | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 20f4237..62591df 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -418,7 +418,8 @@ public: // "Dependent" is needed to make "std::enable_if_t" SFINAE, since "std::enable_if_t" is ill-formed when Extent is greater than 0. - class = std::enable_if_t<(Dependent || Extent == 0 || Extent == dynamic_extent)>> + class = std::enable_if_t<(Dependent || + details::is_allowed_extent_conversion<0, Extent>::value)>> constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) {} @@ -430,36 +431,31 @@ public: constexpr span(pointer firstElem, pointer lastElem) noexcept : storage_(firstElem, static_cast(std::distance(firstElem, lastElem))) { - if (Extent != dynamic_extent) { Expects(lastElem - firstElem == static_cast(Extent)); } + if (Extent != dynamic_extent) + { Expects(lastElem - firstElem == static_cast(Extent)); } } - template + template ::value, int> = 0> constexpr span(element_type (&arr)[N]) noexcept : storage_(KnownNotNull{std::addressof(arr[0])}, details::extent_type()) {} - template = 0> - constexpr span(std::array& arr) noexcept + template ::value, int> = 0> + constexpr span(std::array& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type()) {} - template ::value), + template ::value && + details::is_allowed_element_type_conversion::value), int> = 0> constexpr span(const std::array& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type()) {} - constexpr span(std::array&) noexcept - : storage_(static_cast(nullptr), details::extent_type<0>()) - {} - - constexpr span(const std::array&) noexcept - : storage_(static_cast(nullptr), details::extent_type<0>()) - {} - // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement // on Container to be a contiguous sequence container. template ::value && !details::is_span::value && + !details::is_std_array::value && std::is_convertible::value && std::is_convertible().data()), pointer>::value>> constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size()) @@ -677,7 +674,7 @@ private: template constexpr span make_subspan(size_type offset, size_type count, - subspan_selector) const + subspan_selector) const { const span tmp(*this); return tmp.subspan(offset, count); @@ -686,8 +683,8 @@ private: // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on - constexpr span make_subspan(size_type offset, size_type count, - subspan_selector) const + constexpr span + make_subspan(size_type offset, size_type count, subspan_selector) const { Expects(size() >= offset); From cce6ee563eb2047238f57c62afe4e44a5ee8ce8a Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 10 Feb 2020 17:09:58 -0800 Subject: [PATCH 58/81] address issue with v140 toolset --- include/gsl/span | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/gsl/span b/include/gsl/span index 62591df..6c2b4de 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -71,7 +71,11 @@ namespace gsl { // [views.constants], constants +#if (defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)) +constexpr const std::size_t dynamic_extent = static_cast(-1); +#else constexpr std::size_t dynamic_extent = static_cast(-1); +#endif template class span; @@ -134,6 +138,12 @@ namespace details #ifdef _MSC_VER using _Unchecked_type = pointer; #endif + constexpr span_iterator() = default; + + constexpr span_iterator(pointer begin, pointer end, pointer current) + : begin_(begin), end_(end), current_(current) + {} + constexpr operator span_iterator() const noexcept { return {begin_, end_, current_}; @@ -494,6 +504,7 @@ public: template constexpr span first() const noexcept { + Expects(Count != dynamic_extent); Expects(Count <= size()); return {data(), Count}; } @@ -504,6 +515,7 @@ public: // clang-format on constexpr span last() const noexcept { + Expects(Count != dynamic_extent); Expects(size() >= Count); return {data() + (size() - Count), Count}; } From 926aaeca5618931097a7626ffe4a0f87623e1cd8 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 11 Feb 2020 16:36:07 -0800 Subject: [PATCH 59/81] reviewed the pr in its entirety and made some slight modifications. Removed all members and fields marked as deprecated. --- include/gsl/span | 26 ++++---------------------- include/gsl/string_span | 2 +- tests/span_tests.cpp | 8 ++++---- tests/string_span_tests.cpp | 4 ++-- 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 6c2b4de..8f73b1c 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -71,11 +71,7 @@ namespace gsl { // [views.constants], constants -#if (defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)) constexpr const std::size_t dynamic_extent = static_cast(-1); -#else -constexpr std::size_t dynamic_extent = static_cast(-1); -#endif template class span; @@ -137,7 +133,7 @@ namespace details #ifdef _MSC_VER using _Unchecked_type = pointer; -#endif +#endif // _MSC_VER constexpr span_iterator() = default; constexpr span_iterator(pointer begin, pointer end, pointer current) @@ -348,14 +344,14 @@ namespace details public: using size_type = std::size_t; - static_assert(Ext != dynamic_extent, "A fixed-size span must be >= 0 in size."); + static_assert(Ext != dynamic_extent, "A fixed-size span must not have size == dynamic_extent"); constexpr extent_type() noexcept {} template constexpr extent_type(extent_type ext) { - static_assert(Other == Ext || Other == dynamic_extent, + static_assert(Other == Ext, "Mismatch between fixed-size extent and size of initializing data."); Expects(ext.size() == Ext); } @@ -415,8 +411,6 @@ public: using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - using index_type [[deprecated("use size_type instead of index_type")]] = size_type; - #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) static constexpr const size_type extent{Extent}; #else @@ -805,18 +799,6 @@ as_writable_bytes(span s) noexcept return {reinterpret_cast(s.data()), s.size_bytes()}; } -template ::value, int> = 0> -[[deprecated( - "use as_writable_bytes")]] span::value> -as_writeable_bytes(span s) noexcept -{ - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on - return {reinterpret_cast(s.data()), s.size_bytes()}; -} - // // make_span() - Utility functions for creating spans // @@ -868,7 +850,7 @@ constexpr ElementType& at(span s, index i) { // No bounds checking here because it is done in span::operator[] called below Ensures(i >= 0); - return s[narrow_cast(i)]; + return s[static_cast(i)]; } // [span.obs] Free observer functions diff --git a/include/gsl/string_span b/include/gsl/string_span index 27b8977..cc0588e 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -381,7 +381,7 @@ as_bytes(basic_string_span s) noexcept template ::value>> basic_string_span::value> -as_writeable_bytes(basic_string_span s) noexcept +as_writable_bytes(basic_string_span s) noexcept { GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast(s.data()), s.size_bytes()}; diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 1f5020b..ab437a5 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1485,7 +1485,7 @@ TEST(span_test, from_array_constructor) } } - TEST(span_test, as_writeable_bytes) + TEST(span_test, as_writable_bytes) { int a[] = {1, 2, 3, 4}; @@ -1494,7 +1494,7 @@ TEST(span_test, from_array_constructor) // you should not be able to get writeable bytes for const objects span s = a; EXPECT_TRUE(s.size() == 4); - span bs = as_writeable_bytes(s); + span bs = as_writable_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); #endif @@ -1502,7 +1502,7 @@ TEST(span_test, from_array_constructor) { span s; - const auto bs = as_writeable_bytes(s); + const auto bs = as_writable_bytes(s); EXPECT_TRUE(bs.size() == s.size()); EXPECT_TRUE(bs.size() == 0); EXPECT_TRUE(bs.size_bytes() == 0); @@ -1512,7 +1512,7 @@ TEST(span_test, from_array_constructor) { span s = a; - const auto bs = as_writeable_bytes(s); + const auto bs = as_writable_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index c1f8cf4..7a9f7fb 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -1206,12 +1206,12 @@ TEST(string_span_tests, as_bytes) EXPECT_TRUE(bs.size() == s.size_bytes()); } -TEST(string_span_tests, as_writeable_bytes) +TEST(string_span_tests, as_writable_bytes) { wchar_t buf[]{L"qwerty"}; wzstring_span<> v(buf); const auto s = v.as_string_span(); - const auto bs = as_writeable_bytes(s); + const auto bs = as_writable_bytes(s); EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } From 41ae38f197a8b1565352a156bc0e5fa9772cec25 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Fri, 14 Feb 2020 15:24:46 -0800 Subject: [PATCH 60/81] addressing a few more comments and adding gsl-std span compatibility tests --- include/gsl/span | 15 +- tests/CMakeLists.txt | 1 + tests/span_compatibility_tests.cpp | 1066 ++++++++++++++++++++++++++++ tests/span_tests.cpp | 9 +- tests/utils_tests.cpp | 2 +- 5 files changed, 1080 insertions(+), 13 deletions(-) create mode 100644 tests/span_compatibility_tests.cpp diff --git a/include/gsl/span b/include/gsl/span index 8f73b1c..cffe043 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -105,19 +105,19 @@ namespace details }; template - struct is_std_array : public is_std_array_oracle> + struct is_std_array : is_std_array_oracle> { }; template struct is_allowed_extent_conversion - : public std::integral_constant + : std::integral_constant { }; template struct is_allowed_element_type_conversion - : public std::integral_constant::value> + : std::integral_constant::value> { }; @@ -460,13 +460,12 @@ public: : storage_(KnownNotNull{arr.data()}, details::extent_type()) {} - // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement + // NB: the SFINAE here uses .data() as an incomplete/imperfect proxy for the requirement // on Container to be a contiguous sequence container. template ::value && !details::is_std_array::value && std::is_convertible::value && - std::is_convertible::value && std::is_convertible().data()), pointer>::value>> constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) {} @@ -671,7 +670,7 @@ private: // The rest is needed to remove unnecessary null check // in subspans and constructors from arrays - constexpr span(KnownNotNull ptr, size_type count) : storage_(ptr, count) {} + constexpr span(KnownNotNull ptr, size_type count) noexcept : storage_(ptr, count) {} template class subspan_selector @@ -680,7 +679,7 @@ private: template constexpr span make_subspan(size_type offset, size_type count, - subspan_selector) const + subspan_selector) const noexcept { const span tmp(*this); return tmp.subspan(offset, count); @@ -690,7 +689,7 @@ private: GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on constexpr span - make_subspan(size_type offset, size_type count, subspan_selector) const + make_subspan(size_type offset, size_type count, subspan_selector) const noexcept { Expects(size() >= offset); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3a6163c..38dbb85 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -153,6 +153,7 @@ function(add_gsl_test name) endfunction() add_gsl_test(span_tests) +add_gsl_test(span_compatibility_tests) add_gsl_test(multi_span_tests) add_gsl_test(strided_span_tests) add_gsl_test(string_span_tests) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp new file mode 100644 index 0000000..cdf0bff --- /dev/null +++ b/tests/span_compatibility_tests.cpp @@ -0,0 +1,1066 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for byte +#include // for span, span_iterator, operator==, operator!= + +#include // for array +#include // for ptrdiff_t +#include // for reverse_iterator, operator-, operator== +#include // for integral_constant<>::value, is_default_co... +#include + +using namespace std; +using namespace gsl; + +// Below are tests that verify the gsl interface support the same things as the std +// Ranges and Concepts support need to be added later. + +struct Base +{ +}; +struct Derived : Base +{ +}; +static_assert(std::is_convertible::value, "std::is_convertible"); +static_assert(!std::is_convertible::value, + "!std::is_convertible"); + +template +constexpr bool AsWritableBytesCompilesFor = false; + +template +constexpr bool AsWritableBytesCompilesFor()))>> = + true; + +TEST(span_test, std_span_compatibilty_assertion_tests) +{ + int arr[3]{10, 20, 30}; + std::array stl{{100, 200, 300}}; + + { + gsl::span sp_dyn; + assert(sp_dyn.data() == nullptr); + assert(sp_dyn.size() == 0); + assert(sp_dyn.empty()); + } + { + gsl::span sp_zero; + assert(sp_zero.data() == nullptr); + assert(sp_zero.size() == 0); + assert(sp_zero.empty()); + + gsl::span sp_dyn_a(arr, 3); + gsl::span sp_dyn_b(begin(arr), 3); + EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn_a.size() == 3); + EXPECT_TRUE(sp_dyn_b.size() == 3); + + gsl::span sp_three_a(arr, 3); + gsl::span sp_three_b(begin(arr), 3); + EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_three_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_three_a.size() == 3); + EXPECT_TRUE(sp_three_b.size() == 3); + + gsl::span sp_const_a(arr, 3); + gsl::span sp_const_b(begin(arr), 3); + EXPECT_TRUE(sp_const_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_a.size() == 3); + EXPECT_TRUE(sp_const_b.size() == 3); + +#if __cplusplus >= 201703l + gsl::span sp_const_c(std::as_const(arr), 3); + EXPECT_TRUE(sp_const_c.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_c.size() == 3); +#endif // __cplusplus >= 201703l + + gsl::span sp_const_d(cbegin(arr), 3); + EXPECT_TRUE(sp_const_d.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_d.size() == 3); + } + { + gsl::span sp_dyn_a(begin(arr), std::end(arr)); + EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn_a.size() == 3); + + gsl::span sp_three_a(begin(arr), std::end(arr)); + EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_three_a.size() == 3); + + gsl::span sp_const_a(begin(arr), std::end(arr)); + gsl::span sp_const_b(begin(arr), std::cend(arr)); + gsl::span sp_const_c(cbegin(arr), std::end(arr)); + gsl::span sp_const_d(cbegin(arr), std::cend(arr)); + EXPECT_TRUE(sp_const_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_c.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_d.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_a.size() == 3); + EXPECT_TRUE(sp_const_b.size() == 3); + EXPECT_TRUE(sp_const_c.size() == 3); + EXPECT_TRUE(sp_const_d.size() == 3); + } + { + gsl::span sp_dyn_a(arr); + gsl::span sp_dyn_b(stl); + gsl::span sp_dyn_c{stl}; + gsl::span sp_dyn_d{stl}; + EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn_b.data() == stl.data()); + EXPECT_TRUE(sp_dyn_a.size() == 3); + EXPECT_TRUE(sp_dyn_b.size() == 3); + + gsl::span sp_three_a(arr); + gsl::span sp_three_b(stl); + EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_three_b.data() == stl.data()); + EXPECT_TRUE(sp_three_a.size() == 3); + EXPECT_TRUE(sp_three_b.size() == 3); + + gsl::span sp_const_w(arr); + gsl::span sp_const_y(stl); + EXPECT_TRUE(sp_const_w.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_y.data() == stl.data()); + EXPECT_TRUE(sp_const_w.size() == 3); + EXPECT_TRUE(sp_const_y.size() == 3); + +#if __cplusplus >= 201703l + gsl::span sp_const_x(std::as_const(arr)); + EXPECT_TRUE(sp_const_x.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_x.size() == 3); + + gsl::span sp_const_z(std::as_const(stl)); + EXPECT_TRUE(sp_const_z.data() == stl.data()); + EXPECT_TRUE(sp_const_z.size() == 3); +#endif // __cplusplus >= 201703l + } + { + const gsl::span orig_dyn(arr); + const gsl::span orig_three(arr); + const gsl::span orig_const_dyn(arr); + const gsl::span orig_const_three(arr); + + gsl::span sp_a(orig_dyn); + gsl::span sp_b(orig_three); + + gsl::span sp_c(orig_three); + + gsl::span sp_d(orig_dyn); + gsl::span sp_e(orig_three); + gsl::span sp_f(orig_const_dyn); + gsl::span sp_g(orig_const_three); + + gsl::span sp_h(orig_three); + gsl::span sp_i(orig_const_three); + + EXPECT_TRUE(sp_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_c.data() == std::begin(arr)); + EXPECT_TRUE(sp_d.data() == std::begin(arr)); + EXPECT_TRUE(sp_e.data() == std::begin(arr)); + EXPECT_TRUE(sp_f.data() == std::begin(arr)); + EXPECT_TRUE(sp_g.data() == std::begin(arr)); + EXPECT_TRUE(sp_h.data() == std::begin(arr)); + EXPECT_TRUE(sp_i.data() == std::begin(arr)); + EXPECT_TRUE(sp_a.size() == 3); + EXPECT_TRUE(sp_b.size() == 3); + EXPECT_TRUE(sp_c.size() == 3); + EXPECT_TRUE(sp_d.size() == 3); + EXPECT_TRUE(sp_e.size() == 3); + EXPECT_TRUE(sp_f.size() == 3); + EXPECT_TRUE(sp_g.size() == 3); + EXPECT_TRUE(sp_h.size() == 3); + EXPECT_TRUE(sp_i.size() == 3); + } + { + gsl::span sp_dyn(arr); + gsl::span sp_three(arr); + gsl::span sp_const_dyn(arr); + gsl::span sp_const_three(arr); + + EXPECT_TRUE(sp_dyn.data() == std::begin(arr)); + EXPECT_TRUE(sp_three.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_dyn.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_three.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn.size() == 3); + EXPECT_TRUE(sp_three.size() == 3); + EXPECT_TRUE(sp_const_dyn.size() == 3); + EXPECT_TRUE(sp_const_three.size() == 3); + + int other[4]{12, 34, 56, 78}; + + sp_dyn = gsl::span{other}; + sp_three = gsl::span{stl}; + sp_const_dyn = gsl::span{other}; + sp_const_three = gsl::span{stl}; + + EXPECT_TRUE(sp_dyn.data() == std::begin(other)); + EXPECT_TRUE(sp_three.data() == stl.data()); + EXPECT_TRUE(sp_const_dyn.data() == std::begin(other)); + EXPECT_TRUE(sp_const_three.data() == stl.data()); + EXPECT_TRUE(sp_dyn.size() == 4); + EXPECT_TRUE(sp_three.size() == 3); + EXPECT_TRUE(sp_const_dyn.size() == 4); + EXPECT_TRUE(sp_const_three.size() == 3); + } + { + gsl::span::iterator it_dyn{}; + + { + gsl::span sp_dyn(arr); + it_dyn = sp_dyn.begin(); + } + + EXPECT_TRUE(*it_dyn == arr[0]); + EXPECT_TRUE(it_dyn[2] == arr[2]); + + gsl::span::iterator it_three{}; + + { + gsl::span sp_three(stl); + it_three = sp_three.begin(); + } + + EXPECT_TRUE(*it_three == stl[0]); + EXPECT_TRUE(it_three[2] == stl[2]); + } + + { + int sequence[9]{10, 20, 30, 40, 50, 60, 70, 80, 90}; + + const gsl::span sp_dyn(sequence); + const gsl::span sp_nine(sequence); + + auto first_3 = sp_dyn.first<3>(); + auto first_4 = sp_nine.first<4>(); + auto first_5 = sp_dyn.first(5); + auto first_6 = sp_nine.first(6); + static_assert(noexcept(sp_dyn.first<3>()), "noexcept(sp_dyn.first<3>())"); // strengthened + static_assert(noexcept(sp_nine.first<4>()), "noexcept(sp_nine.first<4>())"); // strengthened + static_assert(noexcept(sp_dyn.first(5)), "noexcept(sp_dyn.first(5))"); // strengthened + static_assert(noexcept(sp_nine.first(6)), "noexcept(sp_nine.first(6))"); // strengthened + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + EXPECT_TRUE(first_3.data() == std::begin(sequence)); + EXPECT_TRUE(first_4.data() == std::begin(sequence)); + EXPECT_TRUE(first_5.data() == std::begin(sequence)); + EXPECT_TRUE(first_6.data() == std::begin(sequence)); + EXPECT_TRUE(first_3.size() == 3); + EXPECT_TRUE(first_4.size() == 4); + EXPECT_TRUE(first_5.size() == 5); + EXPECT_TRUE(first_6.size() == 6); + + auto last_3 = sp_dyn.last<3>(); + auto last_4 = sp_nine.last<4>(); + auto last_5 = sp_dyn.last(5); + auto last_6 = sp_nine.last(6); + static_assert(noexcept(sp_dyn.last<3>()), "noexcept(sp_dyn.last<3>())"); // strengthened + static_assert(noexcept(sp_nine.last<4>()), "noexcept(sp_nine.last<4>())"); // strengthened + static_assert(noexcept(sp_dyn.last(5)), "noexcept(sp_dyn.last(5))"); // strengthened + static_assert(noexcept(sp_nine.last(6)), "noexcept(sp_nine.last(6))"); // strengthened + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + EXPECT_TRUE(last_3.data() == std::begin(sequence) + 6); + EXPECT_TRUE(last_4.data() == std::begin(sequence) + 5); + EXPECT_TRUE(last_5.data() == std::begin(sequence) + 4); + EXPECT_TRUE(last_6.data() == std::begin(sequence) + 3); + EXPECT_TRUE(last_3.size() == 3); + EXPECT_TRUE(last_4.size() == 4); + EXPECT_TRUE(last_5.size() == 5); + EXPECT_TRUE(last_6.size() == 6); + + auto offset_3 = sp_dyn.subspan<3>(); + auto offset_4 = sp_nine.subspan<4>(); + auto offset_5 = sp_dyn.subspan(5); + auto offset_6 = sp_nine.subspan(6); + static_assert(noexcept(sp_dyn.subspan<3>()), + "noexcept(sp_dyn.subspan<3>())"); // strengthened + static_assert(noexcept(sp_nine.subspan<4>()), + "noexcept(sp_nine.subspan<4>())"); // strengthened + static_assert(noexcept(sp_dyn.subspan(5)), "noexcept(sp_dyn.subspan(5))"); // strengthened + static_assert(noexcept(sp_nine.subspan(6)), "noexcept(sp_nine.subspan(6))"); // strengthened + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + EXPECT_TRUE(offset_3.data() == std::begin(sequence) + 3); + EXPECT_TRUE(offset_4.data() == std::begin(sequence) + 4); + EXPECT_TRUE(offset_5.data() == std::begin(sequence) + 5); + EXPECT_TRUE(offset_6.data() == std::begin(sequence) + 6); + EXPECT_TRUE(offset_3.size() == 6); + EXPECT_TRUE(offset_4.size() == 5); + EXPECT_TRUE(offset_5.size() == 4); + EXPECT_TRUE(offset_6.size() == 3); + + auto subspan_3 = sp_dyn.subspan<3, 2>(); + auto subspan_4 = sp_nine.subspan<4, 2>(); + auto subspan_5 = sp_dyn.subspan(5, 2); + auto subspan_6 = sp_nine.subspan(6, 2); + static_assert(noexcept(sp_dyn.subspan<3, 2>()), + "noexcept(sp_dyn.subspan<3, 2>())"); // strengthened + static_assert(noexcept(sp_nine.subspan<4, 2>()), + "noexcept(sp_nine.subspan<4, 2>())"); // strengthened + static_assert(noexcept(sp_dyn.subspan(5, 2)), + "noexcept(sp_dyn.subspan(5, 2))"); // strengthened + static_assert(noexcept(sp_nine.subspan(6, 2)), + "noexcept(sp_nine.subspan(6, 2))"); // strengthened + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + EXPECT_TRUE(subspan_3.data() == std::begin(sequence) + 3); + EXPECT_TRUE(subspan_4.data() == std::begin(sequence) + 4); + EXPECT_TRUE(subspan_5.data() == std::begin(sequence) + 5); + EXPECT_TRUE(subspan_6.data() == std::begin(sequence) + 6); + EXPECT_TRUE(subspan_3.size() == 2); + EXPECT_TRUE(subspan_4.size() == 2); + EXPECT_TRUE(subspan_5.size() == 2); + EXPECT_TRUE(subspan_6.size() == 2); + + static_assert(noexcept(sp_dyn.size()), "noexcept(sp_dyn.size())"); + static_assert(noexcept(sp_dyn.size_bytes()), "noexcept(sp_dyn.size_bytes())"); + static_assert(noexcept(sp_dyn.empty()), "noexcept(sp_dyn.empty())"); + static_assert(noexcept(sp_dyn[0]), "noexcept(sp_dyn[0])"); // strengthened + static_assert(noexcept(sp_dyn.front()), "noexcept(sp_dyn.front())"); // strengthened + static_assert(noexcept(sp_dyn.back()), "noexcept(sp_dyn.back())"); // strengthened + static_assert(noexcept(sp_dyn.data()), "noexcept(sp_dyn.data())"); + static_assert(noexcept(sp_dyn.begin()), "noexcept(sp_dyn.begin())"); + static_assert(noexcept(sp_dyn.end()), "noexcept(sp_dyn.end())"); + static_assert(noexcept(sp_dyn.cbegin()), "noexcept(sp_dyn.cbegin())"); + static_assert(noexcept(sp_dyn.cend()), "noexcept(sp_dyn.cend())"); + static_assert(noexcept(sp_dyn.rbegin()), "noexcept(sp_dyn.rbegin())"); + static_assert(noexcept(sp_dyn.rend()), "noexcept(sp_dyn.rend())"); + static_assert(noexcept(sp_dyn.crbegin()), "noexcept(sp_dyn.crbegin())"); + static_assert(noexcept(sp_dyn.crend()), "noexcept(sp_dyn.crend())"); + + static_assert(noexcept(sp_nine.size()), "noexcept(sp_nine.size())"); + static_assert(noexcept(sp_nine.size_bytes()), "noexcept(sp_nine.size_bytes())"); + static_assert(noexcept(sp_nine.empty()), "noexcept(sp_nine.empty())"); + static_assert(noexcept(sp_nine[0]), "noexcept(sp_nine[0])"); // strengthened + static_assert(noexcept(sp_nine.front()), "noexcept(sp_nine.front())"); // strengthened + static_assert(noexcept(sp_nine.back()), "noexcept(sp_nine.back())"); // strengthened + static_assert(noexcept(sp_nine.data()), "noexcept(sp_nine.data())"); + static_assert(noexcept(sp_nine.begin()), "noexcept(sp_nine.begin())"); + static_assert(noexcept(sp_nine.end()), "noexcept(sp_nine.end())"); + static_assert(noexcept(sp_nine.cbegin()), "noexcept(sp_nine.cbegin())"); + static_assert(noexcept(sp_nine.cend()), "noexcept(sp_nine.cend())"); + static_assert(noexcept(sp_nine.rbegin()), "noexcept(sp_nine.rbegin())"); + static_assert(noexcept(sp_nine.rend()), "noexcept(sp_nine.rend())"); + static_assert(noexcept(sp_nine.crbegin()), "noexcept(sp_nine.crbegin())"); + static_assert(noexcept(sp_nine.crend()), "noexcept(sp_nine.crend())"); + + EXPECT_TRUE(sp_dyn.size() == 9); + EXPECT_TRUE(sp_nine.size() == 9); + + EXPECT_TRUE(sp_dyn.size_bytes() == 9 * sizeof(int)); + EXPECT_TRUE(sp_nine.size_bytes() == 9 * sizeof(int)); + + EXPECT_TRUE(!sp_dyn.empty()); + EXPECT_TRUE(!sp_nine.empty()); + + EXPECT_TRUE(sp_dyn[0] == 10); + EXPECT_TRUE(sp_nine[0] == 10); + EXPECT_TRUE(sp_dyn[8] == 90); + EXPECT_TRUE(sp_nine[8] == 90); + + EXPECT_TRUE(sp_dyn.front() == 10); + EXPECT_TRUE(sp_nine.front() == 10); + + EXPECT_TRUE(sp_dyn.back() == 90); + EXPECT_TRUE(sp_nine.back() == 90); + + EXPECT_TRUE(&sp_dyn.front() == std::begin(sequence)); + EXPECT_TRUE(&sp_nine.front() == std::begin(sequence)); + EXPECT_TRUE(&sp_dyn[4] == std::begin(sequence) + 4); + EXPECT_TRUE(&sp_nine[4] == std::begin(sequence) + 4); + EXPECT_TRUE(&sp_dyn.back() == std::begin(sequence) + 8); + EXPECT_TRUE(&sp_nine.back() == std::begin(sequence) + 8); + + EXPECT_TRUE(sp_dyn.data() == std::begin(sequence)); + EXPECT_TRUE(sp_nine.data() == std::begin(sequence)); + + EXPECT_TRUE(*sp_dyn.begin() == 10); + EXPECT_TRUE(*sp_nine.begin() == 10); + + EXPECT_TRUE(sp_dyn.end()[-2] == 80); + EXPECT_TRUE(sp_nine.end()[-2] == 80); + + EXPECT_TRUE(*sp_dyn.cbegin() == 10); + EXPECT_TRUE(*sp_nine.cbegin() == 10); + + EXPECT_TRUE(sp_dyn.cend()[-2] == 80); + EXPECT_TRUE(sp_nine.cend()[-2] == 80); + + EXPECT_TRUE(*sp_dyn.rbegin() == 90); + EXPECT_TRUE(*sp_nine.rbegin() == 90); + + EXPECT_TRUE(sp_dyn.rend()[-2] == 20); + EXPECT_TRUE(sp_nine.rend()[-2] == 20); + + EXPECT_TRUE(*sp_dyn.crbegin() == 90); + EXPECT_TRUE(*sp_nine.crbegin() == 90); + + EXPECT_TRUE(sp_dyn.crend()[-2] == 20); + EXPECT_TRUE(sp_nine.crend()[-2] == 20); + + static_assert(is_same::iterator>::value, + "is_same::iterator>::value"); + static_assert(is_same::iterator>::value, + "is_same::iterator>::value"); + static_assert(is_same::iterator>::value, + "is_same::iterator>::value"); + static_assert(is_same::iterator>::value, + "is_same::iterator>::value"); + static_assert(is_same::const_iterator>::value, + "is_same::const_iterator>::value"); + static_assert( + is_same::const_iterator>::value, + "is_same::const_iterator>::value"); + static_assert(is_same::const_iterator>::value, + "is_same::const_iterator>::value"); + static_assert( + is_same::const_iterator>::value, + "is_same::const_iterator>::value"); + static_assert( + is_same::reverse_iterator>::value, + "is_same::reverse_iterator>::value"); + static_assert( + is_same::reverse_iterator>::value, + "is_same::reverse_iterator>::value"); + static_assert(is_same::reverse_iterator>::value, + "is_same::reverse_iterator>::value"); + static_assert( + is_same::reverse_iterator>::value, + "is_same::reverse_iterator>::value"); + static_assert( + is_same::const_reverse_iterator>::value, + "is_same::const_reverse_iterator>::value"); + static_assert( + is_same::const_reverse_iterator>::value, + "is_same::const_reverse_iterator>::value"); + static_assert( + is_same::const_reverse_iterator>::value, + "is_same::const_reverse_iterator>::value"); + static_assert( + is_same::const_reverse_iterator>::value, + "is_same::const_reverse_iterator>::value"); + } + { + int sequence[9]{10, 20, 30, 40, 50, 60, 70, 80, 90}; + + constexpr size_t SizeBytes = sizeof(sequence); + + const gsl::span sp_dyn(sequence); + const gsl::span sp_nine(sequence); + const gsl::span sp_const_dyn(sequence); + const gsl::span sp_const_nine(sequence); + + static_assert(noexcept(as_bytes(sp_dyn)), "noexcept(as_bytes(sp_dyn))"); + static_assert(noexcept(as_bytes(sp_nine)), "noexcept(as_bytes(sp_nine))"); + static_assert(noexcept(as_bytes(sp_const_dyn)), "noexcept(as_bytes(sp_const_dyn))"); + static_assert(noexcept(as_bytes(sp_const_nine)), "noexcept(as_bytes(sp_const_nine))"); + static_assert(noexcept(as_writable_bytes(sp_dyn)), "noexcept(as_writable_bytes(sp_dyn))"); + static_assert(noexcept(as_writable_bytes(sp_nine)), "noexcept(as_writable_bytes(sp_nine))"); + + static_assert(AsWritableBytesCompilesFor>, + "AsWritableBytesCompilesFor>"); + static_assert(AsWritableBytesCompilesFor>, + "AsWritableBytesCompilesFor>"); + static_assert(!AsWritableBytesCompilesFor>, + "!AsWritableBytesCompilesFor>"); + static_assert(!AsWritableBytesCompilesFor>, + "!AsWritableBytesCompilesFor>"); + + auto sp_1 = as_bytes(sp_dyn); + auto sp_2 = as_bytes(sp_nine); + auto sp_3 = as_bytes(sp_const_dyn); + auto sp_4 = as_bytes(sp_const_nine); + auto sp_5 = as_writable_bytes(sp_dyn); + auto sp_6 = as_writable_bytes(sp_nine); + + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + + EXPECT_TRUE(sp_1.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_2.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_3.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_4.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_5.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_6.data() == reinterpret_cast(begin(sequence))); + + EXPECT_TRUE(sp_1.size() == SizeBytes); + EXPECT_TRUE(sp_2.size() == SizeBytes); + EXPECT_TRUE(sp_3.size() == SizeBytes); + EXPECT_TRUE(sp_4.size() == SizeBytes); + EXPECT_TRUE(sp_5.size() == SizeBytes); + EXPECT_TRUE(sp_6.size() == SizeBytes); + } +} + +// assertions for span's definition +static_assert(std::is_same::value, + "gsl::dynamic_extent must be respresented as std::size_t"); +static_assert(gsl::dynamic_extent == static_cast(-1), + "gsl::dynamic_extent must be defined as the max value of std::size_t"); + +static_assert(std::is_same::extent), const std::size_t>::value, + "Ensure that the type of gsl::span::extent is std::size_t"); +static_assert(gsl::span::extent == gsl::dynamic_extent, + "gsl::span::extent should be equivalent to gsl::dynamic_extent"); + +static_assert(std::is_same::extent), const std::size_t>::value, + "Ensure that the type of gsl::span::extent is std::size_t"); +static_assert(gsl::span::extent == 3, "Ensure that span::extent is equal to 3"); + +static_assert(std::is_same::element_type, int>::value, + "span::element_type should be int"); +static_assert(std::is_same::value_type, int>::value, + "span::value_type should be int"); +static_assert(std::is_same::size_type, std::size_t>::value, + "span::size_type should be std::size_t"); +static_assert(std::is_same::difference_type, ptrdiff_t>::value, + "span::difference_type should be std::ptrdiff_t"); +static_assert(std::is_same::pointer, int*>::value, + "span::pointer should be int*"); +static_assert(std::is_same::const_pointer, const int*>::value, + "span::const_pointer should be const int*"); +static_assert(std::is_same::reference, int&>::value, + "span::reference should be int&"); +static_assert(std::is_same::const_reference, const int&>::value, + "span::const_reference should be const int&"); + +static_assert(std::is_same::element_type, int>::value, + "span::element_type should be int"); +static_assert(std::is_same::value_type, int>::value, + "span::value_type should be int"); +static_assert(std::is_same::size_type, std::size_t>::value, + "span::size_type should be std::size_t"); +static_assert(std::is_same::difference_type, ptrdiff_t>::value, + "span::difference_type should be std::ptrdiff_t"); +static_assert(std::is_same::pointer, int*>::value, + "span::pointer should be int*"); +static_assert(std::is_same::const_pointer, const int*>::value, + "span::const_pointer should be const int*"); +static_assert(std::is_same::reference, int&>::value, + "span::reference should be int&"); +static_assert(std::is_same::const_reference, const int&>::value, + "span::const_reference should be const int&"); + +static_assert(std::is_same::element_type, const int>::value, + "span::element_type should be const int"); +static_assert(std::is_same::value_type, int>::value, + "span::value_type should be int"); +static_assert(std::is_same::size_type, std::size_t>::value, + "span::size_type should be size_t"); +static_assert(std::is_same::difference_type, ptrdiff_t>::value, + "span::difference_type should be ptrdiff_t"); +static_assert(std::is_same::pointer, const int*>::value, + "span::pointer should be const int*"); +static_assert(std::is_same::const_pointer, const int*>::value, + "span::const_pointer should be const int*"); +static_assert(std::is_same::reference, const int&>::value, + "span::reference should be const int&"); +static_assert(std::is_same::const_reference, const int&>::value, + "span::const_reference should be const int&"); + +static_assert(std::is_same::element_type, const int>::value, + "span::element_type should be const int"); +static_assert(std::is_same::value_type, int>::value, + "span::value_type should be int"); +static_assert(std::is_same::size_type, std::size_t>::value, + "span::size_type should be size_t"); +static_assert(std::is_same::difference_type, ptrdiff_t>::value, + "span::difference_type should be ptrdiff_t"); +static_assert(std::is_same::pointer, const int*>::value, + "span::pointer should be const int*"); +static_assert(std::is_same::const_pointer, const int*>::value, + "span::const_pointer should be const int*"); +static_assert(std::is_same::reference, const int&>::value, + "span::reference should be const int&"); +static_assert(std::is_same::const_reference, const int&>::value, + "span::const_reference should be const int&"); + +// assertions for span_iterator +static_assert(std::is_same::iterator>::pointer, int*>::value, + "span::iterator's pointer should be int*"); +static_assert( + std::is_same::const_iterator>::pointer, const int*>::value, + "span::const_iterator's pointer should be const int*"); +static_assert( + std::is_same::reverse_iterator, + std::reverse_iterator::iterator>>::value, + "span::reverse_iterator should equal std::reverse_iterator::iterator>"); +static_assert(std::is_same::const_reverse_iterator, + std::reverse_iterator::const_iterator>>::value, + "span::const_reverse_iterator should equal " + "std::reverse_iterator::const_iterator>"); + +static_assert(std::is_same::iterator>::pointer, int*>::value, + "span::iterator's pointer should be int*"); +static_assert(std::is_same::const_iterator>::pointer, + const int*>::value, + "span::const_iterator's pointer should be const int*"); +static_assert( + std::is_same::reverse_iterator, + std::reverse_iterator::iterator>>::value, + "span::reverse_iterator should equal std::reverse_iterator::iterator>"); +static_assert(std::is_same::const_reverse_iterator, + std::reverse_iterator::const_iterator>>::value, + "span::const_reverse_iterator should equal std::reverse_iterator::const_iterator>"); + +static_assert( + std::is_same::iterator>::pointer, const int*>::value, + "span::iterator's pointer should be int*"); +static_assert(std::is_same::const_iterator>::pointer, + const int*>::value, + "span::const_iterator's pointer should be const int*"); +static_assert(std::is_same::reverse_iterator, + std::reverse_iterator::iterator>>::value, + "span::reverse_iterator should equal std::reverse_iterator::iterator>"); +static_assert(std::is_same::const_reverse_iterator, + std::reverse_iterator::const_iterator>>::value, + "span::const_reverse_iterator should equal " + "std::reverse_iterator::const_iterator>"); + +static_assert(std::is_same::iterator>::pointer, + const int*>::value, + "span::iterator's pointer should be int*"); +static_assert(std::is_same::const_iterator>::pointer, + const int*>::value, + "span::const_iterator's pointer should be const int*"); +static_assert(std::is_same::reverse_iterator, + std::reverse_iterator::iterator>>::value, + "span::reverse_iterator should equal std::reverse_iterator::iterator>"); +static_assert(std::is_same::const_reverse_iterator, + std::reverse_iterator::const_iterator>>::value, + "span::const_reverse_iterator should equal " + "std::reverse_iterator::const_iterator>"); + +// copyability assertions +static_assert(std::is_trivially_copyable>::value, + "span should be trivially copyable"); +static_assert(std::is_trivially_copyable::iterator>::value, + "span::iterator should be trivially copyable"); +static_assert(std::is_trivially_copyable::const_iterator>::value, + "span::const_iterator should be trivially copyable"); + +static_assert(std::is_trivially_copyable>::value, + "span should be trivially copyable"); +static_assert(std::is_trivially_copyable::iterator>::value, + "span::iterator should be trivially copyable"); +static_assert(std::is_trivially_copyable::const_iterator>::value, + "span::const_iterator should be trivially copyable"); + +static_assert(std::is_trivially_copyable>::value, + "span should be trivially copyable"); +static_assert(std::is_trivially_copyable::iterator>::value, + "span::iterator should be trivially copyable"); +static_assert(std::is_trivially_copyable::const_iterator>::value, + "span::const_iterator should be trivially copyable"); + +static_assert(std::is_trivially_copyable>::value, + "span should be trivially copyable"); +static_assert(std::is_trivially_copyable::iterator>::value, + "span::iterator should be trivially copyable"); +static_assert(std::is_trivially_copyable::const_iterator>::value, + "span::const_iterator should be trivially copyable"); + +// nothrow constructible assertions +static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, + "std::is_nothrow_constructible, int*, std::size_t>"); +static_assert(std::is_nothrow_constructible, int*, std::uint16_t>::value, + "std::is_nothrow_constructible, int*, std::uint16_t>"); +static_assert(std::is_nothrow_constructible, int*, int*>::value, + "std::is_nothrow_constructible, int*, int*>"); +static_assert(std::is_nothrow_constructible, int (&)[3]>::value, + "std::is_nothrow_constructible, int(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); + +static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, + "std::is_nothrow_constructible, int*, std::size_t>"); +static_assert(std::is_nothrow_constructible, int*, std::uint16_t>::value, + "std::is_nothrow_constructible, int*, std::uint16_t>"); +static_assert(std::is_nothrow_constructible, int*, int*>::value, + "std::is_nothrow_constructible, int*, int*>"); +static_assert(std::is_nothrow_constructible, int (&)[3]>::value, + "std::is_nothrow_constructible, int(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); + +static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, + "std::is_nothrow_constructible, int*, std::size_t>"); +static_assert(std::is_nothrow_constructible, int*, int*>::value, + "std::is_nothrow_constructible, int*, int*>"); +static_assert(std::is_nothrow_constructible, int*, const int*>::value, + "std::is_nothrow_constructible, int*, const int*>"); +static_assert(std::is_nothrow_constructible, int (&)[3]>::value, + "std::is_nothrow_constructible, int(&)[3]>"); +static_assert(std::is_nothrow_constructible, const int*, int*>::value, + "std::is_nothrow_constructible, const int*, int*>"); +static_assert(std::is_nothrow_constructible, const int*, const int*>::value, + "std::is_nothrow_constructible, const int*, const int*>"); +static_assert(std::is_nothrow_constructible, const int*, std::size_t>::value, + "std::is_nothrow_constructible, const int*, std::size_t>"); +static_assert(std::is_nothrow_constructible, const int (&)[3]>::value, + "std::is_nothrow_constructible, const int(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); +static_assert(std::is_nothrow_constructible, const std::array&>::value, + "std::is_nothrow_constructible, const std::array&>"); + +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); + +static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, + "std::is_nothrow_constructible, Base(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); + +static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, + "std::is_nothrow_constructible, Base(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); + +static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, + "std::is_nothrow_constructible, Base(&)[3]>"); +static_assert(std::is_nothrow_constructible, const Base (&)[3]>::value, + "std::is_nothrow_constructible, const Base(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); +static_assert( + std::is_nothrow_constructible, const std::array&>::value, + "std::is_nothrow_constructible, const std::array&>"); + +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); + +// non-constructible assertions +static_assert(!std::is_constructible, const int*, int*>::value, + "!std::is_constructible, const int*, int*>"); +static_assert(!std::is_constructible, const int*, const int*>::value, + "!std::is_constructible, const int*, const int*>"); +static_assert(!std::is_constructible, const int*, double*>::value, + "!std::is_constructible, const int*, double*>"); +static_assert(!std::is_constructible, const int*, std::size_t>::value, + "!std::is_constructible, const int*, std::size_t>"); +static_assert(!std::is_constructible, const int (&)[3]>::value, + "!std::is_constructible, const int(&)[3]>"); +static_assert(!std::is_constructible, double*, int*>::value, + "!std::is_constructible, double*, int*>"); +static_assert(!std::is_constructible, double*, const int*>::value, + "!std::is_constructible, double*, const int*>"); +static_assert(!std::is_constructible, double*, double*>::value, + "!std::is_constructible, double*, double*>"); +static_assert(!std::is_constructible, double*, std::size_t>::value, + "!std::is_constructible, double*, std::size_t>"); +static_assert(!std::is_constructible, double (&)[3]>::value, + "!std::is_constructible, double(&)[3]>"); +static_assert(!std::is_constructible, int*, double*>::value, + "!std::is_constructible, int*, double*>"); +static_assert(!std::is_constructible, std::size_t, int*>::value, + "!std::is_constructible, std::size_t, int*>"); +static_assert(!std::is_constructible, std::size_t, std::size_t>::value, + "!std::is_constructible, std::size_t, std::size_t>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const std::array&>::value, + "!std::is_constructible, const std::array&>"); + +static_assert(!std::is_constructible, int*, double*>::value, + "!std::is_constructible, int*, double*>"); +static_assert(!std::is_constructible, int (&)[500]>::value, + "!std::is_constructible, int(&)[500]>"); +static_assert(!std::is_constructible, const int*, int*>::value, + "!std::is_constructible, const int*, int*>"); +static_assert(!std::is_constructible, const int*, const int*>::value, + "!std::is_constructible, const int*, const int*>"); +static_assert(!std::is_constructible, const int*, std::size_t>::value, + "!std::is_constructible, const int*, std::size_t>"); +static_assert(!std::is_constructible, const int*, double*>::value, + "!std::is_constructible, const int*, double*>"); +static_assert(!std::is_constructible, const int (&)[3]>::value, + "!std::is_constructible, const int(&)[3]>"); +static_assert(!std::is_constructible, double*, std::size_t>::value, + "!std::is_constructible, double*, std::size_t>"); +static_assert(!std::is_constructible, double*, int*>::value, + "!std::is_constructible, double*, int*>"); +static_assert(!std::is_constructible, double*, const int*>::value, + "!std::is_constructible, double*, const int*>"); +static_assert(!std::is_constructible, double*, double*>::value, + "!std::is_constructible, double*, double*>"); +static_assert(!std::is_constructible, double (&)[3]>::value, + "!std::is_constructible, double(&)[3]>"); + +static_assert(!std::is_constructible, std::size_t, int*>::value, + "!std::is_constructible, std::size_t, int*>"); +static_assert(!std::is_constructible, std::size_t, std::size_t>::value, + "!std::is_constructible, std::size_t, std::size_t>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const std::array&>::value, + "!std::is_constructible, const std::array&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, double (&)[3]>::value, + "!std::is_constructible, double(&)[3]>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert( + !std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, Derived (&)[3]>::value, + "!std::is_constructible, Derived(&)[3]>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, Derived (&)[3]>::value, + "!std::is_constructible, Derived(&)[3]>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); + +static_assert(!std::is_constructible, Derived (&)[3]>::value, + "!std::is_constructible, Derived(&)[3]>"); +static_assert(!std::is_constructible, const Derived (&)[3]>::value, + "!std::is_constructible, const Derived(&)[3]>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const std::array&>::value, + "!std::is_constructible, const std::array&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert( + !std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert( + !std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const std::array&>::value, + "!std::is_constructible, const std::array&>"); + +// no throw copy constructor +static_assert(std::is_nothrow_copy_constructible>::value, + "std::is_nothrow_copy_constructible>"); +static_assert(std::is_nothrow_copy_constructible>::value, + "std::is_nothrow_copy_constructible>"); +static_assert(std::is_nothrow_copy_constructible>::value, + "std::is_nothrow_copy_constructible>"); +static_assert(std::is_nothrow_copy_constructible>::value, + "std::is_nothrow_copy_constructible>"); + +// no throw copy assignment +static_assert(std::is_nothrow_copy_assignable>::value, + "std::is_nothrow_copy_assignable>"); +static_assert(std::is_nothrow_copy_assignable>::value, + "std::is_nothrow_copy_assignable>"); +static_assert(std::is_nothrow_copy_assignable>::value, + "std::is_nothrow_copy_assignable>"); +static_assert(std::is_nothrow_copy_assignable>::value, + "std::is_nothrow_copy_assignable>"); + +// no throw destruction +static_assert(std::is_nothrow_destructible>::value, + "std::is_nothrow_destructible>"); +static_assert(std::is_nothrow_destructible>::value, + "std::is_nothrow_destructible>"); +static_assert(std::is_nothrow_destructible>::value, + "std::is_nothrow_destructible>"); + +// conversions +static_assert(std::is_convertible>::value, + "std::is_convertible>"); +static_assert(std::is_convertible>::value, + "std::is_convertible>"); +static_assert(std::is_convertible>::value, + "std::is_convertible>"); + +static_assert(std::is_convertible>::value, + "std::is_convertible>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index ab437a5..2c4a19c 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -29,6 +29,7 @@ #include // for string #include // for integral_constant<>::value, is_default_co... #include // for vector +#include using namespace std; using namespace gsl; @@ -1021,11 +1022,11 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE(s.begin() == begin(s)); - EXPECT_TRUE(s.end() == end(s)); + EXPECT_TRUE(s.begin() == std::begin(s)); + EXPECT_TRUE(s.end() == std::end(s)); - EXPECT_TRUE(s.cbegin() == cbegin(s)); - EXPECT_TRUE(s.cend() == cend(s)); + EXPECT_TRUE(s.cbegin() == std::cbegin(s)); + EXPECT_TRUE(s.cend() == std::cend(s)); EXPECT_TRUE(s.rbegin() == rbegin(s)); EXPECT_TRUE(s.rend() == rend(s)); diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 1fb0fd2..f7f7ce3 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -23,7 +23,7 @@ #include // for numeric_limits #include // for uint32_t, int32_t #include // for is_same -#include // for std::size_t +#include // for std::ptrdiff_t using namespace gsl; From 67a7f7eaef6481d9f929bef24839b05dfbbd7b5a Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Fri, 14 Feb 2020 15:44:58 -0800 Subject: [PATCH 61/81] errors in appveyor are indicating that AsWritableByesCompilersFor needs to be static. --- tests/span_compatibility_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index cdf0bff..62793e7 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -42,10 +42,10 @@ static_assert(!std::is_convertible::value, "!std::is_convertible"); template -constexpr bool AsWritableBytesCompilesFor = false; +static constexpr bool AsWritableBytesCompilesFor = false; template -constexpr bool AsWritableBytesCompilesFor()))>> = +static constexpr bool AsWritableBytesCompilesFor()))>> = true; TEST(span_test, std_span_compatibilty_assertion_tests) From b6b1e9c3cf1200ad5d912d4bd63364286863cbfc Mon Sep 17 00:00:00 2001 From: jordan maples Date: Fri, 14 Feb 2020 16:13:21 -0800 Subject: [PATCH 62/81] assert -> expect_true --- tests/span_compatibility_tests.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 62793e7..d4cde0c 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -48,22 +48,22 @@ template static constexpr bool AsWritableBytesCompilesFor()))>> = true; -TEST(span_test, std_span_compatibilty_assertion_tests) +TEST(span_compatibility_tests, assertion_tests) { int arr[3]{10, 20, 30}; std::array stl{{100, 200, 300}}; { gsl::span sp_dyn; - assert(sp_dyn.data() == nullptr); - assert(sp_dyn.size() == 0); - assert(sp_dyn.empty()); + EXPECT_TRUE(sp_dyn.data() == nullptr); + EXPECT_TRUE(sp_dyn.size() == 0); + EXPECT_TRUE(sp_dyn.empty()); } { gsl::span sp_zero; - assert(sp_zero.data() == nullptr); - assert(sp_zero.size() == 0); - assert(sp_zero.empty()); + EXPECT_TRUE(sp_zero.data() == nullptr); + EXPECT_TRUE(sp_zero.size() == 0); + EXPECT_TRUE(sp_zero.empty()); gsl::span sp_dyn_a(arr, 3); gsl::span sp_dyn_b(begin(arr), 3); From 6b01a0488b1157a2c49805b85becd09e1fe84f57 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Fri, 14 Feb 2020 16:25:25 -0800 Subject: [PATCH 63/81] Update span_compatibility_tests.cpp some fixes. --- tests/span_compatibility_tests.cpp | 35 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index d4cde0c..57a85e7 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -41,13 +41,6 @@ static_assert(std::is_convertible::value, "std::is_convertible< static_assert(!std::is_convertible::value, "!std::is_convertible"); -template -static constexpr bool AsWritableBytesCompilesFor = false; - -template -static constexpr bool AsWritableBytesCompilesFor()))>> = - true; - TEST(span_compatibility_tests, assertion_tests) { int arr[3]{10, 20, 30}; @@ -501,15 +494,6 @@ TEST(span_compatibility_tests, assertion_tests) static_assert(noexcept(as_writable_bytes(sp_dyn)), "noexcept(as_writable_bytes(sp_dyn))"); static_assert(noexcept(as_writable_bytes(sp_nine)), "noexcept(as_writable_bytes(sp_nine))"); - static_assert(AsWritableBytesCompilesFor>, - "AsWritableBytesCompilesFor>"); - static_assert(AsWritableBytesCompilesFor>, - "AsWritableBytesCompilesFor>"); - static_assert(!AsWritableBytesCompilesFor>, - "!AsWritableBytesCompilesFor>"); - static_assert(!AsWritableBytesCompilesFor>, - "!AsWritableBytesCompilesFor>"); - auto sp_1 = as_bytes(sp_dyn); auto sp_2 = as_bytes(sp_nine); auto sp_3 = as_bytes(sp_const_dyn); @@ -1064,3 +1048,22 @@ static_assert(std::is_convertible&, gsl::span>::va static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); + + +#if __cplusplus >= 201703l +template +inline constexpr bool AsWritableBytesCompilesFor = false; + +template +inline constexpr bool AsWritableBytesCompilesFor()))>> = + true; + +static_assert(AsWritableBytesCompilesFor>, + "AsWritableBytesCompilesFor>"); +static_assert(AsWritableBytesCompilesFor>, + "AsWritableBytesCompilesFor>"); +static_assert(!AsWritableBytesCompilesFor>, + "!AsWritableBytesCompilesFor>"); +static_assert(!AsWritableBytesCompilesFor>, + "!AsWritableBytesCompilesFor>"); +#endif // __cplusplus >= 201703l From 8d6ca323fad94f22b0233d30fdf13228bcb5ccb0 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 18 Feb 2020 10:13:03 -0800 Subject: [PATCH 64/81] GTest latest is breaking, rolling back to 1.10 until further investigation --- tests/CMakeLists.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt.in b/tests/CMakeLists.txt.in index 50c041d..f380b8f 100644 --- a/tests/CMakeLists.txt.in +++ b/tests/CMakeLists.txt.in @@ -4,7 +4,7 @@ project(googletest-download NONE) include(ExternalProject) ExternalProject_Add(googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG master + GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" CONFIGURE_COMMAND "" From f4c608fd39fe8129dfb2ea5e737e2aea6baf4519 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 18 Feb 2020 14:09:11 -0800 Subject: [PATCH 65/81] addressing comments --- include/gsl/span | 47 ++++++++++++++---------------- tests/span_compatibility_tests.cpp | 12 ++++---- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index cffe043..e3ea0db 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -25,7 +25,6 @@ #include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... -#include // for std::addressof #include #include // for enable_if_t, declval, is_convertible, inte... #include @@ -147,14 +146,14 @@ namespace details constexpr reference operator*() const noexcept { - Expects(begin_ && current_ && end_); + Expects(begin_ && end_); Expects(begin_ <= current_ && current_ < end_); return *current_; } constexpr pointer operator->() const noexcept { - Expects(begin_ && current_ && end_); + Expects(begin_ && end_); Expects(begin_ <= current_ && current_ < end_); return current_; } @@ -175,7 +174,7 @@ namespace details constexpr span_iterator& operator--() noexcept { - Expects(begin_ && current_ && end_); + Expects(begin_ && end_); Expects(begin_ < current_); --current_; return *this; @@ -346,7 +345,7 @@ namespace details static_assert(Ext != dynamic_extent, "A fixed-size span must not have size == dynamic_extent"); - constexpr extent_type() noexcept {} + constexpr extent_type() noexcept = default; template constexpr extent_type(extent_type ext) @@ -433,7 +432,7 @@ public: } constexpr span(pointer firstElem, pointer lastElem) noexcept - : storage_(firstElem, static_cast(std::distance(firstElem, lastElem))) + : storage_(firstElem, static_cast(lastElem - firstElem)) { if (Extent != dynamic_extent) { Expects(lastElem - firstElem == static_cast(Extent)); } @@ -442,7 +441,7 @@ public: template ::value, int> = 0> constexpr span(element_type (&arr)[N]) noexcept - : storage_(KnownNotNull{std::addressof(arr[0])}, details::extent_type()) + : storage_(KnownNotNull{arr + 0}, details::extent_type()) {} template ::value && !details::is_std_array::value && - std::is_convertible::value && - std::is_convertible().data()), pointer>::value>> + std::is_pointer().data())>::value && + std::is_convertible().data())>(*)[], element_type(*)[]>::value>> constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) {} @@ -474,8 +473,8 @@ public: class = std::enable_if_t< std::is_const::value && !details::is_span::value && !details::is_std_array::value && - std::is_convertible::value && - std::is_convertible().data()), pointer>::value>> + std::is_pointer().data())>::value && + std::is_convertible().data())>(*)[], element_type(*)[]>::value>> constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size()) {} @@ -497,7 +496,6 @@ public: template constexpr span first() const noexcept { - Expects(Count != dynamic_extent); Expects(Count <= size()); return {data(), Count}; } @@ -505,20 +503,19 @@ public: template // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on - constexpr span last() const noexcept + // clang-format on + constexpr span last() const noexcept { - Expects(Count != dynamic_extent); - Expects(size() >= Count); + Expects(Count <= size()); return {data() + (size() - Count), Count}; } template // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on - constexpr auto subspan() const noexcept -> - typename details::calculate_subspan_type::type + // clang-format on + constexpr auto subspan() const noexcept -> + typename details::calculate_subspan_type::type { Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset))); @@ -589,8 +586,8 @@ public: constexpr iterator end() const noexcept { const auto data = storage_.data(); - const auto size = storage_.size(); - return {data, data + size, data + size}; + const auto endData = data + storage_.size(); + return {data, endData, endData}; } constexpr const_iterator cbegin() const noexcept @@ -602,8 +599,8 @@ public: constexpr const_iterator cend() const noexcept { const auto data = storage_.data(); - const auto size = storage_.size(); - return {data, data + size, data + size}; + const auto endData = data + storage_.size(); + return {data, endData, endData}; } constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } @@ -767,6 +764,7 @@ namespace details template struct calculate_byte_size : std::integral_constant { + static_assert(Extent < dynamic_extent / sizeof(ElementType), "Size is too big."); }; template @@ -843,12 +841,11 @@ constexpr span make_span(Ptr& cont) return span(cont); } -// Specialization of gsl::at for span template constexpr ElementType& at(span s, index i) { // No bounds checking here because it is done in span::operator[] called below - Ensures(i >= 0); + Expects(i >= 0); return s[static_cast(i)]; } diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 57a85e7..0301ace 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -931,6 +931,8 @@ static_assert(!std::is_constructible, Derived (&)[3]>::value, "!std::is_constructible, Derived(&)[3]>"); static_assert(!std::is_constructible, std::array&>::value, "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, std::vector&>::value, + "!std::is_constructible, std::vector&>"); static_assert(!std::is_constructible, const gsl::span&>::value, "!std::is_constructible, const gsl::span&>"); static_assert(!std::is_constructible, const gsl::span&>::value, @@ -1048,16 +1050,16 @@ static_assert(std::is_convertible&, gsl::span>::va static_assert(std::is_convertible&, gsl::span>::value, "std::is_convertible&, gsl::span>"); - - + + #if __cplusplus >= 201703l template -inline constexpr bool AsWritableBytesCompilesFor = false; +static constexpr bool AsWritableBytesCompilesFor = false; template -inline constexpr bool AsWritableBytesCompilesFor()))>> = +static constexpr bool AsWritableBytesCompilesFor()))>> = true; - + static_assert(AsWritableBytesCompilesFor>, "AsWritableBytesCompilesFor>"); static_assert(AsWritableBytesCompilesFor>, From 46603698ec9a37b07c2a39926c47cb465bda0aa8 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 18 Feb 2020 15:36:15 -0800 Subject: [PATCH 66/81] rewrite operators in iterator to take advantage of nrvo --- include/gsl/span | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index e3ea0db..0d8dcb0 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -199,7 +199,8 @@ namespace details constexpr span_iterator operator+(const difference_type n) const noexcept { span_iterator ret = *this; - return ret += n; + ret += n; + return ret; } friend constexpr span_iterator operator+(const difference_type n, @@ -220,7 +221,8 @@ namespace details constexpr span_iterator operator-(const difference_type n) const noexcept { span_iterator ret = *this; - return ret -= n; + ret -= n; + return ret; } template < @@ -343,8 +345,6 @@ namespace details public: using size_type = std::size_t; - static_assert(Ext != dynamic_extent, "A fixed-size span must not have size == dynamic_extent"); - constexpr extent_type() noexcept = default; template From 94f43d4adfba526c43f625e4409acbcb9f2fbe24 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 19 Feb 2020 14:28:12 -0800 Subject: [PATCH 67/81] splitting up span's standard and non-standard behavior --- include/gsl/span | 157 ------------- include/gsl/span_ext | 198 ++++++++++++++++ include/gsl/string_span | 2 +- tests/CMakeLists.txt | 1 + tests/span_compatibility_tests.cpp | 1 + tests/span_ext_tests.cpp | 360 +++++++++++++++++++++++++++++ tests/span_tests.cpp | 280 ---------------------- 7 files changed, 561 insertions(+), 438 deletions(-) create mode 100644 include/gsl/span_ext create mode 100644 tests/span_ext_tests.cpp diff --git a/include/gsl/span b/include/gsl/span index 0d8dcb0..23c58c9 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -21,13 +21,10 @@ #include // for byte #include // for narrow_cast, narrow -#include // for lexicographical_compare #include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... -#include #include // for enable_if_t, declval, is_convertible, inte... -#include #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) @@ -716,43 +713,6 @@ template constexpr const typename span::size_type span::extent; #endif -// [span.comparison], span comparison operators -template -constexpr bool operator==(span l, span r) -{ - return std::equal(l.begin(), l.end(), r.begin(), r.end()); -} - -template -constexpr bool operator!=(span l, span r) -{ - return !(l == r); -} - -template -constexpr bool operator<(span l, span r) -{ - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); -} - -template -constexpr bool operator<=(span l, span r) -{ - return !(l > r); -} - -template -constexpr bool operator>(span l, span r) -{ - return r < l; -} - -template -constexpr bool operator>=(span l, span r) -{ - return !(l < r); -} - namespace details { // if we only supported compilers with good constexpr support then @@ -796,123 +756,6 @@ as_writable_bytes(span s) noexcept return {reinterpret_cast(s.data()), s.size_bytes()}; } -// -// make_span() - Utility functions for creating spans -// -template -constexpr span make_span(ElementType* ptr, typename span::size_type count) -{ - return span(ptr, count); -} - -template -constexpr span make_span(ElementType* firstElem, ElementType* lastElem) -{ - return span(firstElem, lastElem); -} - -template -constexpr span make_span(ElementType (&arr)[N]) noexcept -{ - return span(arr); -} - -template -constexpr span make_span(Container& cont) -{ - return span(cont); -} - -template -constexpr span make_span(const Container& cont) -{ - return span(cont); -} - -template -constexpr span make_span(Ptr& cont, std::size_t count) -{ - return span(cont, count); -} - -template -constexpr span make_span(Ptr& cont) -{ - return span(cont); -} - -template -constexpr ElementType& at(span s, index i) -{ - // No bounds checking here because it is done in span::operator[] called below - Expects(i >= 0); - return s[static_cast(i)]; -} - -// [span.obs] Free observer functions -template -constexpr std::ptrdiff_t ssize(const span& s) noexcept -{ - return static_cast(s.size()); -} - -// [span.iter] Free functions for begin/end functions -template -constexpr typename span::iterator -begin(const span& s) noexcept -{ - return s.begin(); -} - -template -constexpr typename span::iterator -end(const span& s) noexcept -{ - return s.end(); -} - -template -constexpr typename span::const_iterator -cbegin(const span& s) noexcept -{ - return s.cbegin(); -} - -template -constexpr typename span::const_iterator -cend(const span& s) noexcept -{ - return s.cend(); -} - -template -constexpr typename span::reverse_iterator -rbegin(const span& s) noexcept -{ - return s.rbegin(); -} - -template -constexpr typename span::reverse_iterator -rend(const span& s) noexcept -{ - return s.rend(); -} - -template -constexpr typename span::const_reverse_iterator -crbegin(const span& s) noexcept -{ - return s.crbegin(); -} - -template -constexpr typename span::const_reverse_iterator -crend(const span& s) noexcept -{ - return s.crend(); -} - } // namespace gsl #if defined(_MSC_VER) && !defined(__clang__) diff --git a/include/gsl/span_ext b/include/gsl/span_ext new file mode 100644 index 0000000..b466df8 --- /dev/null +++ b/include/gsl/span_ext @@ -0,0 +1,198 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_SPAN_EXT_H +#define GSL_SPAN_EXT_H + +/////////////////////////////////////////////////////////////////////////////// +// +// File: span_ext +// Purpose: continue offering features that have been cut from the official +// implementation of span. +// While modernizing gsl::span a number of features needed to be removed to +// be compliant with the design of std::span +// +/////////////////////////////////////////////////////////////////////////////// + + +#include // for narrow_cast, narrow +#include // for span + +#include // for lexicographical_compare +#include // for ptrdiff_t, size_t +#include + +namespace gsl +{ + +// [span.comparison], span comparison operators +template +constexpr bool operator==(span l, span r) +{ + return std::equal(l.begin(), l.end(), r.begin(), r.end()); +} + +template +constexpr bool operator!=(span l, span r) +{ + return !(l == r); +} + +template +constexpr bool operator<(span l, span r) +{ + return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); +} + +template +constexpr bool operator<=(span l, span r) +{ + return !(l > r); +} + +template +constexpr bool operator>(span l, span r) +{ + return r < l; +} + +template +constexpr bool operator>=(span l, span r) +{ + return !(l < r); +} + +// +// make_span() - Utility functions for creating spans +// +template +constexpr span make_span(ElementType* ptr, typename span::size_type count) +{ + return span(ptr, count); +} + +template +constexpr span make_span(ElementType* firstElem, ElementType* lastElem) +{ + return span(firstElem, lastElem); +} + +template +constexpr span make_span(ElementType (&arr)[N]) noexcept +{ + return span(arr); +} + +template +constexpr span make_span(Container& cont) +{ + return span(cont); +} + +template +constexpr span make_span(const Container& cont) +{ + return span(cont); +} + +template +constexpr span make_span(Ptr& cont, std::size_t count) +{ + return span(cont, count); +} + +template +constexpr span make_span(Ptr& cont) +{ + return span(cont); +} + +// Specialization of gsl::at for span +template +constexpr ElementType& at(span s, index i) +{ + // No bounds checking here because it is done in span::operator[] called below + Ensures(i >= 0); + return s[narrow_cast(i)]; +} + +// [span.obs] Free observer functions +template +constexpr std::ptrdiff_t ssize(const span& s) noexcept +{ + return static_cast(s.size()); +} + +// [span.iter] Free functions for begin/end functions +template +constexpr typename span::iterator +begin(const span& s) noexcept +{ + return s.begin(); +} + +template +constexpr typename span::iterator +end(const span& s) noexcept +{ + return s.end(); +} + +template +constexpr typename span::const_iterator +cbegin(const span& s) noexcept +{ + return s.cbegin(); +} + +template +constexpr typename span::const_iterator +cend(const span& s) noexcept +{ + return s.cend(); +} + +template +constexpr typename span::reverse_iterator +rbegin(const span& s) noexcept +{ + return s.rbegin(); +} + +template +constexpr typename span::reverse_iterator +rend(const span& s) noexcept +{ + return s.rend(); +} + +template +constexpr typename span::const_reverse_iterator +crbegin(const span& s) noexcept +{ + return s.crbegin(); +} + +template +constexpr typename span::const_reverse_iterator +crend(const span& s) noexcept +{ + return s.crend(); +} + +} // namespace gsl + +#endif // GSL_SPAN_EXT_H diff --git a/include/gsl/string_span b/include/gsl/string_span index cc0588e..2207291 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -19,7 +19,7 @@ #include // for Ensures, Expects #include // for narrow_cast -#include // for operator!=, operator==, dynamic_extent +#include // for operator!=, operator==, dynamic_extent #include // for equal, lexicographical_compare #include // for array diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 38dbb85..1099fda 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -153,6 +153,7 @@ function(add_gsl_test name) endfunction() add_gsl_test(span_tests) +add_gsl_test(span_ext_tests) add_gsl_test(span_compatibility_tests) add_gsl_test(multi_span_tests) add_gsl_test(strided_span_tests) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 0301ace..8733e72 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -24,6 +24,7 @@ #include // for reverse_iterator, operator-, operator== #include // for integral_constant<>::value, is_default_co... #include +#include // for vector using namespace std; using namespace gsl; diff --git a/tests/span_ext_tests.cpp b/tests/span_ext_tests.cpp new file mode 100644 index 0000000..7b751e7 --- /dev/null +++ b/tests/span_ext_tests.cpp @@ -0,0 +1,360 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for narrow_cast, at +#include // for operator==, operator!=, make_span + +#include // for array +#include // for cerr +#include // for vector + +using namespace std; +using namespace gsl; + +namespace +{ +static constexpr char deathstring[] = "Expected Death"; +} // namespace + +TEST(span_ext_test, make_span_from_pointer_length_constructor) +{ + std::set_terminate([] { + std::cerr << "Expected Death. from_pointer_length_constructor"; + std::abort(); + }); + int arr[4] = {1, 2, 3, 4}; + + { + auto s = make_span(&arr[0], 2); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); + } + + { + int* p = nullptr; + auto s = make_span(p, narrow_cast::size_type>(0)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + } + + { + int* p = nullptr; + auto workaround_macro = [=]() { make_span(p, 2); }; + EXPECT_DEATH(workaround_macro(), deathstring); + } +} + +TEST(span_ext_test, make_span_from_pointer_pointer_construction) +{ + int arr[4] = {1, 2, 3, 4}; + + { + auto s = make_span(&arr[0], &arr[2]); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); + } + + { + auto s = make_span(&arr[0], &arr[0]); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); + } + + { + int* p = nullptr; + auto s = make_span(p, p); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + } +} + +TEST(span_ext_test, make_span_from_array_constructor) + { + int arr[5] = {1, 2, 3, 4, 5}; + int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; + int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + + { + const auto s = make_span(arr); + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == std::addressof(arr[0])); + } + + { + const auto s = make_span(std::addressof(arr2d[0]), 1); + EXPECT_TRUE(s.size() == 1); + EXPECT_TRUE(s.data() == std::addressof(arr2d[0])); + } + + { + const auto s = make_span(std::addressof(arr3d[0]), 1); + EXPECT_TRUE(s.size() == 1); + EXPECT_TRUE(s.data() == std::addressof(arr3d[0])); + } + } + + TEST(span_ext_test, make_span_from_dynamic_array_constructor) + { + double(*arr)[3][4] = new double[100][3][4]; + + { + auto s = make_span(&arr[0][0][0], 10); + EXPECT_TRUE(s.size() == 10); + EXPECT_TRUE(s.data() == &arr[0][0][0]); + } + + delete[] arr; + } + + TEST(span_ext_test, make_span_from_std_array_constructor) + { + std::array arr = {1, 2, 3, 4}; + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } + + // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590 + { + span s1 = make_span(arr); + + static span s2; + s2 = s1; + + #if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \ + __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__) + // Known to be broken in gcc 6.4 and 6.5 with optimizations + // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116 + EXPECT_TRUE(s1.size() == 4); + EXPECT_TRUE(s2.size() == 0); + #else + EXPECT_TRUE(s1.size() == s2.size()); + #endif + } + } + + TEST(span_ext_test, make_span_from_const_std_array_constructor) + { + const std::array arr = {1, 2, 3, 4}; + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } + } + + TEST(span_ext_test, make_span_from_std_array_const_constructor) + { + std::array arr = {1, 2, 3, 4}; + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } + } + + TEST(span_ext_test, make_span_from_container_constructor) + { + std::vector v = {1, 2, 3}; + const std::vector cv = v; + + { + auto s = make_span(v); + EXPECT_TRUE(s.size() == v.size()); + EXPECT_TRUE(s.data() == v.data()); + + auto cs = make_span(cv); + EXPECT_TRUE(cs.size() == cv.size()); + EXPECT_TRUE(cs.data() == cv.data()); + } + } + + TEST(span_test, interop_with_gsl_at) + { + int arr[5] = {1, 2, 3, 4, 5}; + span s{arr}; + EXPECT_TRUE(at(s, 0) == 1); + EXPECT_TRUE(at(s, 1) == 2); + } + + TEST(span_ext_test, iterator_free_functions) + { + int a[] = {1, 2, 3, 4}; + span s{a}; + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); + + EXPECT_TRUE(s.begin() == begin(s)); + EXPECT_TRUE(s.end() == end(s)); + + EXPECT_TRUE(s.cbegin() == cbegin(s)); + EXPECT_TRUE(s.cend() == cend(s)); + + EXPECT_TRUE(s.rbegin() == rbegin(s)); + EXPECT_TRUE(s.rend() == rend(s)); + + EXPECT_TRUE(s.crbegin() == crbegin(s)); + EXPECT_TRUE(s.crend() == crend(s)); + } + + TEST(span_ext_test, ssize_free_function) + { + int a[] = {1, 2, 3, 4}; + span s{a}; + + EXPECT_FALSE((std::is_same::value)); + EXPECT_TRUE(s.size() == static_cast(ssize(s))); + } + + TEST(span_ext_test, comparison_operators) + { + { + span s1; + span s2; + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 != s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {2, 1}; + span s1 = arr; + span s2 = arr; + + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {2, 1}; // bigger + + span s1; + span s2 = arr; + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } + + { + int arr1[] = {1, 2}; + int arr2[] = {1, 2}; + span s1 = arr1; + span s2 = arr2; + + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {1, 2, 3}; + + span s1 = {&arr[0], 2}; // shorter + span s2 = arr; // longer + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } + + { + int arr1[] = {1, 2}; // smaller + int arr2[] = {2, 1}; // bigger + + span s1 = arr1; + span s2 = arr2; + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } + } \ No newline at end of file diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 2c4a19c..689fff9 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -196,27 +196,6 @@ TEST(span_test, from_pointer_length_constructor) auto workaround_macro = [=]() { const span s{p, 2}; }; EXPECT_DEATH(workaround_macro(), deathstring); } - - { - auto s = make_span(&arr[0], 2); - EXPECT_TRUE(s.size() == 2); - EXPECT_TRUE(s.data() == &arr[0]); - EXPECT_TRUE(s[0] == 1); - EXPECT_TRUE(s[1] == 2); - } - - { - int* p = nullptr; - auto s = make_span(p, narrow_cast::size_type>(0)); - EXPECT_TRUE(s.size() == 0); - EXPECT_TRUE(s.data() == nullptr); - } - - { - int* p = nullptr; - auto workaround_macro = [=]() { make_span(p, 2); }; - EXPECT_DEATH(workaround_macro(), deathstring); - } } TEST(span_test, from_pointer_pointer_construction) @@ -283,27 +262,6 @@ TEST(span_test, from_pointer_pointer_construction) // auto workaround_macro = [&]() { span s{&arr[0], p}; }; // EXPECT_DEATH(workaround_macro(), deathstring); //} - - { - auto s = make_span(&arr[0], &arr[2]); - EXPECT_TRUE(s.size() == 2); - EXPECT_TRUE(s.data() == &arr[0]); - EXPECT_TRUE(s[0] == 1); - EXPECT_TRUE(s[1] == 2); - } - - { - auto s = make_span(&arr[0], &arr[0]); - EXPECT_TRUE(s.size() == 0); - EXPECT_TRUE(s.data() == &arr[0]); - } - - { - int* p = nullptr; - auto s = make_span(p, p); - EXPECT_TRUE(s.size() == 0); - EXPECT_TRUE(s.data() == nullptr); - } } TEST(span_test, from_array_constructor) @@ -393,24 +351,6 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(s.size() == 1); } - { - const auto s = make_span(arr); - EXPECT_TRUE(s.size() == 5); - EXPECT_TRUE(s.data() == std::addressof(arr[0])); - } - - { - const auto s = make_span(std::addressof(arr2d[0]), 1); - EXPECT_TRUE(s.size() == 1); - EXPECT_TRUE(s.data() == std::addressof(arr2d[0])); - } - - { - const auto s = make_span(std::addressof(arr3d[0]), 1); - EXPECT_TRUE(s.size() == 1); - EXPECT_TRUE(s.data() == std::addressof(arr3d[0])); - } - AddressOverloaded ao_arr[5] = {}; { @@ -430,12 +370,6 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(s.data() == &arr[0][0][0]); } - { - auto s = make_span(&arr[0][0][0], 10); - EXPECT_TRUE(s.size() == 10); - EXPECT_TRUE(s.data() == &arr[0][0][0]); - } - delete[] arr; } @@ -517,30 +451,6 @@ TEST(span_test, from_array_constructor) // try to take a temporary std::array take_a_span(get_an_array()); } - - { - auto s = make_span(arr); - EXPECT_TRUE(s.size() == arr.size()); - EXPECT_TRUE(s.data() == arr.data()); - } - - // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590 - { - span s1 = make_span(arr); - - static span s2; - s2 = s1; - - #if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \ - __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__) - // Known to be broken in gcc 6.4 and 6.5 with optimizations - // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116 - EXPECT_TRUE(s1.size() == 4); - EXPECT_TRUE(s2.size() == 0); - #else - EXPECT_TRUE(s1.size() == s2.size()); - #endif - } } TEST(span_test, from_const_std_array_constructor) @@ -591,12 +501,6 @@ TEST(span_test, from_array_constructor) // try to take a temporary std::array take_a_span(get_an_array()); } - - { - auto s = make_span(arr); - EXPECT_TRUE(s.size() == arr.size()); - EXPECT_TRUE(s.data() == arr.data()); - } } TEST(span_test, from_std_array_const_constructor) @@ -636,12 +540,6 @@ TEST(span_test, from_array_constructor) span s{arr}; } #endif - - { - auto s = make_span(arr); - EXPECT_TRUE(s.size() == arr.size()); - EXPECT_TRUE(s.data() == arr.data()); - } } TEST(span_test, from_container_constructor) @@ -730,16 +628,6 @@ TEST(span_test, from_array_constructor) span s{m}; #endif } - - { - auto s = make_span(v); - EXPECT_TRUE(s.size() == v.size()); - EXPECT_TRUE(s.data() == v.data()); - - auto cs = make_span(cv); - EXPECT_TRUE(cs.size() == cv.size()); - EXPECT_TRUE(cs.data() == cv.data()); - } } TEST(span_test, from_convertible_span_constructor){{span avd; @@ -1004,46 +892,6 @@ TEST(span_test, from_array_constructor) span::const_iterator cit3 = it + 4; EXPECT_TRUE(cit3 == s.cend()); } - - TEST(span_test, iterator_free_functions) - { - int a[] = {1, 2, 3, 4}; - span s{a}; - - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - - EXPECT_TRUE(s.begin() == std::begin(s)); - EXPECT_TRUE(s.end() == std::end(s)); - - EXPECT_TRUE(s.cbegin() == std::cbegin(s)); - EXPECT_TRUE(s.cend() == std::cend(s)); - - EXPECT_TRUE(s.rbegin() == rbegin(s)); - EXPECT_TRUE(s.rend() == rend(s)); - - EXPECT_TRUE(s.crbegin() == crbegin(s)); - EXPECT_TRUE(s.crend() == crend(s)); - } - - TEST(span_test, ssize_free_function) - { - int a[] = {1, 2, 3, 4}; - span s{a}; - - EXPECT_FALSE((std::is_same::value)); - EXPECT_TRUE(s.size() == static_cast(ssize(s))); - } - TEST(span_test, iterator_comparisons) { int a[] = {1, 2, 3, 4}; @@ -1326,126 +1174,6 @@ TEST(span_test, from_array_constructor) } } - TEST(span_test, comparison_operators) - { - { - span s1; - span s2; - EXPECT_TRUE(s1 == s2); - EXPECT_FALSE(s1 != s2); - EXPECT_FALSE(s1 < s2); - EXPECT_TRUE(s1 <= s2); - EXPECT_FALSE(s1 > s2); - EXPECT_TRUE(s1 >= s2); - EXPECT_TRUE(s2 == s1); - EXPECT_FALSE(s2 != s1); - EXPECT_FALSE(s2 != s1); - EXPECT_TRUE(s2 <= s1); - EXPECT_FALSE(s2 > s1); - EXPECT_TRUE(s2 >= s1); - } - - { - int arr[] = {2, 1}; - span s1 = arr; - span s2 = arr; - - EXPECT_TRUE(s1 == s2); - EXPECT_FALSE(s1 != s2); - EXPECT_FALSE(s1 < s2); - EXPECT_TRUE(s1 <= s2); - EXPECT_FALSE(s1 > s2); - EXPECT_TRUE(s1 >= s2); - EXPECT_TRUE(s2 == s1); - EXPECT_FALSE(s2 != s1); - EXPECT_FALSE(s2 < s1); - EXPECT_TRUE(s2 <= s1); - EXPECT_FALSE(s2 > s1); - EXPECT_TRUE(s2 >= s1); - } - - { - int arr[] = {2, 1}; // bigger - - span s1; - span s2 = arr; - - EXPECT_TRUE(s1 != s2); - EXPECT_TRUE(s2 != s1); - EXPECT_FALSE(s1 == s2); - EXPECT_FALSE(s2 == s1); - EXPECT_TRUE(s1 < s2); - EXPECT_FALSE(s2 < s1); - EXPECT_TRUE(s1 <= s2); - EXPECT_FALSE(s2 <= s1); - EXPECT_TRUE(s2 > s1); - EXPECT_FALSE(s1 > s2); - EXPECT_TRUE(s2 >= s1); - EXPECT_FALSE(s1 >= s2); - } - - { - int arr1[] = {1, 2}; - int arr2[] = {1, 2}; - span s1 = arr1; - span s2 = arr2; - - EXPECT_TRUE(s1 == s2); - EXPECT_FALSE(s1 != s2); - EXPECT_FALSE(s1 < s2); - EXPECT_TRUE(s1 <= s2); - EXPECT_FALSE(s1 > s2); - EXPECT_TRUE(s1 >= s2); - EXPECT_TRUE(s2 == s1); - EXPECT_FALSE(s2 != s1); - EXPECT_FALSE(s2 < s1); - EXPECT_TRUE(s2 <= s1); - EXPECT_FALSE(s2 > s1); - EXPECT_TRUE(s2 >= s1); - } - - { - int arr[] = {1, 2, 3}; - - span s1 = {&arr[0], 2}; // shorter - span s2 = arr; // longer - - EXPECT_TRUE(s1 != s2); - EXPECT_TRUE(s2 != s1); - EXPECT_FALSE(s1 == s2); - EXPECT_FALSE(s2 == s1); - EXPECT_TRUE(s1 < s2); - EXPECT_FALSE(s2 < s1); - EXPECT_TRUE(s1 <= s2); - EXPECT_FALSE(s2 <= s1); - EXPECT_TRUE(s2 > s1); - EXPECT_FALSE(s1 > s2); - EXPECT_TRUE(s2 >= s1); - EXPECT_FALSE(s1 >= s2); - } - - { - int arr1[] = {1, 2}; // smaller - int arr2[] = {2, 1}; // bigger - - span s1 = arr1; - span s2 = arr2; - - EXPECT_TRUE(s1 != s2); - EXPECT_TRUE(s2 != s1); - EXPECT_FALSE(s1 == s2); - EXPECT_FALSE(s2 == s1); - EXPECT_TRUE(s1 < s2); - EXPECT_FALSE(s2 < s1); - EXPECT_TRUE(s1 <= s2); - EXPECT_FALSE(s2 <= s1); - EXPECT_TRUE(s2 > s1); - EXPECT_FALSE(s1 > s2); - EXPECT_TRUE(s2 >= s1); - EXPECT_FALSE(s1 >= s2); - } - } - TEST(span_test, as_bytes) { std::set_terminate([] { @@ -1643,14 +1371,6 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(match[0].second == (f_it + 1)); } - TEST(span_test, interop_with_gsl_at) - { - int arr[5] = {1, 2, 3, 4, 5}; - span s{arr}; - EXPECT_TRUE(at(s, 0) == 1); - EXPECT_TRUE(at(s, 1) == 2); - } - TEST(span_test, default_constructible) { EXPECT_TRUE((std::is_default_constructible>::value)); From c853017be39d0dccd1e041c2f9e1b98df5d66da4 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 19 Feb 2020 14:44:22 -0800 Subject: [PATCH 68/81] forgot nl @ eof in span_ext_tests.cpp --- tests/span_ext_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/span_ext_tests.cpp b/tests/span_ext_tests.cpp index 7b751e7..bd256a8 100644 --- a/tests/span_ext_tests.cpp +++ b/tests/span_ext_tests.cpp @@ -357,4 +357,4 @@ TEST(span_ext_test, make_span_from_array_constructor) EXPECT_TRUE(s2 >= s1); EXPECT_FALSE(s1 >= s2); } - } \ No newline at end of file + } From 31440829097397a857076fc7785a4ceffc076bac Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 24 Feb 2020 11:16:26 -0800 Subject: [PATCH 69/81] forward declare span and remove header --- include/gsl/span | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 23c58c9..e8ca691 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -21,7 +21,6 @@ #include // for byte #include // for narrow_cast, narrow -#include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... #include // for enable_if_t, declval, is_convertible, inte... @@ -63,6 +62,15 @@ #pragma GCC diagnostic ignored "-Wsign-conversion" #endif +namespace std +{ +// forward declaring std::array. +// array is only used for a few constructors, so pulling the entire header is unnecessary for span. +// The end user's logic will pull in the actual definition of array if they need it. +template +class array; +} + namespace gsl { From ac370042740e2353fa8d6d1d26cbb16ee745cabb Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 24 Feb 2020 11:45:33 -0800 Subject: [PATCH 70/81] clang defines struct as array where msvc and g++ define it as class. --- include/gsl/span | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/gsl/span b/include/gsl/span index e8ca691..b668e71 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -68,7 +68,11 @@ namespace std // array is only used for a few constructors, so pulling the entire header is unnecessary for span. // The end user's logic will pull in the actual definition of array if they need it. template +#if defined(_MSC_VER) || (defined(__GNUC__) && !defined(__clang__)) class array; +#else +struct array; +#endif // defined(_MSC_VER) || (defined(__GNUC__) && !defined(__clang__)) } namespace gsl From 89271b89c10cf2e3d8987d66dc2814b0d5e6c762 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 24 Feb 2020 13:06:01 -0800 Subject: [PATCH 71/81] fix apple clang forward declaration --- include/gsl/span | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index b668e71..f11ea6a 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -68,11 +68,11 @@ namespace std // array is only used for a few constructors, so pulling the entire header is unnecessary for span. // The end user's logic will pull in the actual definition of array if they need it. template -#if defined(_MSC_VER) || (defined(__GNUC__) && !defined(__clang__)) -class array; -#else +#if defined(__clang__) || defined(__APPLE__) struct array; -#endif // defined(_MSC_VER) || (defined(__GNUC__) && !defined(__clang__)) +#else +class array; +#endif // defined(__clang__) || defined(__APPLE__) } namespace gsl From 60372b6468ebf6b7aec6646ce0e6affe8c932bc4 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 24 Feb 2020 13:43:42 -0800 Subject: [PATCH 72/81] apple-clang failed again, forcing class instead of struct --- include/gsl/span | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index f11ea6a..bcb55d4 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -68,11 +68,11 @@ namespace std // array is only used for a few constructors, so pulling the entire header is unnecessary for span. // The end user's logic will pull in the actual definition of array if they need it. template -#if defined(__clang__) || defined(__APPLE__) +#if defined(__clang__) && !defined(__APPLE__) struct array; #else class array; -#endif // defined(__clang__) || defined(__APPLE__) +#endif // defined(__clang__) && !defined(__APPLE__) } namespace gsl From 0f60c68ab9366a64063d7bf3f3b8c3eedf07bcb7 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 24 Feb 2020 14:41:29 -0800 Subject: [PATCH 73/81] disgusting test to get apple clang to work, dont look at it --- include/gsl/span | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index bcb55d4..7484f38 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -68,11 +68,15 @@ namespace std // array is only used for a few constructors, so pulling the entire header is unnecessary for span. // The end user's logic will pull in the actual definition of array if they need it. template -#if defined(__clang__) && !defined(__APPLE__) -struct array; +#if defined(__clang__) +struct \ +#if defined(__APPLE__) +_LIBCPP_TYPE_VIS_ONLY \ +#endif +array; #else class array; -#endif // defined(__clang__) && !defined(__APPLE__) +#endif // defined(__clang__) } namespace gsl From 32e5fea6ac56a6a9a458d20d1fedf8170bc6b61b Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 24 Feb 2020 14:47:45 -0800 Subject: [PATCH 74/81] test --- include/gsl/span | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 7484f38..fc1677e 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -69,11 +69,14 @@ namespace std // The end user's logic will pull in the actual definition of array if they need it. template #if defined(__clang__) -struct \ + #if defined(__APPLE__) -_LIBCPP_TYPE_VIS_ONLY \ +#define VIS_MOD _LIBCPP_TYPE_VIS_ONLY +#else +#define VIS_MOD #endif -array; + +struct VIS_MOD array; #else class array; #endif // defined(__clang__) From 5d54cada8ee44bde05c5db7357db3e3f5659d83a Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 24 Feb 2020 15:49:30 -0800 Subject: [PATCH 75/81] just pulling in array header if we detect apple clang --- include/gsl/span | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index fc1677e..c13a7c8 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -25,6 +25,24 @@ #include // for reverse_iterator, distance, random_access_... #include // for enable_if_t, declval, is_convertible, inte... +// forward declaring std::array. +// pulling the entire array header is unnecessary for span because array is only used for a few constructors. +// The end user's logic will pull in the actual definition of array if they need it. +// To do: find a way to forward declare array for Apple Clang +#if defined(__APPLE__) +#include +#else +namespace std +{ +template +#if defined(__clang__) +struct array; +#else +class array; +#endif // defined(__clang__) +} +#endif // defined(__APPLE__) + #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) @@ -62,26 +80,6 @@ #pragma GCC diagnostic ignored "-Wsign-conversion" #endif -namespace std -{ -// forward declaring std::array. -// array is only used for a few constructors, so pulling the entire header is unnecessary for span. -// The end user's logic will pull in the actual definition of array if they need it. -template -#if defined(__clang__) - -#if defined(__APPLE__) -#define VIS_MOD _LIBCPP_TYPE_VIS_ONLY -#else -#define VIS_MOD -#endif - -struct VIS_MOD array; -#else -class array; -#endif // defined(__clang__) -} - namespace gsl { From fc54e0d89a0fff924fc60e0c61bd8d3a83353a9a Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Mon, 24 Feb 2020 15:49:30 -0800 Subject: [PATCH 76/81] just pulling in array header if we detect apple clang --- include/gsl/span | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index fc1677e..c13a7c8 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -25,6 +25,24 @@ #include // for reverse_iterator, distance, random_access_... #include // for enable_if_t, declval, is_convertible, inte... +// forward declaring std::array. +// pulling the entire array header is unnecessary for span because array is only used for a few constructors. +// The end user's logic will pull in the actual definition of array if they need it. +// To do: find a way to forward declare array for Apple Clang +#if defined(__APPLE__) +#include +#else +namespace std +{ +template +#if defined(__clang__) +struct array; +#else +class array; +#endif // defined(__clang__) +} +#endif // defined(__APPLE__) + #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) @@ -62,26 +80,6 @@ #pragma GCC diagnostic ignored "-Wsign-conversion" #endif -namespace std -{ -// forward declaring std::array. -// array is only used for a few constructors, so pulling the entire header is unnecessary for span. -// The end user's logic will pull in the actual definition of array if they need it. -template -#if defined(__clang__) - -#if defined(__APPLE__) -#define VIS_MOD _LIBCPP_TYPE_VIS_ONLY -#else -#define VIS_MOD -#endif - -struct VIS_MOD array; -#else -class array; -#endif // defined(__clang__) -} - namespace gsl { From 4a6a7a095ddd748064b6036d9bb9e73a0bdc5e40 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 25 Feb 2020 14:09:29 -0800 Subject: [PATCH 77/81] add back array header, will remove in separate pr --- include/gsl/span | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index c13a7c8..23c58c9 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -21,28 +21,11 @@ #include // for byte #include // for narrow_cast, narrow +#include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... #include // for enable_if_t, declval, is_convertible, inte... -// forward declaring std::array. -// pulling the entire array header is unnecessary for span because array is only used for a few constructors. -// The end user's logic will pull in the actual definition of array if they need it. -// To do: find a way to forward declare array for Apple Clang -#if defined(__APPLE__) -#include -#else -namespace std -{ -template -#if defined(__clang__) -struct array; -#else -class array; -#endif // defined(__clang__) -} -#endif // defined(__APPLE__) - #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) From 769f01900dbf58ffa96b987e37cd169e371d005b Mon Sep 17 00:00:00 2001 From: Jordan Maples Date: Tue, 3 Mar 2020 17:04:46 -0800 Subject: [PATCH 78/81] moving exception include --- include/gsl/gsl_assert | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index 7a9e8ad..ac87ef4 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -17,8 +17,6 @@ #ifndef GSL_CONTRACTS_H #define GSL_CONTRACTS_H -#include - // // make suppress attributes parse for some compilers // Hopefully temporary until suppression standardization occurs @@ -47,6 +45,10 @@ #pragma clang diagnostic ignored "-Winvalid-noreturn" #endif +#else + +#include + #endif #define GSL_STRINGIFY_DETAIL(x) #x @@ -110,14 +112,6 @@ namespace details #endif } - template - [[deprecated("GSL no longer supports throwing for contract violations. Use gsl::details::terminate() instead.")]] - [[noreturn]] void throw_exception(Exception&&) noexcept - { - gsl::details::terminate(); - } - - } // namespace details } // namespace gsl From b30524088a8d3454b95c2a94f300caf26ba92fe2 Mon Sep 17 00:00:00 2001 From: Jordan Maples Date: Fri, 6 Mar 2020 11:17:58 -0800 Subject: [PATCH 79/81] added some comments and ran clang-format --- include/gsl/gsl_assert | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index ac87ef4..e8f3f66 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -36,6 +36,7 @@ // Currently terminate is a no-op in this mode, so we add termination behavior back // #if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS + #define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND #include #define RANGE_CHECKS_FAILURE 0 @@ -43,13 +44,13 @@ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winvalid-noreturn" -#endif +#endif // defined(__clang__) #else #include -#endif +#endif // !defined(_MSC_VER) || !defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS #define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) @@ -57,10 +58,12 @@ #if defined(__clang__) || defined(__GNUC__) #define GSL_LIKELY(x) __builtin_expect(!!(x), 1) #define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0) + #else + #define GSL_LIKELY(x) (!!(x)) #define GSL_UNLIKELY(x) (!!(x)) -#endif +#endif // defined(__clang__) || defined(__GNUC__) // // GSL_ASSUME(cond) @@ -87,9 +90,11 @@ namespace details { #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) - typedef void (__cdecl *terminate_handler)(); + typedef void(__cdecl* terminate_handler)(); + // clang-format off GSL_SUPPRESS(f.6) // NO-FORMAT: attribute + // clang-format on [[noreturn]] inline void __cdecl default_terminate_handler() { __fastfail(RANGE_CHECKS_FAILURE); @@ -101,7 +106,7 @@ namespace details return handler; } -#endif +#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) [[noreturn]] inline void terminate() noexcept { @@ -109,13 +114,12 @@ namespace details (*gsl::details::get_terminate_handler())(); #else std::terminate(); -#endif +#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) } } // namespace details } // namespace gsl - #define GSL_CONTRACT_CHECK(type, cond) \ (GSL_LIKELY(cond) ? static_cast(0) : gsl::details::terminate()) From ce4d689f4f5af11ce97e1c2f05c26b91de164493 Mon Sep 17 00:00:00 2001 From: Jordan Maples Date: Fri, 6 Mar 2020 11:22:09 -0800 Subject: [PATCH 80/81] shuffle around code to bring includes to top. --- include/gsl/gsl_assert | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index e8f3f66..7efa84e 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -17,20 +17,6 @@ #ifndef GSL_CONTRACTS_H #define GSL_CONTRACTS_H -// -// make suppress attributes parse for some compilers -// Hopefully temporary until suppression standardization occurs -// -#if defined(__clang__) -#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] -#else -#if defined(_MSC_VER) -#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] -#else -#define GSL_SUPPRESS(x) -#endif // _MSC_VER -#endif // __clang__ - // // Temporary until MSVC STL supports no-exceptions mode. // Currently terminate is a no-op in this mode, so we add termination behavior back @@ -45,13 +31,24 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winvalid-noreturn" #endif // defined(__clang__) - #else - #include - #endif // !defined(_MSC_VER) || !defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS +// +// make suppress attributes parse for some compilers +// Hopefully temporary until suppression standardization occurs +// +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#if defined(_MSC_VER) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#define GSL_SUPPRESS(x) +#endif // _MSC_VER +#endif // __clang__ + #define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) From 06adf557e925ba4010b0964cb216efb9f2370ed6 Mon Sep 17 00:00:00 2001 From: Jordan Maples Date: Thu, 12 Mar 2020 12:32:32 -0700 Subject: [PATCH 81/81] update kernel mode detection macro --- include/gsl/gsl_assert | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index 7efa84e..96eaada 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -21,7 +21,7 @@ // Temporary until MSVC STL supports no-exceptions mode. // Currently terminate is a no-op in this mode, so we add termination behavior back // -#if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS +#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) #define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND #include @@ -31,9 +31,12 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winvalid-noreturn" #endif // defined(__clang__) -#else + +#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) + #include -#endif // !defined(_MSC_VER) || !defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS + +#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) // // make suppress attributes parse for some compilers