Skip to content

Commit 601216f

Browse files
update test
1 parent b0dcc2e commit 601216f

File tree

2 files changed

+172
-127
lines changed

2 files changed

+172
-127
lines changed

libcxx/include/__ranges/concat_view.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ class concat_view<_Views...>::__iterator {
309309
if (__offset >= __steps) {
310310
std::get<_Idx>(__it_) -= static_cast<__underlying_diff_type>(__steps);
311311
} else {
312-
auto __prev_size = ranges::__distance(std::get<_Idx - 1>(__parent_->__views_));
312+
auto __prev_size = ranges::distance(std::get<_Idx - 1>(__parent_->__views_));
313313
__it_.template emplace<_Idx - 1>(ranges::begin(std::get<_Idx - 1>(__parent_->__views_)) + __prev_size);
314314
__advance_bwd<_Idx - 1>(__prev_size, __steps - __offset);
315315
}

libcxx/test/libcxx/ranges/range.adaptors/range.concat/iterator.valueless_by_exception.pass.cpp

Lines changed: 171 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -18,190 +18,235 @@
1818
#include "double_move_tracker.h"
1919
#include "test_iterators.h"
2020

21-
int globalArray[8] = {0, 1, 2, 3, 4, 5, 6, 7};
22-
bool already_moved = false;
21+
int val[] = {1, 2, 3};
2322

24-
template <class It, class ItTraits = It >
25-
class ThrowOnMoveIterator {
26-
using Traits = std::iterator_traits<ItTraits>;
27-
It it_;
28-
support::double_move_tracker tracker_;
23+
bool flag = false;
2924

30-
template <class U, class T>
31-
friend class ThrowOnMoveIterator;
25+
// Forward declaration
26+
template<std::size_t N> struct Iter;
3227

33-
public:
34-
using iterator_category = std::input_iterator_tag;
35-
using value_type = typename Traits::value_type;
36-
using difference_type = typename Traits::difference_type;
37-
using pointer = It;
38-
using reference = typename Traits::reference;
28+
// Iterator class
29+
template<std::size_t N>
30+
struct Iter {
31+
using value_type = int;
32+
using difference_type = std::ptrdiff_t;
33+
using reference = int&;
34+
using pointer = int*;
35+
using iterator_category = std::random_access_iterator_tag;
36+
using iterator_concept = std::random_access_iterator_tag;
3937

40-
constexpr ThrowOnMoveIterator() {}
38+
private:
39+
int* ptr_ = nullptr;
4140

42-
constexpr ThrowOnMoveIterator(It it) : it_(it) {}
41+
// Allow cross-template access to ptr_
42+
template<std::size_t M> friend struct Iter;
4343

44-
template <class U, class T>
45-
constexpr ThrowOnMoveIterator(const ThrowOnMoveIterator<U, T>& u) : it_(u.it_), tracker_(u.tracker_) {}
44+
public:
45+
// Constructors
46+
Iter() = default;
47+
Iter(int* ptr) : ptr_(ptr) {}
48+
Iter(const Iter&) = default;
49+
Iter(Iter&& other) noexcept : ptr_(other.ptr_) {}
50+
51+
// Cross-template constructor
52+
template<std::size_t M>
53+
Iter(const Iter<M>& other) : ptr_(other.ptr_) {}
54+
55+
// Assignment operators
56+
Iter& operator=(const Iter&) = default;
57+
Iter& operator=(Iter&& other) noexcept {
58+
ptr_ = other.ptr_;
59+
return *this;
60+
}
4661

47-
constexpr ThrowOnMoveIterator(const ThrowOnMoveIterator&) {}
62+
// Dereference and access
63+
reference operator*() const { return *ptr_; }
64+
pointer operator->() const { return ptr_; }
65+
reference operator[](difference_type n) const { return ptr_[n]; }
4866

49-
constexpr ThrowOnMoveIterator(ThrowOnMoveIterator&&) {
50-
std::cout << "moved ctor called with: " << already_moved << std::endl;
51-
if (!already_moved) {
52-
already_moved = true;
53-
throw std::runtime_error("Move failed in iter");
54-
}
55-
}
67+
// Increment and decrement
68+
Iter& operator++() { ++ptr_; return *this; }
69+
Iter operator++(int) { auto tmp = *this; ++*this; return tmp; }
70+
Iter& operator--() { --ptr_; return *this; }
71+
Iter operator--(int) { auto tmp = *this; --*this; return tmp; }
5672

57-
ThrowOnMoveIterator& operator=(ThrowOnMoveIterator&&) {
58-
if (!already_moved) {
59-
already_moved = true;
60-
throw std::runtime_error("Move assignment failed in iter");
61-
}
62-
return *this;
63-
}
73+
// Arithmetic operations
74+
Iter& operator+=(difference_type n) { ptr_ += n; return *this; }
75+
Iter& operator-=(difference_type n) { ptr_ -= n; return *this; }
6476

65-
constexpr reference operator*() const { return *it_; }
77+
// Declare friend operators (no inline definition)
78+
template<std::size_t X>
79+
friend Iter<X> operator+(Iter<X> it, difference_type n);
6680

67-
constexpr ThrowOnMoveIterator& operator++() {
68-
++it_;
69-
return *this;
70-
}
71-
constexpr ThrowOnMoveIterator operator++(int) { return ThrowOnMoveIterator(it_++); }
81+
template<std::size_t X>
82+
friend Iter<X> operator+(difference_type n, Iter<X> it);
7283

73-
friend constexpr bool operator==(const ThrowOnMoveIterator& x, const ThrowOnMoveIterator& y) {
74-
return x.it_ == y.it_;
75-
}
76-
friend constexpr bool operator!=(const ThrowOnMoveIterator& x, const ThrowOnMoveIterator& y) {
77-
return x.it_ != y.it_;
78-
}
84+
template<std::size_t X>
85+
friend Iter<X> operator-(Iter<X> it, difference_type n);
7986

80-
friend constexpr It base(const ThrowOnMoveIterator& i) { return i.it_; }
87+
template<std::size_t X, std::size_t Y>
88+
friend difference_type operator-(Iter<X> a, Iter<Y> b);
8189

82-
template <class T>
83-
void operator,(T const&) = delete;
90+
// Comparison operators
91+
friend bool operator==(Iter a, Iter b) = default;
92+
friend bool operator<(Iter a, Iter b) { return a.ptr_ < b.ptr_; }
93+
friend bool operator>(Iter a, Iter b) { return a.ptr_ > b.ptr_; }
94+
friend bool operator<=(Iter a, Iter b) { return a.ptr_ <= b.ptr_; }
95+
friend bool operator>=(Iter a, Iter b) { return a.ptr_ >= b.ptr_; }
8496
};
8597

86-
template <class T>
87-
struct BufferView : std::ranges::view_base {
88-
T* buffer_;
89-
std::size_t size_;
98+
// Define operators outside the class
99+
template<std::size_t X>
100+
inline Iter<X> operator+(Iter<X> it, std::ptrdiff_t n) {
101+
return Iter<X>(it.ptr_ + n);
102+
}
90103

91-
template <std::size_t N>
92-
constexpr BufferView(T (&b)[N]) : buffer_(b), size_(N) {}
93-
};
104+
template<std::size_t X>
105+
inline Iter<X> operator+(std::ptrdiff_t n, Iter<X> it) {
106+
return Iter<X>(it.ptr_ + n);
107+
}
94108

95-
using IntBufferView = BufferView<int>;
109+
template<std::size_t X>
110+
inline Iter<X> operator-(Iter<X> it, std::ptrdiff_t n) {
111+
return Iter<X>(it.ptr_ - n);
112+
}
96113

97-
template <bool Simple>
98-
struct Common : IntBufferView {
99-
using IntBufferView::IntBufferView;
100-
using Iter = ThrowOnMoveIterator<int*>;
101-
using ConstIter = ThrowOnMoveIterator<const int*>;
102-
using Sent = sentinel_wrapper<Iter>;
103-
using ConstSent = sentinel_wrapper<ConstIter>;
114+
template<std::size_t X, std::size_t Y>
115+
inline std::ptrdiff_t operator-(Iter<X> a, Iter<Y> b) {
116+
return a.ptr_ - b.ptr_;
117+
}
104118

105-
constexpr Iter begin()
106-
requires(!Simple)
107-
{
108-
return Iter{buffer_};
109-
}
110-
constexpr const ConstIter begin() const { return ConstIter{buffer_}; }
111-
constexpr Sent end()
112-
requires(!Simple)
113-
{
114-
return Sent(buffer_ + size_);
115-
}
116-
constexpr ConstSent end() const { return ConstSent(buffer_ + size_); }
119+
template<std::size_t N>
120+
struct Range : std::ranges::view_base {
121+
using iterator = Iter<N>;
122+
using const_iterator = Iter<N>;
123+
124+
int* data_;
125+
std::size_t size_;
126+
127+
Range() : data_(val), size_(4) {}
128+
129+
Range(int* data, std::size_t size) : data_(data), size_(size) {}
130+
131+
iterator begin() { return iterator(data_); }
132+
iterator end() { return iterator(data_ + size_); }
133+
134+
const_iterator begin() const { return const_iterator(data_); }
135+
const_iterator end() const { return const_iterator(data_ + size_); }
136+
137+
std::size_t size() const { return size_; }
117138
};
118139

119-
using SimpleCommon = Common<true>;
120-
using NonSimpleCommon = Common<false>;
140+
static_assert(std::ranges::range<Range<0>>);
141+
static_assert(std::ranges::sized_range<Range<0>>);
121142

122143
int main() {
144+
123145
{
124-
int buffer[3] = {1, 2, 3};
125-
int buffer2[3] = {1, 2, 3};
126-
NonSimpleCommon view(buffer);
127-
NonSimpleCommon view2(buffer2);
128-
std::ranges::concat_view v(view, view2);
129-
std::ranges::iterator_t<std::ranges::concat_view<decltype(view), decltype(view2)>> it1;
146+
//valueless by exception test operator*
147+
Range<0> r1;
148+
Range<1> r2;
149+
150+
auto cv = std::views::concat(r1, r2);
151+
auto iter1 = cv.begin();
152+
auto iter2 = std::ranges::next(cv.begin(), 4);
153+
flag = true;
130154
try {
131-
it1 = v.begin();
155+
iter1 = std::move(iter2);
132156
} catch (...) {
133-
std::cout << "hit catch" << std::endl;
134-
//ASSERT_SAME_TYPE(std::ranges::iterator_t<const decltype(v)>, int);
135-
std::ranges::iterator_t<const decltype(v)> it2(it1);
157+
auto f = std::ranges::distance(r1);
158+
(void)f;
136159
TEST_LIBCPP_ASSERT_FAILURE(
137160
[=] {
138-
std::ranges::iterator_t<const decltype(v)> it2(it1);
139-
(void)it2;
161+
*iter1;
140162
}(),
141163
"valueless by exception");
142164
}
143165
}
144-
/*
166+
145167
{
146168
//valueless by exception test operator==
147-
ThrowingRange<int*> throwing{3, 5};
148-
auto concatView_2 = std::views::concat(throwing);
149-
decltype(concatView_2.begin()) it1{};
150-
decltype(concatView_2.begin()) it2{};
169+
flag = false;
170+
Range<0> r1;
171+
Range<1> r2;
172+
173+
auto cv = std::views::concat(r1, r2);
174+
auto iter1 = cv.begin();
175+
auto iter2 = std::ranges::next(cv.begin(), 4);
176+
auto iter3 = cv.begin();
177+
flag = true;
151178
try {
152-
it1 = concatView_2.begin();
179+
iter1 = std::move(iter2);
153180
} catch (...) {
154-
std::cout << "Catch is hit" << std::endl;
155-
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)(it1 == it2); }(), "valueless by exception");
181+
TEST_LIBCPP_ASSERT_FAILURE(
182+
[=] {
183+
(void)(iter1 == iter3);
184+
}(),
185+
"valueless by exception");
156186
}
157187
}
158188

159189
{
160190
//valueless by exception test operator--
161-
std::ranges::concat_view<ThrowOnCopyView> concatView_2;
162-
std::ranges::iterator_t<std::ranges::concat_view<ThrowOnCopyView>> it1;
163-
try {
164-
it1 = concatView_2.begin();
165-
} catch (...) {
166-
std::cout << "Catch is hit" << std::endl;
167-
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)--*it1; }(), "valueless by exception");
168-
}
169-
}
170-
171-
{
172-
//valueless by exception test operator*
173-
std::ranges::concat_view<ThrowOnCopyView> concatView_2;
174-
std::ranges::iterator_t<std::ranges::concat_view<ThrowOnCopyView>> it1;
191+
flag = false;
192+
Range<0> r1;
193+
Range<1> r2;
194+
195+
auto cv = std::views::concat(r1, r2);
196+
auto iter1 = cv.begin();
197+
auto iter2 = std::ranges::next(cv.begin(), 4);
198+
flag = true;
175199
try {
176-
it1 = concatView_2.begin();
200+
iter1 = std::move(iter2);
177201
} catch (...) {
178-
std::cout << "Catch is hit" << std::endl;
179-
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)*it1; }(), "valueless by exception");
202+
//ASSERT_SAME_TYPE(decltype(iter1), int);
203+
TEST_LIBCPP_ASSERT_FAILURE(
204+
[&] {
205+
iter1--;
206+
}(),
207+
"valueless by exception");
180208
}
181209
}
182210

183211
{
184212
//valueless by exception test operator++
185-
std::ranges::concat_view<ThrowOnCopyView> concatView_2;
186-
std::ranges::iterator_t<std::ranges::concat_view<ThrowOnCopyView>> it1;
213+
flag = false;
214+
Range<0> r1;
215+
Range<1> r2;
216+
217+
auto cv = std::views::concat(r1, r2);
218+
auto iter1 = cv.begin();
219+
auto iter2 = std::ranges::next(cv.begin(), 4);
220+
flag = true;
187221
try {
188-
it1 = concatView_2.begin();
222+
iter1 = std::move(iter2);
189223
} catch (...) {
190-
std::cout << "Catch is hit" << std::endl;
191-
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)++*it1; }(), "valueless by exception");
224+
TEST_LIBCPP_ASSERT_FAILURE(
225+
[&] {
226+
++iter1;
227+
}(),
228+
"valueless by exception");
192229
}
193230
}
194231

195232
{
196233
//valueless by exception test operator+=
197-
std::ranges::concat_view<ThrowOnCopyView> concatView_2;
198-
std::ranges::iterator_t<std::ranges::concat_view<ThrowOnCopyView>> it1;
234+
flag = false;
235+
Range<0> r1;
236+
Range<1> r2;
237+
238+
auto cv = std::views::concat(r1, r2);
239+
auto iter1 = cv.begin();
240+
auto iter2 = std::ranges::next(cv.begin(), 4);
241+
flag = true;
199242
try {
200-
it1 = concatView_2.begin();
243+
iter1 = std::move(iter2);
201244
} catch (...) {
202-
std::cout << "Catch is hit" << std::endl;
203-
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)(it1 += 1); }(), "valueless by exception");
245+
TEST_LIBCPP_ASSERT_FAILURE(
246+
[&] {
247+
iter1 += 1;
248+
}(),
249+
"valueless by exception");
204250
}
205251
}
206-
*/
207252
}

0 commit comments

Comments
 (0)