Make gsl::span's iterators use the contiguous_iterator concept (#1035)

Resolves #1016

Co-authored-by: Casey Carter <Casey@Carter.net>
This commit is contained in:
dmitrykobets-msft 2022-03-22 13:20:54 -07:00 committed by GitHub
parent f22f524aa2
commit 383723676c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 1 deletions

View File

@ -25,8 +25,13 @@
#include <array> // for array #include <array> // for array
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t #include <cstddef> // for ptrdiff_t, size_t, nullptr_t
#include <iterator> // for reverse_iterator, distance, random_access_... #include <iterator> // for reverse_iterator, distance, random_access_...
#include <memory> // for pointer_traits
#include <type_traits> // for enable_if_t, declval, is_convertible, inte... #include <type_traits> // for enable_if_t, declval, is_convertible, inte...
#if defined(__has_include) && __has_include(<version>)
#include <version>
#endif
#if defined(_MSC_VER) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push) #pragma warning(push)
@ -110,6 +115,9 @@ namespace details
class span_iterator class span_iterator
{ {
public: 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 iterator_category = std::random_access_iterator_tag;
using value_type = std::remove_cv_t<Type>; using value_type = std::remove_cv_t<Type>;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
@ -329,8 +337,24 @@ namespace details
pointer begin_ = nullptr; pointer begin_ = nullptr;
pointer end_ = nullptr; pointer end_ = nullptr;
pointer current_ = nullptr; pointer current_ = nullptr;
};
template <typename Ptr>
friend struct std::pointer_traits;
};
}} // namespace gsl::details
template <class Type>
struct std::pointer_traits<::gsl::details::span_iterator<Type>> {
using pointer = ::gsl::details::span_iterator<Type>;
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 <std::size_t Ext> template <std::size_t Ext>
class extent_type class extent_type
{ {

View File

@ -40,6 +40,9 @@
#endif // __has_include(<string_view>) #endif // __has_include(<string_view>)
#endif // __has_include #endif // __has_include
#endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) #endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
#if defined(__cplusplus) && __cplusplus >= 202002L
#include <span>
#endif // __cplusplus >= 202002L
#include "deathTestCommon.h" #include "deathTestCommon.h"
@ -1297,3 +1300,20 @@ TEST(span_test, front_back)
EXPECT_DEATH(s2.front(), expected); EXPECT_DEATH(s2.front(), expected);
EXPECT_DEATH(s2.back(), 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<int> 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<int> 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