Skip to content

Commit

Permalink
Make gsl::span's iterators use the contiguous_iterator concept (#1035)
Browse files Browse the repository at this point in the history
Resolves #1016

Co-authored-by: Casey Carter <Casey@Carter.net>
  • Loading branch information
dmitrykobets-msft and CaseyCarter committed Mar 22, 2022
1 parent f22f524 commit 3837236
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
24 changes: 24 additions & 0 deletions include/gsl/span
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@
#include <array> // for array
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
#include <iterator> // for reverse_iterator, distance, random_access_...
#include <memory> // for pointer_traits
#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__)
#pragma warning(push)

Expand Down Expand Up @@ -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<Type>;
using difference_type = std::ptrdiff_t;
Expand Down Expand Up @@ -329,8 +337,24 @@ namespace details
pointer begin_ = nullptr;
pointer end_ = 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>
class extent_type
{
Expand Down
20 changes: 20 additions & 0 deletions tests/span_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
#endif // __has_include(<string_view>)
#endif // __has_include
#endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
#if defined(__cplusplus) && __cplusplus >= 202002L
#include <span>
#endif // __cplusplus >= 202002L

#include "deathTestCommon.h"

Expand Down Expand Up @@ -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<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

0 comments on commit 3837236

Please sign in to comment.