Skip to content

Commit 342b431

Browse files
committed
Improve _Copy_memcpy_common return type
1 parent cceff61 commit 342b431

File tree

7 files changed

+369
-118
lines changed

7 files changed

+369
-118
lines changed

stl/inc/memory

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ namespace ranges {
7979
_STL_INTERNAL_STATIC_ASSERT(constructible_from<iter_value_t<_Out>, iter_reference_t<_It>>);
8080

8181
if constexpr (is_same_v<_Se, _It> && _Ptr_copy_cat<_It, _Out>::_Really_trivial) {
82-
return {_ILast, _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast)};
82+
return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast);
8383
} else {
8484
_Uninitialized_backout _Backout{_STD move(_OFirst)};
8585

@@ -149,7 +149,7 @@ namespace ranges {
149149
auto _OFirst = _Get_unwrapped(_STD move(_First2));
150150
const auto _OLast = _Get_unwrapped(_STD move(_Last2));
151151
if constexpr (_Ptr_copy_cat<_It, _Out>::_Really_trivial) {
152-
_OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast);
152+
return _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast);
153153
} else {
154154
_Uninitialized_backout _Backout{_STD move(_OFirst)};
155155

@@ -283,7 +283,7 @@ namespace ranges {
283283
auto _OFirst = _Get_unwrapped(_STD move(_First2));
284284
const auto _OLast = _Get_unwrapped(_STD move(_Last2));
285285
if constexpr (_Ptr_move_cat<_It, _Out>::_Really_trivial) {
286-
_OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast);
286+
return _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast);
287287
} else {
288288
_Uninitialized_backout _Backout{_STD move(_OFirst)};
289289

stl/inc/xmemory

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,18 @@ namespace ranges {
15511551
&& _No_throw_forward_iterator<iterator_t<_Rng>>;
15521552
// clang-format on
15531553

1554+
template <class _InIt, class _OutIt>
1555+
in_out_result<_InIt, _OutIt> _Copy_memcpy_common(
1556+
_InIt _IFirst, _InIt _ILast, _OutIt _OFirst, _OutIt _OLast) noexcept {
1557+
const auto _IFirst_ch = const_cast<char*>(reinterpret_cast<const volatile char*>(_IFirst));
1558+
const auto _ILast_ch = const_cast<const char*>(reinterpret_cast<const volatile char*>(_ILast));
1559+
const auto _OFirst_ch = const_cast<char*>(reinterpret_cast<volatile char*>(_OFirst));
1560+
const auto _OLast_ch = const_cast<const char*>(reinterpret_cast<const volatile char*>(_OLast));
1561+
const auto _Count = static_cast<size_t>((_STD min)(_ILast_ch - _IFirst_ch, _OLast_ch - _OFirst_ch));
1562+
_CSTD memcpy(_OFirst_ch, _IFirst_ch, _Count);
1563+
return {reinterpret_cast<_InIt>(_IFirst_ch + _Count), reinterpret_cast<_OutIt>(_OFirst_ch + _Count)};
1564+
}
1565+
15541566
// ALIAS TEMPLATE uninitialized_move_result
15551567
template <class _In, class _Out>
15561568
using uninitialized_move_result = in_out_result<_In, _Out>;
@@ -1564,7 +1576,7 @@ namespace ranges {
15641576
_It _IFirst, const _Se _ILast, _Out _OFirst, const _OSe _OLast) {
15651577
// clang-format on
15661578
if constexpr (is_same_v<_Se, _It> && _Ptr_move_cat<_It, _Out>::_Really_trivial) {
1567-
return {_ILast, _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast)};
1579+
return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast);
15681580
} else {
15691581
_Uninitialized_backout _Backout{_STD move(_OFirst)};
15701582

stl/inc/xutility

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4102,17 +4102,6 @@ _OutIt _Copy_memmove(move_iterator<_InIt> _First, move_iterator<_InIt> _Last, _O
41024102
return _Copy_memmove(_First.base(), _Last.base(), _Dest);
41034103
}
41044104

4105-
template <class _InIt, class _OutIt>
4106-
_OutIt _Copy_memcpy_common(_InIt _IFirst, _InIt _ILast, _OutIt _OFirst, _OutIt _OLast) noexcept {
4107-
const auto _IFirst_ch = const_cast<const char*>(reinterpret_cast<const volatile char*>(_IFirst));
4108-
const auto _ILast_ch = const_cast<const char*>(reinterpret_cast<const volatile char*>(_ILast));
4109-
const auto _OFirst_ch = const_cast<char*>(reinterpret_cast<volatile char*>(_OFirst));
4110-
const auto _OLast_ch = const_cast<const char*>(reinterpret_cast<const volatile char*>(_OLast));
4111-
const auto _Count = static_cast<size_t>((_STD min)(_ILast_ch - _IFirst_ch, _OLast_ch - _OFirst_ch));
4112-
_CSTD memcpy(_OFirst_ch, _IFirst_ch, _Count);
4113-
return reinterpret_cast<_OutIt>(_OFirst_ch + _Count);
4114-
}
4115-
41164105
// VARIABLE TEMPLATE _Is_vb_iterator
41174106
template <class _It, bool _RequiresMutable = false>
41184107
_INLINE_VAR constexpr bool _Is_vb_iterator = false;

tests/std/tests/P0896R4_ranges_alg_uninitialized_copy/test.cpp

Lines changed: 84 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -76,21 +76,16 @@ struct holder {
7676
}
7777
};
7878

79-
template <class R>
80-
void not_ranges_destroy(R&& r) { // TRANSITION, ranges::destroy
81-
for (auto& e : r) {
82-
destroy_at(&e);
83-
}
84-
}
85-
8679
struct instantiator {
87-
static constexpr int expected_output[] = {13, 55, 12345};
88-
static constexpr int expected_input[] = {13, 55, 12345};
80+
static constexpr int expected_output[] = {13, 55, 12345};
81+
static constexpr int expected_output_long[] = {13, 55, 12345, -1};
82+
static constexpr int expected_input[] = {13, 55, 12345};
83+
static constexpr int expected_input_long[] = {13, 55, 12345, 42};
8984

9085
template <ranges::input_range R, ranges::forward_range W>
9186
static void call() {
92-
using ranges::uninitialized_copy, ranges::uninitialized_copy_result, ranges::equal, ranges::equal_to,
93-
ranges::iterator_t;
87+
using ranges::destroy, ranges::uninitialized_copy, ranges::uninitialized_copy_result, ranges::equal,
88+
ranges::equal_to, ranges::iterator_t;
9489

9590
{ // Validate range overload
9691
int_wrapper input[3] = {13, 55, 12345};
@@ -107,7 +102,7 @@ struct instantiator {
107102
assert(result.out == wrapped_output.end());
108103
assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val));
109104
assert(equal(input, expected_input, equal_to{}, &int_wrapper::val));
110-
not_ranges_destroy(wrapped_output);
105+
destroy(wrapped_output);
111106
assert(int_wrapper::constructions == 3);
112107
assert(int_wrapper::destructions == 3);
113108
}
@@ -127,10 +122,51 @@ struct instantiator {
127122
assert(result.out == wrapped_output.end());
128123
assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val));
129124
assert(equal(input, expected_input, equal_to{}, &int_wrapper::val));
130-
not_ranges_destroy(wrapped_output);
125+
destroy(wrapped_output);
126+
assert(int_wrapper::constructions == 3);
127+
assert(int_wrapper::destructions == 3);
128+
}
129+
130+
{ // Validate range overload shorter output
131+
int_wrapper input[4] = {13, 55, 12345, 42};
132+
R wrapped_input{input};
133+
holder<int_wrapper, 3> mem;
134+
W wrapped_output{mem.as_span()};
135+
136+
int_wrapper::clear_counts();
137+
same_as<uninitialized_copy_result<iterator_t<R>, iterator_t<W>>> auto result =
138+
uninitialized_copy(wrapped_input, wrapped_output);
139+
assert(int_wrapper::constructions == 3);
140+
assert(int_wrapper::destructions == 0);
141+
assert(++result.in == wrapped_input.end());
142+
assert(result.out == wrapped_output.end());
143+
assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val));
144+
assert(equal(input, expected_input_long, equal_to{}, &int_wrapper::val));
145+
destroy(wrapped_output);
131146
assert(int_wrapper::constructions == 3);
132147
assert(int_wrapper::destructions == 3);
133148
}
149+
150+
{ // Validate range overload shorter input
151+
int_wrapper input[3] = {13, 55, 12345};
152+
R wrapped_input{input};
153+
holder<int_wrapper, 4> mem;
154+
W wrapped_output{mem.as_span()};
155+
156+
int_wrapper::clear_counts();
157+
same_as<uninitialized_copy_result<iterator_t<R>, iterator_t<W>>> auto result =
158+
uninitialized_copy(wrapped_input, wrapped_output);
159+
assert(int_wrapper::constructions == 3);
160+
assert(int_wrapper::destructions == 0);
161+
assert(result.in == wrapped_input.end());
162+
construct_at(addressof(*result.out), -1); // Need to construct non written element for comparison
163+
assert(++result.out == wrapped_output.end());
164+
assert(equal(wrapped_output, expected_output_long, equal_to{}, &int_wrapper::val));
165+
assert(equal(input, expected_input, equal_to{}, &int_wrapper::val));
166+
destroy(wrapped_output);
167+
assert(int_wrapper::constructions == 4);
168+
assert(int_wrapper::destructions == 4);
169+
}
134170
}
135171
};
136172

@@ -161,17 +197,44 @@ struct throwing_test {
161197
};
162198

163199
struct memcopy_test {
164-
static constexpr int expected_output[] = {13, 55, 12345};
165-
static constexpr int expected_input[] = {13, 55, 12345};
200+
static constexpr int expected_output[] = {13, 55, 12345};
201+
static constexpr int expected_output_long[] = {13, 55, 12345, -1};
202+
static constexpr int expected_input[] = {13, 55, 12345};
203+
static constexpr int expected_input_long[] = {13, 55, 12345, 42};
166204

167205
static void call() {
168-
// Validate only range overload (one is plenty since they both use the same backend)
169-
int input[] = {13, 55, 12345};
170-
int output[] = {-1, -1, -1};
206+
{ // Validate only range overload
207+
int input[] = {13, 55, 12345};
208+
int output[] = {-1, -1, -1};
209+
210+
const auto result = ranges::uninitialized_copy(input, output);
211+
assert(result.in == end(input));
212+
assert(result.out == end(output));
213+
assert(ranges::equal(input, expected_input));
214+
assert(ranges::equal(output, expected_output));
215+
}
216+
217+
{ // Validate input shorter
218+
int input[] = {13, 55, 12345};
219+
int output[] = {-1, -1, -1, -1};
171220

172-
ranges::uninitialized_copy(input, output);
173-
assert(ranges::equal(input, expected_input));
174-
assert(ranges::equal(output, expected_output));
221+
auto result = ranges::uninitialized_copy(input, output);
222+
assert(result.in == end(input));
223+
assert(++result.out == end(output));
224+
assert(ranges::equal(input, expected_input));
225+
assert(ranges::equal(output, expected_output_long));
226+
}
227+
228+
{ // Validate output shorter
229+
int input[] = {13, 55, 12345, 42};
230+
int output[] = {-1, -1, -1};
231+
232+
auto result = ranges::uninitialized_copy(input, output);
233+
assert(++result.in == end(input));
234+
assert(result.out == end(output));
235+
assert(ranges::equal(input, expected_input_long));
236+
assert(ranges::equal(output, expected_output));
237+
}
175238
}
176239
};
177240

tests/std/tests/P0896R4_ranges_alg_uninitialized_copy_n/test.cpp

Lines changed: 95 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -66,39 +66,77 @@ struct holder {
6666
}
6767
};
6868

69-
template <class R>
70-
void not_ranges_destroy(R&& r) { // TRANSITION, ranges::destroy
71-
for (auto& e : r) {
72-
destroy_at(&e);
73-
}
74-
}
75-
7669
struct instantiator {
77-
static constexpr int expected_output[] = {13, 55, 12345};
78-
static constexpr int expected_input[] = {13, 55, 12345};
70+
static constexpr int expected_output[] = {13, 55, 12345};
71+
static constexpr int expected_output_long[] = {13, 55, 12345, -1};
72+
static constexpr int expected_input[] = {13, 55, 12345};
73+
static constexpr int expected_input_long[] = {13, 55, 12345, 42};
7974

8075
template <ranges::input_range Read, ranges::forward_range Write>
8176
static void call() {
82-
using ranges::uninitialized_copy_n, ranges::uninitialized_copy_n_result, ranges::equal, ranges::equal_to,
83-
ranges::iterator_t;
77+
using ranges::destroy, ranges::uninitialized_copy_n, ranges::uninitialized_copy_n_result, ranges::equal,
78+
ranges::equal_to, ranges::iterator_t;
79+
80+
{ // Validate equal ranges
81+
int_wrapper input[3] = {13, 55, 12345};
82+
Read wrapped_input{input};
83+
holder<int_wrapper, 3> mem;
84+
Write wrapped_output{mem.as_span()};
85+
86+
int_wrapper::clear_counts();
87+
const same_as<uninitialized_copy_n_result<iterator_t<Read>, iterator_t<Write>>> auto result =
88+
uninitialized_copy_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end());
89+
assert(int_wrapper::constructions == 3);
90+
assert(int_wrapper::destructions == 0);
91+
assert(result.in == wrapped_input.end());
92+
assert(result.out == wrapped_output.end());
93+
assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val));
94+
assert(equal(input, expected_input, equal_to{}, &int_wrapper::val));
95+
destroy(wrapped_output);
96+
assert(int_wrapper::constructions == 3);
97+
assert(int_wrapper::destructions == 3);
98+
}
8499

85-
int_wrapper input[3] = {13, 55, 12345};
86-
Read wrapped_input{input};
87-
holder<int_wrapper, 3> mem;
88-
Write wrapped_output{mem.as_span()};
100+
{ // Validate shorter output
101+
int_wrapper input[4] = {13, 55, 12345, 42};
102+
Read wrapped_input{input};
103+
holder<int_wrapper, 3> mem;
104+
Write wrapped_output{mem.as_span()};
105+
106+
int_wrapper::clear_counts();
107+
same_as<uninitialized_copy_n_result<iterator_t<Read>, iterator_t<Write>>> auto result =
108+
uninitialized_copy_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end());
109+
assert(int_wrapper::constructions == 3);
110+
assert(int_wrapper::destructions == 0);
111+
assert(++result.in == wrapped_input.end());
112+
assert(result.out == wrapped_output.end());
113+
assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val));
114+
assert(equal(input, expected_input_long, equal_to{}, &int_wrapper::val));
115+
destroy(wrapped_output);
116+
assert(int_wrapper::constructions == 3);
117+
assert(int_wrapper::destructions == 3);
118+
}
89119

90-
int_wrapper::clear_counts();
91-
const same_as<uninitialized_copy_n_result<iterator_t<Read>, iterator_t<Write>>> auto result =
92-
uninitialized_copy_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end());
93-
assert(int_wrapper::constructions == 3);
94-
assert(int_wrapper::destructions == 0);
95-
assert(result.in == wrapped_input.end());
96-
assert(result.out == wrapped_output.end());
97-
assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val));
98-
assert(equal(input, expected_input, equal_to{}, &int_wrapper::val));
99-
not_ranges_destroy(wrapped_output);
100-
assert(int_wrapper::constructions == 3);
101-
assert(int_wrapper::destructions == 3);
120+
{ // Validate shorter input
121+
int_wrapper input[3] = {13, 55, 12345};
122+
Read wrapped_input{input};
123+
holder<int_wrapper, 4> mem;
124+
Write wrapped_output{mem.as_span()};
125+
126+
int_wrapper::clear_counts();
127+
same_as<uninitialized_copy_n_result<iterator_t<Read>, iterator_t<Write>>> auto result =
128+
uninitialized_copy_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end());
129+
assert(int_wrapper::constructions == 3);
130+
assert(int_wrapper::destructions == 0);
131+
assert(result.in == wrapped_input.end());
132+
construct_at(addressof(*result.out), -1); // Need to construct non written element for comparison
133+
assert(++result.out == wrapped_output.end());
134+
assert(equal(wrapped_output, expected_output_long, equal_to{}, &int_wrapper::val));
135+
assert(equal(input, expected_input, equal_to{}, &int_wrapper::val));
136+
destroy(wrapped_output);
137+
assert(int_wrapper::constructions == 4);
138+
assert(int_wrapper::destructions == 4);
139+
}
102140
}
103141
};
104142

@@ -127,17 +165,39 @@ struct throwing_test {
127165
};
128166

129167
struct memcopy_test {
130-
static constexpr int expected_output[] = {13, 55, 12345, -1};
131-
static constexpr int expected_input[] = {13, 55, 12345, 42};
168+
static constexpr int expected_output[] = {13, 55, 12345, -1};
169+
static constexpr int expected_output_long[] = {13, 55, -1, -1};
170+
static constexpr int expected_input[] = {13, 55, 12345, 42};
171+
static constexpr int expected_input_short[] = {13, 55};
172+
static constexpr int expected_input_long[] = {13, 55, 12345, 42};
132173

133174
static void call() {
134-
// Validate only range overload (one is plenty since they both use the same backend)
135-
int input[] = {13, 55, 12345, 42};
136-
int output[] = {-1, -1, -1, -1};
175+
{ // Validate range overload
176+
int input[] = {13, 55, 12345, 42};
177+
int output[] = {-1, -1, -1, -1};
178+
179+
ranges::uninitialized_copy_n(input, 3, begin(output), end(output));
180+
assert(ranges::equal(input, expected_input));
181+
assert(ranges::equal(output, expected_output));
182+
}
183+
184+
{ // Validate shorter input
185+
int input[] = {13, 55};
186+
int output[] = {-1, -1, -1, -1};
137187

138-
ranges::uninitialized_copy_n(input, 3, output, output + 4);
139-
assert(ranges::equal(input, expected_input));
140-
assert(ranges::equal(output, expected_output));
188+
ranges::uninitialized_copy_n(input, 2, begin(output), end(output));
189+
assert(ranges::equal(input, expected_input_short));
190+
assert(ranges::equal(output, expected_output_long));
191+
}
192+
193+
{ // Validate shorter output
194+
int input[] = {13, 55, 12345, 42};
195+
int output[] = {-1, -1};
196+
197+
ranges::uninitialized_copy_n(input, 3, begin(output), end(output));
198+
assert(ranges::equal(input, expected_input));
199+
assert(ranges::equal(output, expected_input_short));
200+
}
141201
}
142202
};
143203

0 commit comments

Comments
 (0)