diff --git a/include/gsl/span b/include/gsl/span index 5488f52..4413a4d 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -25,8 +25,13 @@ #include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... +#include // for pointer_traits #include // for enable_if_t, declval, is_convertible, inte... +#if defined(__has_include) && __has_include() +#include +#endif + #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) @@ -110,6 +115,9 @@ namespace details class span_iterator { public: +#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts)) + using iterator_concept = std::contiguous_iterator_tag; +#endif // __cpp_lib_ranges using iterator_category = std::random_access_iterator_tag; using value_type = std::remove_cv_t; using difference_type = std::ptrdiff_t; @@ -329,8 +337,24 @@ namespace details pointer begin_ = nullptr; pointer end_ = nullptr; pointer current_ = nullptr; - }; + template + friend struct std::pointer_traits; + }; +}} // namespace gsl::details + +template +struct std::pointer_traits<::gsl::details::span_iterator> { + using pointer = ::gsl::details::span_iterator; + using element_type = Type; + using difference_type = ptrdiff_t; + + static constexpr element_type* to_address(const pointer i) noexcept { + return i.current_; + } +}; + +namespace gsl { namespace details { template class extent_type { diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 33ccf56..41ac3ae 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -40,6 +40,9 @@ #endif // __has_include() #endif // __has_include #endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) +#if defined(__cplusplus) && __cplusplus >= 202002L +#include +#endif // __cplusplus >= 202002L #include "deathTestCommon.h" @@ -1297,3 +1300,20 @@ TEST(span_test, front_back) EXPECT_DEATH(s2.front(), expected); EXPECT_DEATH(s2.back(), expected); } + +#if defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L +TEST(span_test, std_span) +{ + // make sure std::span can be constructed from gsl::span + int arr[5] = {1, 2, 3, 4, 5}; + gsl::span gsl_span{arr}; +#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts)) + EXPECT_TRUE(std::to_address(gsl_span.begin()) == gsl_span.data()); + EXPECT_TRUE(std::to_address(gsl_span.end()) == gsl_span.data() + gsl_span.size()); +#endif // __cpp_lib_ranges + + std::span std_span = gsl_span; + EXPECT_TRUE(std_span.data() == gsl_span.data()); + EXPECT_TRUE(std_span.size() == gsl_span.size()); +} +#endif // defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L