Skip to content

Commit adbe092

Browse files
[deque] fix: copy_construct_impl source pointer, emplace_decision::pos type, null-pointer guard in deque(n,val)
- copy_construct_impl for non-trivial types: use fromcontroller.front_block.curr_ptr instead of controller.front_block.curr_ptr for single-block case - emplace_decision::pos changed from ::std::size_t to iterator type - deque(size_type, const_reference) add early return for n==0 to avoid null-pointer arithmetic in set_newed_common Add tests: access, algorithm, assign_range, capacity, compare, concepts, constructors/iter_iter, constructors/n_val, insert_initializer_list, insert_range_iterator, invalidation, move_only, self_reference, swap, type_traits
1 parent 547077c commit adbe092

16 files changed

Lines changed: 2190 additions & 6 deletions

File tree

include/fast_io_dsal/impl/deque.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -859,10 +859,10 @@ inline constexpr void deque_clone_trivial_impl(dequecontroltype &controller, deq
859859
using begin_ptrtype = replacetype *;
860860

861861
begin_ptrtype lastblockbegin;
862-
if (front_controller_ptr == back_controller_ptr)
863-
{
864-
lastblockbegin = fromcontroller.front_block.curr_ptr;
865-
}
862+
if (front_controller_ptr == back_controller_ptr)
863+
{
864+
lastblockbegin = fromcontroller.front_block.curr_ptr;
865+
}
866866
else
867867
{
868868
auto destit{controller.front_block.controller_ptr};
@@ -2228,7 +2228,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE
22282228
pointer lastblockbegin;
22292229
if (front_controller_ptr == back_controller_ptr)
22302230
{
2231-
lastblockbegin = controller.front_block.curr_ptr;
2231+
lastblockbegin = fromcontroller.front_block.curr_ptr;
22322232
}
22332233
else
22342234
{
@@ -2342,7 +2342,12 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE
23422342
}
23432343

23442344
inline explicit constexpr deque(size_type n, const_reference val) noexcept(::std::is_nothrow_copy_constructible_v<value_type>)
2345+
: controller{}
23452346
{
2347+
if (!n)
2348+
{
2349+
return;
2350+
}
23462351
if constexpr (::std::is_nothrow_copy_constructible_v<value_type>)
23472352
{
23482353
this->reserve_back(n);
@@ -3303,7 +3308,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE
33033308

33043309
struct emplace_decision
33053310
{
3306-
::std::size_t pos;
3311+
iterator pos;
33073312
::std::int_fast8_t decision;
33083313
};
33093314
template <bool isnothrow>
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#include <fast_io.h>
2+
#include <fast_io_dsal/deque.h>
3+
#include <deque>
4+
5+
namespace
6+
{
7+
8+
inline void test_operator_subscript()
9+
{
10+
::fast_io::io::perr("=== deque operator[] test ===\n");
11+
12+
::fast_io::deque<::std::size_t> dq;
13+
::std::deque<::std::size_t> ref;
14+
15+
// Fill with data
16+
for (::std::size_t i{}; i != 4096u; ++i)
17+
{
18+
dq.push_back(i);
19+
ref.push_back(i);
20+
}
21+
22+
// Test operator[] (non-const)
23+
for (::std::size_t i{}; i != dq.size(); ++i)
24+
{
25+
if (dq[i] != ref[i])
26+
{
27+
::fast_io::io::panicln("operator[] mismatch at ", i);
28+
}
29+
}
30+
31+
// Test operator[] (const)
32+
{
33+
auto const &cdq = dq;
34+
for (::std::size_t i{}; i != cdq.size(); ++i)
35+
{
36+
if (cdq[i] != ref[i])
37+
{
38+
::fast_io::io::panicln("const operator[] mismatch at ", i);
39+
}
40+
}
41+
}
42+
43+
// Test index_unchecked
44+
for (::std::size_t i{}; i != dq.size(); ++i)
45+
{
46+
if (dq.index_unchecked(i) != ref[i])
47+
{
48+
::fast_io::io::panicln("index_unchecked mismatch at ", i);
49+
}
50+
}
51+
52+
// Modify via operator[] and verify
53+
for (::std::size_t i{}; i != dq.size(); ++i)
54+
{
55+
dq[i] = i * 2u;
56+
ref[i] = i * 2u;
57+
}
58+
59+
for (::std::size_t i{}; i != dq.size(); ++i)
60+
{
61+
if (dq[i] != ref[i])
62+
{
63+
::fast_io::io::panicln("operator[] modification mismatch at ", i);
64+
}
65+
}
66+
67+
::fast_io::io::print("deque operator[] test finished\n");
68+
}
69+
70+
inline void test_front_back()
71+
{
72+
::fast_io::io::perr("=== deque front() / back() test ===\n");
73+
74+
::fast_io::deque<::std::size_t> dq;
75+
::std::deque<::std::size_t> ref;
76+
77+
for (::std::size_t i{}; i != 4096u; ++i)
78+
{
79+
dq.push_back(i);
80+
ref.push_back(i);
81+
}
82+
83+
// front() and back() (non-const)
84+
if (dq.front() != ref.front())
85+
{
86+
::fast_io::io::panic("front() mismatch\n");
87+
}
88+
89+
if (dq.back() != ref.back())
90+
{
91+
::fast_io::io::panic("back() mismatch\n");
92+
}
93+
94+
// front() and back() (const)
95+
{
96+
auto const &cdq = dq;
97+
if (cdq.front() != ref.front())
98+
{
99+
::fast_io::io::panic("const front() mismatch\n");
100+
}
101+
102+
if (cdq.back() != ref.back())
103+
{
104+
::fast_io::io::panic("const back() mismatch\n");
105+
}
106+
}
107+
108+
// front_unchecked and back_unchecked
109+
if (dq.front_unchecked() != ref.front())
110+
{
111+
::fast_io::io::panic("front_unchecked() mismatch\n");
112+
}
113+
114+
if (dq.back_unchecked() != ref.back())
115+
{
116+
::fast_io::io::panic("back_unchecked() mismatch\n");
117+
}
118+
119+
// Modify and verify
120+
dq.front() = 9999u;
121+
ref.front() = 9999u;
122+
123+
if (dq.front() != ref.front())
124+
{
125+
::fast_io::io::panic("front() modification mismatch\n");
126+
}
127+
128+
dq.back() = 8888u;
129+
ref.back() = 8888u;
130+
131+
if (dq.back() != ref.back())
132+
{
133+
::fast_io::io::panic("back() modification mismatch\n");
134+
}
135+
136+
::fast_io::io::print("deque front() / back() test finished\n");
137+
}
138+
139+
} // namespace
140+
141+
int main()
142+
{
143+
test_operator_subscript();
144+
test_front_back();
145+
}
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
#include <fast_io.h>
2+
#include <fast_io_dsal/deque.h>
3+
#include <deque>
4+
#include <algorithm>
5+
#include <vector>
6+
7+
namespace
8+
{
9+
10+
inline void test_copy()
11+
{
12+
::fast_io::io::perr("=== deque std::copy test ===\n");
13+
14+
// Test sizes at and around block boundaries
15+
::std::size_t const sizes[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
16+
17+
for (::std::size_t n : sizes)
18+
{
19+
::fast_io::deque<::std::size_t> src;
20+
::fast_io::deque<::std::size_t> dst;
21+
22+
for (::std::size_t i{}; i != n; ++i)
23+
{
24+
src.push_back(i);
25+
dst.push_back(0u);
26+
}
27+
28+
auto result = ::std::copy(src.cbegin(), src.cend(), dst.begin());
29+
if (result != dst.end())
30+
{
31+
::fast_io::io::panicln("copy result not at end for n=", n);
32+
}
33+
34+
for (::std::size_t i{}; i != n; ++i)
35+
{
36+
if (dst[i] != src[i])
37+
{
38+
::fast_io::io::panicln("copy value mismatch at ", i, " for n=", n);
39+
}
40+
}
41+
}
42+
43+
// Compare with std::deque
44+
{
45+
::fast_io::deque<::std::size_t> fsrc, fdst;
46+
::std::deque<::std::size_t> ssrc, sdst;
47+
48+
for (::std::size_t i{}; i != 4096u; ++i)
49+
{
50+
fsrc.push_back(i);
51+
fdst.push_back(0u);
52+
ssrc.push_back(i);
53+
sdst.push_back(0);
54+
}
55+
56+
::std::copy(fsrc.cbegin(), fsrc.cend(), fdst.begin());
57+
::std::copy(ssrc.cbegin(), ssrc.cend(), sdst.begin());
58+
59+
for (::std::size_t i{}; i != 4096u; ++i)
60+
{
61+
if (fdst[i] != sdst[i])
62+
{
63+
::fast_io::io::panicln("copy mismatch with std::deque at ", i);
64+
}
65+
}
66+
}
67+
68+
::fast_io::io::print("deque std::copy test finished\n");
69+
}
70+
71+
inline void test_copy_backward()
72+
{
73+
::fast_io::io::perr("=== deque std::copy_backward test ===\n");
74+
75+
{
76+
::fast_io::deque<::std::size_t> dq;
77+
for (::std::size_t i{}; i != 100u; ++i)
78+
{
79+
dq.push_back(i);
80+
}
81+
82+
dq.resize(110u);
83+
::std::copy_backward(dq.cbegin(), dq.cbegin() + 100, dq.end());
84+
85+
// First 10 elements unchanged (still 0..9)
86+
for (::std::size_t i{}; i != 10u; ++i)
87+
{
88+
if (dq[i] != i)
89+
{
90+
::fast_io::io::panicln("copy_backward: first elements wrong at ", i);
91+
}
92+
}
93+
for (::std::size_t i{}; i != 100u; ++i)
94+
{
95+
if (dq[i + 10u] != i)
96+
{
97+
::fast_io::io::panicln("copy_backward: shifted elements wrong at ", i);
98+
}
99+
}
100+
}
101+
102+
// Compare with std::deque
103+
{
104+
::fast_io::deque<::std::size_t> fdq;
105+
::std::deque<::std::size_t> sdq;
106+
107+
for (::std::size_t i{}; i != 100u; ++i)
108+
{
109+
fdq.push_back(i);
110+
sdq.push_back(i);
111+
}
112+
113+
fdq.resize(110u);
114+
sdq.resize(110);
115+
::std::copy_backward(fdq.cbegin(), fdq.cbegin() + 100, fdq.end());
116+
::std::copy_backward(sdq.cbegin(), sdq.cbegin() + 100, sdq.end());
117+
118+
for (::std::size_t i{}; i != 110u; ++i)
119+
{
120+
if (fdq[i] != sdq[i])
121+
{
122+
::fast_io::io::panicln("copy_backward mismatch with std::deque at ", i);
123+
}
124+
}
125+
}
126+
127+
::fast_io::io::print("deque std::copy_backward test finished\n");
128+
}
129+
130+
inline void test_move()
131+
{
132+
::fast_io::io::perr("=== deque std::move test ===\n");
133+
134+
::std::size_t const sizes[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
135+
136+
for (::std::size_t n : sizes)
137+
{
138+
::fast_io::deque<::std::size_t> src;
139+
::fast_io::deque<::std::size_t> dst;
140+
141+
for (::std::size_t i{}; i != n; ++i)
142+
{
143+
src.push_back(i);
144+
dst.push_back(0u);
145+
}
146+
147+
auto result = ::std::move(src.begin(), src.end(), dst.begin());
148+
if (result != dst.end())
149+
{
150+
::fast_io::io::panicln("move result not at end for n=", n);
151+
}
152+
153+
for (::std::size_t i{}; i != n; ++i)
154+
{
155+
if (dst[i] != i)
156+
{
157+
::fast_io::io::panicln("move value mismatch at ", i, " for n=", n);
158+
}
159+
}
160+
}
161+
162+
::fast_io::io::print("deque std::move test finished\n");
163+
}
164+
165+
inline void test_move_backward()
166+
{
167+
::fast_io::io::perr("=== deque std::move_backward test ===\n");
168+
169+
::fast_io::deque<::std::size_t> dq;
170+
for (::std::size_t i{}; i != 100u; ++i)
171+
{
172+
dq.push_back(i);
173+
}
174+
175+
dq.resize(110u);
176+
::std::move_backward(dq.begin(), dq.begin() + 100, dq.end());
177+
178+
for (::std::size_t i{}; i != 10u; ++i)
179+
{
180+
if (dq[i] != i)
181+
{
182+
::fast_io::io::panicln("move_backward: first elements wrong at ", i);
183+
}
184+
}
185+
for (::std::size_t i{}; i != 100u; ++i)
186+
{
187+
if (dq[i + 10u] != i)
188+
{
189+
::fast_io::io::panicln("move_backward: shifted elements wrong at ", i);
190+
}
191+
}
192+
193+
::fast_io::io::print("deque std::move_backward test finished\n");
194+
}
195+
196+
} // namespace
197+
198+
int main()
199+
{
200+
test_copy();
201+
test_copy_backward();
202+
test_move();
203+
test_move_backward();
204+
}

0 commit comments

Comments
 (0)