Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

span: Implement resolution to LWG-3320 #548

Merged
merged 2 commits into from
Feb 29, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 11 additions & 54 deletions stl/inc/span
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,6 @@ struct _Span_iterator {
using pointer = _Ty*;
using reference = _Ty&;

_NODISCARD constexpr operator _Span_iterator<const _Ty>() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_Myptr, _Mybegin, _Myend};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_Myptr};
#endif // _ITERATOR_DEBUG_LEVEL
}

_NODISCARD constexpr reference operator*() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(_Mybegin, "cannot dereference value-initialized span iterator");
Expand Down Expand Up @@ -141,21 +133,13 @@ struct _Span_iterator {
return _Tmp;
}

// clang-format off
#ifdef __cpp_lib_concepts
template <class _Ty2>
requires same_as<remove_cv_t<_Ty2>, value_type>
#else // ^^^ use concepts / no concepts vvv
template <class _Ty2, enable_if_t<is_same_v<remove_cv_t<_Ty2>, value_type>, int> = 0>
#endif // __cpp_lib_concepts
_NODISCARD constexpr difference_type operator-(const _Span_iterator<_Ty2>& _Right) const noexcept {
_NODISCARD constexpr difference_type operator-(const _Span_iterator& _Right) const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(
_Mybegin == _Right._Mybegin && _Myend == _Right._Myend, "cannot subtract incompatible span iterators");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
return _Myptr - _Right._Myptr;
}
// clang-format on

_NODISCARD constexpr reference operator[](const difference_type _Off) const noexcept {
return *(*this + _Off);
Expand Down Expand Up @@ -359,18 +343,16 @@ struct _Is_span_compatible_range : bool_constant<conjunction_v<
template <class _Ty, size_t _Extent = dynamic_extent>
class span : public _Span_extent_type<_Extent> {
public:
using element_type = _Ty;
using value_type = remove_cv_t<_Ty>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Ty*;
using const_pointer = const _Ty*;
using reference = _Ty&;
using const_reference = const _Ty&;
using iterator = _Span_iterator<_Ty>;
using const_iterator = _Span_iterator<const _Ty>;
using reverse_iterator = _STD reverse_iterator<iterator>;
using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
using element_type = _Ty;
using value_type = remove_cv_t<_Ty>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Ty*;
using const_pointer = const _Ty*;
using reference = _Ty&;
using const_reference = const _Ty&;
using iterator = _Span_iterator<_Ty>;
using reverse_iterator = _STD reverse_iterator<iterator>;

static constexpr size_type extent = _Extent;

Expand Down Expand Up @@ -612,23 +594,6 @@ public:
#endif // _ITERATOR_DEBUG_LEVEL
}

_NODISCARD constexpr const_iterator cbegin() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_Mydata, _Mydata, _Mydata + this->size()};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_Mydata};
#endif // _ITERATOR_DEBUG_LEVEL
}

_NODISCARD constexpr const_iterator cend() const noexcept {
const auto _End = _Mydata + this->size();
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_End, _Mydata, _End};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_End};
#endif // _ITERATOR_DEBUG_LEVEL
}

_NODISCARD constexpr reverse_iterator rbegin() const noexcept {
return reverse_iterator{end()};
}
Expand All @@ -637,14 +602,6 @@ public:
return reverse_iterator{begin()};
}

_NODISCARD constexpr const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator{cend()};
}

_NODISCARD constexpr const_reverse_iterator crend() const noexcept {
return const_reverse_iterator{cbegin()};
}

_NODISCARD constexpr pointer _Unchecked_begin() const noexcept {
return _Mydata;
}
Expand Down
6 changes: 6 additions & 0 deletions tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,12 @@ language.support\support.limits\support.limits.general\string.version.pass.cpp
# Test bug. See LWG-3099 "is_assignable<Incomplete&, Incomplete&>"
utilities\utility\pairs\pairs.pair\assign_pair.pass.cpp

# Test bug after LWG-3320 "span::cbegin/cend methods produce different results than std::[ranges::]cbegin/cend" was accepted.
containers\views\span.iterators\cbegin.pass.cpp
containers\views\span.iterators\cend.pass.cpp
containers\views\span.iterators\crbegin.pass.cpp
containers\views\span.iterators\crend.pass.cpp

StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
# Not yet analyzed, likely bogus tests. Appears to be timing assumptions.
thread\futures\futures.async\async.pass.cpp
thread\futures\futures.shared_future\wait_for.pass.cpp
Expand Down
16 changes: 0 additions & 16 deletions tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ STATIC_ASSERT(stl_checked == _Range_verifiable_v<std::filesystem::path::const_it

#if _HAS_CXX20
STATIC_ASSERT(stl_checked == _Range_verifiable_v<span<int>::iterator>);
STATIC_ASSERT(stl_checked == _Range_verifiable_v<span<int>::const_iterator>);
STATIC_ASSERT(stl_checked == _Range_verifiable_v<span<int>::reverse_iterator>);
STATIC_ASSERT(stl_checked == _Range_verifiable_v<span<int>::const_reverse_iterator>);
#endif // _HAS_CXX20

STATIC_ASSERT(_Range_verifiable_v<stdext::checked_array_iterator<int*>>);
Expand Down Expand Up @@ -185,9 +183,7 @@ STATIC_ASSERT(!_Range_verifiable_v<::DerivedFrom<std::filesystem::path::const_it

#if _HAS_CXX20
STATIC_ASSERT(!_Range_verifiable_v<::DerivedFrom<span<int>::iterator>>);
STATIC_ASSERT(!_Range_verifiable_v<::DerivedFrom<span<int>::const_iterator>>);
STATIC_ASSERT(!_Range_verifiable_v<::DerivedFrom<span<int>::reverse_iterator>>);
STATIC_ASSERT(!_Range_verifiable_v<::DerivedFrom<span<int>::const_reverse_iterator>>);
#endif // _HAS_CXX20

STATIC_ASSERT(!_Range_verifiable_v<::DerivedFrom<stdext::checked_array_iterator<int*>>>);
Expand Down Expand Up @@ -403,9 +399,7 @@ STATIC_ASSERT(test_unwrappable_for_unverified<std::filesystem::path::const_itera

#if _HAS_CXX20
STATIC_ASSERT(test_unwrappable_for_unverified<span<int>::iterator, !stl_checked>());
STATIC_ASSERT(test_unwrappable_for_unverified<span<int>::const_iterator, !stl_checked>());
STATIC_ASSERT(test_unwrappable_for_unverified<span<int>::reverse_iterator, !stl_checked>());
STATIC_ASSERT(test_unwrappable_for_unverified<span<int>::const_reverse_iterator, !stl_checked>());
#endif // _HAS_CXX20

STATIC_ASSERT(test_unwrappable_for_unverified<stdext::checked_array_iterator<int*>, false>());
Expand Down Expand Up @@ -481,9 +475,7 @@ STATIC_ASSERT(test_unwrappable<std::filesystem::path::const_iterator, true>());

#if _HAS_CXX20
STATIC_ASSERT(test_unwrappable<span<int>::iterator, true>());
STATIC_ASSERT(test_unwrappable<span<int>::const_iterator, true>());
STATIC_ASSERT(test_unwrappable<span<int>::reverse_iterator, true>());
STATIC_ASSERT(test_unwrappable<span<int>::const_reverse_iterator, true>());
#endif // _HAS_CXX20

STATIC_ASSERT(test_unwrappable<stdext::checked_array_iterator<int*>, true>());
Expand Down Expand Up @@ -559,9 +551,7 @@ STATIC_ASSERT(test_unwrappable_for_offset<std::filesystem::path::const_iterator,

#if _HAS_CXX20
STATIC_ASSERT(test_unwrappable_for_offset<span<int>::iterator, true>());
STATIC_ASSERT(test_unwrappable_for_offset<span<int>::const_iterator, true>());
STATIC_ASSERT(test_unwrappable_for_offset<span<int>::reverse_iterator, true>());
STATIC_ASSERT(test_unwrappable_for_offset<span<int>::const_reverse_iterator, true>());
#endif // _HAS_CXX20

STATIC_ASSERT(test_unwrappable_for_offset<stdext::checked_array_iterator<int*>, true>());
Expand Down Expand Up @@ -636,9 +626,7 @@ STATIC_ASSERT(test_unwrappable_for_unverified<::DerivedFrom<std::filesystem::pat

#if _HAS_CXX20
STATIC_ASSERT(test_unwrappable_for_unverified<::DerivedFrom<span<int>::iterator>, false>());
STATIC_ASSERT(test_unwrappable_for_unverified<::DerivedFrom<span<int>::const_iterator>, false>());
STATIC_ASSERT(test_unwrappable_for_unverified<::DerivedFrom<span<int>::reverse_iterator>, false>());
STATIC_ASSERT(test_unwrappable_for_unverified<::DerivedFrom<span<int>::const_reverse_iterator>, false>());
#endif // _HAS_CXX20

STATIC_ASSERT(test_unwrappable_for_unverified<::DerivedFrom<stdext::checked_array_iterator<int*>>, false>());
Expand Down Expand Up @@ -713,9 +701,7 @@ STATIC_ASSERT(test_unwrappable<::DerivedFrom<std::filesystem::path::const_iterat

#if _HAS_CXX20
STATIC_ASSERT(test_unwrappable<::DerivedFrom<span<int>::iterator>, false>());
STATIC_ASSERT(test_unwrappable<::DerivedFrom<span<int>::const_iterator>, false>());
STATIC_ASSERT(test_unwrappable<::DerivedFrom<span<int>::reverse_iterator>, false>());
STATIC_ASSERT(test_unwrappable<::DerivedFrom<span<int>::const_reverse_iterator>, false>());
#endif // _HAS_CXX20

STATIC_ASSERT(test_unwrappable<::DerivedFrom<stdext::checked_array_iterator<int*>>, false>());
Expand Down Expand Up @@ -790,9 +776,7 @@ STATIC_ASSERT(test_unwrappable_for_offset<::DerivedFrom<std::filesystem::path::c

#if _HAS_CXX20
STATIC_ASSERT(test_unwrappable_for_offset<::DerivedFrom<span<int>::iterator>, false>());
STATIC_ASSERT(test_unwrappable_for_offset<::DerivedFrom<span<int>::const_iterator>, false>());
STATIC_ASSERT(test_unwrappable_for_offset<::DerivedFrom<span<int>::reverse_iterator>, false>());
STATIC_ASSERT(test_unwrappable_for_offset<::DerivedFrom<span<int>::const_reverse_iterator>, false>());
#endif // _HAS_CXX20

STATIC_ASSERT(test_unwrappable_for_offset<::DerivedFrom<stdext::checked_array_iterator<int*>>, false>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ int main() {

#if _HAS_CXX20
test_iterator<span<int>::iterator>();
test_iterator<span<int>::const_iterator>();
#endif // _HAS_CXX20

test_iterator<sregex_iterator>();
Expand Down
66 changes: 1 addition & 65 deletions tests/std/tests/P0122R7_span/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,52 +61,20 @@ static_assert(is_same_v<span<const int, 3>::const_pointer, const int*>);
static_assert(is_same_v<span<const int, 3>::reference, const int&>);
static_assert(is_same_v<span<const int, 3>::const_reference, const int&>);

// The iterators are thoroughly tested by P0896R4_ranges_range_machinery...
// The iterators are thoroughly tested by P0896R4_ranges_range_machinery
static_assert(is_same_v<iterator_traits<span<int>::iterator>::pointer, int*>);
static_assert(is_same_v<iterator_traits<span<int>::const_iterator>::pointer, const int*>);
static_assert(is_same_v<span<int>::reverse_iterator, reverse_iterator<span<int>::iterator>>);
static_assert(is_same_v<span<int>::const_reverse_iterator, reverse_iterator<span<int>::const_iterator>>);

static_assert(is_same_v<iterator_traits<span<int, 3>::iterator>::pointer, int*>);
static_assert(is_same_v<iterator_traits<span<int, 3>::const_iterator>::pointer, const int*>);
static_assert(is_same_v<span<int, 3>::reverse_iterator, reverse_iterator<span<int, 3>::iterator>>);
static_assert(is_same_v<span<int, 3>::const_reverse_iterator, reverse_iterator<span<int, 3>::const_iterator>>);

static_assert(is_same_v<iterator_traits<span<const int>::iterator>::pointer, const int*>);
static_assert(is_same_v<iterator_traits<span<const int>::const_iterator>::pointer, const int*>);
static_assert(is_same_v<span<const int>::reverse_iterator, reverse_iterator<span<const int>::iterator>>);
static_assert(is_same_v<span<const int>::const_reverse_iterator, reverse_iterator<span<const int>::const_iterator>>);

static_assert(is_same_v<iterator_traits<span<const int, 3>::iterator>::pointer, const int*>);
static_assert(is_same_v<iterator_traits<span<const int, 3>::const_iterator>::pointer, const int*>);
static_assert(is_same_v<span<const int, 3>::reverse_iterator, reverse_iterator<span<const int, 3>::iterator>>);
static_assert(
is_same_v<span<const int, 3>::const_reverse_iterator, reverse_iterator<span<const int, 3>::const_iterator>>);

#ifdef __cpp_lib_concepts
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
// ... except for cross-type iterator operations.
static_assert(totally_ordered_with<span<int>::iterator, span<int>::const_iterator>);
static_assert(sized_sentinel_for<span<int>::iterator, span<int>::const_iterator>);
static_assert(totally_ordered_with<span<const int>::iterator, span<const int>::const_iterator>);
static_assert(sized_sentinel_for<span<const int>::iterator, span<const int>::const_iterator>);
static_assert(totally_ordered_with<span<int, 3>::iterator, span<int, 3>::const_iterator>);
static_assert(sized_sentinel_for<span<int, 3>::iterator, span<int, 3>::const_iterator>);
static_assert(totally_ordered_with<span<const int, 3>::iterator, span<const int, 3>::const_iterator>);
static_assert(sized_sentinel_for<span<const int, 3>::iterator, span<const int, 3>::const_iterator>);

#if _ITERATOR_DEBUG_LEVEL >= 1
static_assert(_Range_verifiable_v<span<int>::iterator, span<int>::const_iterator>);
static_assert(_Range_verifiable_v<span<int>::const_iterator, span<int>::iterator>);
static_assert(_Range_verifiable_v<span<const int>::iterator, span<const int>::const_iterator>);
static_assert(_Range_verifiable_v<span<const int>::const_iterator, span<const int>::iterator>);
static_assert(_Range_verifiable_v<span<int, 3>::iterator, span<int, 3>::const_iterator>);
static_assert(_Range_verifiable_v<span<int, 3>::const_iterator, span<int, 3>::iterator>);
static_assert(_Range_verifiable_v<span<const int, 3>::iterator, span<const int, 3>::const_iterator>);
static_assert(_Range_verifiable_v<span<const int, 3>::const_iterator, span<const int, 3>::iterator>);
#endif // _ITERATOR_DEBUG_LEVEL >= 1
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L

static_assert(ranges::enable_safe_range<span<int>>);
static_assert(ranges::enable_safe_range<span<int, 3>>);
#endif // __cpp_lib_concepts
Expand All @@ -124,16 +92,12 @@ static_assert(is_same_v<tuple_element_t<2, const span<const int, 3>>, const int>
// that span and its iterator types are trivially copyable.
static_assert(is_trivially_copyable_v<span<int>>);
static_assert(is_trivially_copyable_v<span<int>::iterator>);
static_assert(is_trivially_copyable_v<span<int>::const_iterator>);
static_assert(is_trivially_copyable_v<span<int, 3>>);
static_assert(is_trivially_copyable_v<span<int, 3>::iterator>);
static_assert(is_trivially_copyable_v<span<int, 3>::const_iterator>);
static_assert(is_trivially_copyable_v<span<const int>>);
static_assert(is_trivially_copyable_v<span<const int>::iterator>);
static_assert(is_trivially_copyable_v<span<const int>::const_iterator>);
static_assert(is_trivially_copyable_v<span<const int, 3>>);
static_assert(is_trivially_copyable_v<span<const int, 3>::iterator>);
static_assert(is_trivially_copyable_v<span<const int, 3>::const_iterator>);

struct Base {};
struct Derived : Base {};
Expand Down Expand Up @@ -937,12 +901,8 @@ constexpr bool test() {
static_assert(noexcept(sp_dyn.data()));
static_assert(noexcept(sp_dyn.begin()));
static_assert(noexcept(sp_dyn.end()));
static_assert(noexcept(sp_dyn.cbegin()));
static_assert(noexcept(sp_dyn.cend()));
static_assert(noexcept(sp_dyn.rbegin()));
static_assert(noexcept(sp_dyn.rend()));
static_assert(noexcept(sp_dyn.crbegin()));
static_assert(noexcept(sp_dyn.crend()));

static_assert(noexcept(sp_nine.size()));
static_assert(noexcept(sp_nine.size_bytes()));
Expand All @@ -953,12 +913,8 @@ constexpr bool test() {
static_assert(noexcept(sp_nine.data()));
static_assert(noexcept(sp_nine.begin()));
static_assert(noexcept(sp_nine.end()));
static_assert(noexcept(sp_nine.cbegin()));
static_assert(noexcept(sp_nine.cend()));
static_assert(noexcept(sp_nine.rbegin()));
static_assert(noexcept(sp_nine.rend()));
static_assert(noexcept(sp_nine.crbegin()));
static_assert(noexcept(sp_nine.crend()));

assert(sp_dyn.size() == 9);
assert(sp_nine.size() == 9);
Expand Down Expand Up @@ -996,40 +952,20 @@ constexpr bool test() {
assert(sp_dyn.end()[-2] == 80);
assert(sp_nine.end()[-2] == 80);

assert(*sp_dyn.cbegin() == 10);
assert(*sp_nine.cbegin() == 10);

assert(sp_dyn.cend()[-2] == 80);
assert(sp_nine.cend()[-2] == 80);

assert(*sp_dyn.rbegin() == 90);
assert(*sp_nine.rbegin() == 90);

assert(sp_dyn.rend()[-2] == 20);
assert(sp_nine.rend()[-2] == 20);

assert(*sp_dyn.crbegin() == 90);
assert(*sp_nine.crbegin() == 90);

assert(sp_dyn.crend()[-2] == 20);
assert(sp_nine.crend()[-2] == 20);

static_assert(is_same_v<decltype(sp_dyn.begin()), span<int>::iterator>);
static_assert(is_same_v<decltype(sp_nine.begin()), span<int, 9>::iterator>);
static_assert(is_same_v<decltype(sp_dyn.end()), span<int>::iterator>);
static_assert(is_same_v<decltype(sp_nine.end()), span<int, 9>::iterator>);
static_assert(is_same_v<decltype(sp_dyn.cbegin()), span<int>::const_iterator>);
static_assert(is_same_v<decltype(sp_nine.cbegin()), span<int, 9>::const_iterator>);
static_assert(is_same_v<decltype(sp_dyn.cend()), span<int>::const_iterator>);
static_assert(is_same_v<decltype(sp_nine.cend()), span<int, 9>::const_iterator>);
static_assert(is_same_v<decltype(sp_dyn.rbegin()), span<int>::reverse_iterator>);
static_assert(is_same_v<decltype(sp_nine.rbegin()), span<int, 9>::reverse_iterator>);
static_assert(is_same_v<decltype(sp_dyn.rend()), span<int>::reverse_iterator>);
static_assert(is_same_v<decltype(sp_nine.rend()), span<int, 9>::reverse_iterator>);
static_assert(is_same_v<decltype(sp_dyn.crbegin()), span<int>::const_reverse_iterator>);
static_assert(is_same_v<decltype(sp_nine.crbegin()), span<int, 9>::const_reverse_iterator>);
static_assert(is_same_v<decltype(sp_dyn.crend()), span<int>::const_reverse_iterator>);
static_assert(is_same_v<decltype(sp_nine.crend()), span<int, 9>::const_reverse_iterator>);

static_assert(noexcept(get<5>(sp_nine)));
assert(get<5>(sp_nine) == 60);
Expand Down