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 01/11] 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 02/11] 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 03/11] 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 04/11] 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 05/11] 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 06/11] 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 07/11] 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 08/11] 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 09/11] 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 10/11] 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 11/11] 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)