Skip to content

Commit 3837236

Browse files
Make gsl::span's iterators use the contiguous_iterator concept (#1035)
Resolves #1016 Co-authored-by: Casey Carter <Casey@Carter.net>
1 parent f22f524 commit 3837236

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

include/gsl/span

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,13 @@
2525
#include <array> // for array
2626
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
2727
#include <iterator> // for reverse_iterator, distance, random_access_...
28+
#include <memory> // for pointer_traits
2829
#include <type_traits> // for enable_if_t, declval, is_convertible, inte...
2930

31+
#if defined(__has_include) && __has_include(<version>)
32+
#include <version>
33+
#endif
34+
3035
#if defined(_MSC_VER) && !defined(__clang__)
3136
#pragma warning(push)
3237

@@ -110,6 +115,9 @@ namespace details
110115
class span_iterator
111116
{
112117
public:
118+
#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts))
119+
using iterator_concept = std::contiguous_iterator_tag;
120+
#endif // __cpp_lib_ranges
113121
using iterator_category = std::random_access_iterator_tag;
114122
using value_type = std::remove_cv_t<Type>;
115123
using difference_type = std::ptrdiff_t;
@@ -329,8 +337,24 @@ namespace details
329337
pointer begin_ = nullptr;
330338
pointer end_ = nullptr;
331339
pointer current_ = nullptr;
340+
341+
template <typename Ptr>
342+
friend struct std::pointer_traits;
332343
};
344+
}} // namespace gsl::details
345+
346+
template <class Type>
347+
struct std::pointer_traits<::gsl::details::span_iterator<Type>> {
348+
using pointer = ::gsl::details::span_iterator<Type>;
349+
using element_type = Type;
350+
using difference_type = ptrdiff_t;
351+
352+
static constexpr element_type* to_address(const pointer i) noexcept {
353+
return i.current_;
354+
}
355+
};
333356

357+
namespace gsl { namespace details {
334358
template <std::size_t Ext>
335359
class extent_type
336360
{

tests/span_tests.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
#endif // __has_include(<string_view>)
4141
#endif // __has_include
4242
#endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
43+
#if defined(__cplusplus) && __cplusplus >= 202002L
44+
#include <span>
45+
#endif // __cplusplus >= 202002L
4346

4447
#include "deathTestCommon.h"
4548

@@ -1297,3 +1300,20 @@ TEST(span_test, front_back)
12971300
EXPECT_DEATH(s2.front(), expected);
12981301
EXPECT_DEATH(s2.back(), expected);
12991302
}
1303+
1304+
#if defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
1305+
TEST(span_test, std_span)
1306+
{
1307+
// make sure std::span can be constructed from gsl::span
1308+
int arr[5] = {1, 2, 3, 4, 5};
1309+
gsl::span<int> gsl_span{arr};
1310+
#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts))
1311+
EXPECT_TRUE(std::to_address(gsl_span.begin()) == gsl_span.data());
1312+
EXPECT_TRUE(std::to_address(gsl_span.end()) == gsl_span.data() + gsl_span.size());
1313+
#endif // __cpp_lib_ranges
1314+
1315+
std::span<int> std_span = gsl_span;
1316+
EXPECT_TRUE(std_span.data() == gsl_span.data());
1317+
EXPECT_TRUE(std_span.size() == gsl_span.size());
1318+
}
1319+
#endif // defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L

0 commit comments

Comments
 (0)