77// ===----------------------------------------------------------------------===//
88
99// REQUIRES: std-at-least-c++26
10- // UNSUPPORTED: libcpp-hardening-mode=none, no-exceptions
10+ // UNSUPPORTED: no-exceptions
1111
12+ #include < iostream>
1213#include < ranges>
1314#include < utility>
15+ #include < vector>
1416
1517#include " check_assertion.h"
18+ #include " double_move_tracker.h"
19+ #include " test_iterators.h"
1620
1721int globalArray[8 ] = {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 };
1822
19- struct ThrowOnCopyView : std::ranges::view_base {
20- int start_;
21- int * ptr_;
22- constexpr explicit ThrowOnCopyView (int * ptr = globalArray, int start = 0 ) : start_(start), ptr_(ptr) {}
23- constexpr ThrowOnCopyView (ThrowOnCopyView&&) = default;
24- constexpr ThrowOnCopyView (const ThrowOnCopyView&) { throw 42 ; };
25- constexpr ThrowOnCopyView& operator =(ThrowOnCopyView&&) = default ;
26- constexpr ThrowOnCopyView& operator =(const ThrowOnCopyView&) {
27- throw 42 ;
28- return *this ;
29- };
30- constexpr int * begin () const { return ptr_ + start_; }
31- constexpr int * end () const { return ptr_ + 8 ; }
23+
24+ template <class It , class ItTraits = It >
25+ class ThrowOnMoveIterator
26+ {
27+ typedef std::iterator_traits<ItTraits> Traits;
28+ It it_;
29+ support::double_move_tracker tracker_;
30+ bool moved = false ;
31+
32+ template <class U , class T > friend class ThrowOnMoveIterator ;
33+ public:
34+ typedef std::input_iterator_tag iterator_category;
35+ typedef typename Traits::value_type value_type;
36+ typedef typename Traits::difference_type difference_type;
37+ typedef It pointer;
38+ typedef typename Traits::reference reference;
39+
40+ constexpr ThrowOnMoveIterator () {}
41+
42+ constexpr ThrowOnMoveIterator (It it) : it_(it) {}
43+
44+ template <class U , class T >
45+ constexpr ThrowOnMoveIterator (const ThrowOnMoveIterator<U, T>& u) : it_(u.it_), tracker_(u.tracker_), moved(u.moved) {}
46+
47+ constexpr ThrowOnMoveIterator (const ThrowOnMoveIterator& other): moved(other.moved){}
48+
49+ constexpr ThrowOnMoveIterator (ThrowOnMoveIterator&& other){
50+ throw std::runtime_error (" Move failed in iter" );
51+ other.moved = true ;
52+ moved = other.moved ;
53+ }
54+
55+ ThrowOnMoveIterator& operator =(ThrowOnMoveIterator&& other) {
56+ if (other.moved ) {
57+ throw std::runtime_error (" Move assignment failed in iter" );
58+ }
59+ other.moved = true ;
60+ moved = other.moved ;
61+ return *this ;
62+ }
63+
64+ constexpr reference operator *() const {return *it_;}
65+
66+ constexpr ThrowOnMoveIterator& operator ++() {++it_; return *this ;}
67+ constexpr ThrowOnMoveIterator operator ++(int ) {return ThrowOnMoveIterator (it_++);}
68+
69+ friend constexpr bool operator ==(const ThrowOnMoveIterator& x, const ThrowOnMoveIterator& y) {return x.it_ == y.it_ ;}
70+ friend constexpr bool operator !=(const ThrowOnMoveIterator& x, const ThrowOnMoveIterator& y) {return x.it_ != y.it_ ;}
71+
72+ friend constexpr It base (const ThrowOnMoveIterator& i) { return i.it_ ; }
73+
74+ template <class T >
75+ void operator ,(T const &) = delete ;
76+ };
77+
78+ template <class T >
79+ struct BufferView : std::ranges::view_base {
80+ T* buffer_;
81+ std::size_t size_;
82+
83+ template <std::size_t N>
84+ constexpr BufferView (T (&b)[N]) : buffer_(b), size_(N) {}
85+ };
86+
87+ using IntBufferView = BufferView<int >;
88+
89+ template <bool Simple>
90+ struct Common : IntBufferView {
91+ using IntBufferView::IntBufferView;
92+ using Iter = ThrowOnMoveIterator<int *>;
93+ using ConstIter = ThrowOnMoveIterator<const int *>;
94+ using Sent = sentinel_wrapper<Iter>;
95+ using ConstSent = sentinel_wrapper<ConstIter>;
96+
97+ constexpr Iter begin ()
98+ requires(!Simple)
99+ {
100+ return Iter{buffer_};
101+ }
102+ constexpr const ConstIter begin () const { return ConstIter{buffer_}; }
103+ constexpr Sent end ()
104+ requires(!Simple)
105+ {
106+ return Sent (buffer_ + size_);
107+ }
108+ constexpr ConstSent end () const { return ConstSent (buffer_ + size_); }
32109};
33110
111+ using SimpleCommon = Common<true >;
112+ using NonSimpleCommon = Common<false >;
113+
34114int main () {
115+
35116 {
36- // valueless by exception test constructor
37- std::ranges::concat_view<ThrowOnCopyView> concatView_2;
38- std::ranges::iterator_t <std::ranges::concat_view<ThrowOnCopyView>> it1;
39- std::ranges::iterator_t <std::ranges::concat_view<ThrowOnCopyView>> it2;
117+ int buffer[3 ] = {1 , 2 , 3 };
118+ int buffer2[3 ] = {1 , 2 , 3 };
119+ NonSimpleCommon view (buffer);
120+ NonSimpleCommon view2 (buffer2);
121+ std::ranges::concat_view v (view, view2);
122+ std::ranges::iterator_t <std::ranges::concat_view<decltype (view), decltype (view2)>> it1;
40123 try {
41- it1 = concatView_2 .begin ();
124+ it1 = v .begin ();
42125 } catch (...) {
43126 TEST_LIBCPP_ASSERT_FAILURE (
44- [& ] {
45- it2 = it1 ;
127+ [= ] {
128+ std::ranges:: iterator_t < const decltype (v)> it2 (v. begin ()) ;
46129 (void )it2;
47130 }(),
48131 " valueless by exception" );
49132 }
50133 }
51-
134+ /*
52135 {
53136 //valueless by exception test operator==
54- std::ranges::concat_view<ThrowOnCopyView> concatView_2;
55- std::ranges::iterator_t <std::ranges::concat_view<ThrowOnCopyView>> it1;
56- std::ranges::iterator_t <std::ranges::concat_view<ThrowOnCopyView>> it2;
137+ ThrowingRange<int*> throwing{3, 5};
138+ auto concatView_2 = std::views::concat(throwing);
139+ decltype(concatView_2.begin()) it1{};
140+ decltype(concatView_2.begin()) it2{};
57141 try {
58142 it1 = concatView_2.begin();
59143 } catch (...) {
144+ std::cout << "Catch is hit" << std::endl;
60145 TEST_LIBCPP_ASSERT_FAILURE([&] { (void)(it1 == it2); }(), "valueless by exception");
61146 }
62147 }
@@ -68,6 +153,7 @@ int main() {
68153 try {
69154 it1 = concatView_2.begin();
70155 } catch (...) {
156+ std::cout << "Catch is hit" << std::endl;
71157 TEST_LIBCPP_ASSERT_FAILURE([&] { (void)--*it1; }(), "valueless by exception");
72158 }
73159 }
@@ -79,6 +165,7 @@ int main() {
79165 try {
80166 it1 = concatView_2.begin();
81167 } catch (...) {
168+ std::cout << "Catch is hit" << std::endl;
82169 TEST_LIBCPP_ASSERT_FAILURE([&] { (void)*it1; }(), "valueless by exception");
83170 }
84171 }
@@ -90,6 +177,7 @@ int main() {
90177 try {
91178 it1 = concatView_2.begin();
92179 } catch (...) {
180+ std::cout << "Catch is hit" << std::endl;
93181 TEST_LIBCPP_ASSERT_FAILURE([&] { (void)++*it1; }(), "valueless by exception");
94182 }
95183 }
@@ -101,7 +189,9 @@ int main() {
101189 try {
102190 it1 = concatView_2.begin();
103191 } catch (...) {
192+ std::cout << "Catch is hit" << std::endl;
104193 TEST_LIBCPP_ASSERT_FAILURE([&] { (void)(it1 += 1); }(), "valueless by exception");
105194 }
106195 }
196+ */
107197}
0 commit comments