diff --git a/stl/inc/memory b/stl/inc/memory index 279effbcc6b..ae479ece7bb 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -149,7 +149,9 @@ namespace ranges { auto _OFirst = _Get_unwrapped(_STD move(_First2)); const auto _OLast = _Get_unwrapped(_STD move(_Last2)); if constexpr (_Ptr_copy_cat<_It, _Out>::_Really_trivial) { - _OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); + auto _UResult = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); + _IFirst = _UResult.in; + _OFirst = _UResult.out; } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -283,7 +285,9 @@ namespace ranges { auto _OFirst = _Get_unwrapped(_STD move(_First2)); const auto _OLast = _Get_unwrapped(_STD move(_Last2)); if constexpr (_Ptr_move_cat<_It, _Out>::_Really_trivial) { - _OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); + auto _UResult = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); + _IFirst = _UResult.in; + _OFirst = _UResult.out; } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index c3fdd774d14..764b7449716 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1551,6 +1551,18 @@ namespace ranges { && _No_throw_forward_iterator>; // clang-format on + template + in_out_result<_InIt, _OutIt> _Copy_memcpy_common( + _InIt _IFirst, _InIt _ILast, _OutIt _OFirst, _OutIt _OLast) noexcept { + const auto _IFirst_ch = const_cast(reinterpret_cast(_IFirst)); + const auto _ILast_ch = const_cast(reinterpret_cast(_ILast)); + const auto _OFirst_ch = const_cast(reinterpret_cast(_OFirst)); + const auto _OLast_ch = const_cast(reinterpret_cast(_OLast)); + const auto _Count = static_cast((_STD min)(_ILast_ch - _IFirst_ch, _OLast_ch - _OFirst_ch)); + _CSTD memcpy(_OFirst_ch, _IFirst_ch, _Count); + return {reinterpret_cast<_InIt>(_IFirst_ch + _Count), reinterpret_cast<_OutIt>(_OFirst_ch + _Count)}; + } + // ALIAS TEMPLATE uninitialized_move_result template using uninitialized_move_result = in_out_result<_In, _Out>; diff --git a/stl/inc/xutility b/stl/inc/xutility index eb2a04cadf3..66e6cbd227b 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4102,17 +4102,6 @@ _OutIt _Copy_memmove(move_iterator<_InIt> _First, move_iterator<_InIt> _Last, _O return _Copy_memmove(_First.base(), _Last.base(), _Dest); } -template -_OutIt _Copy_memcpy_common(_InIt _IFirst, _InIt _ILast, _OutIt _OFirst, _OutIt _OLast) noexcept { - const auto _IFirst_ch = const_cast(reinterpret_cast(_IFirst)); - const auto _ILast_ch = const_cast(reinterpret_cast(_ILast)); - const auto _OFirst_ch = const_cast(reinterpret_cast(_OFirst)); - const auto _OLast_ch = const_cast(reinterpret_cast(_OLast)); - const auto _Count = static_cast((_STD min)(_ILast_ch - _IFirst_ch, _OLast_ch - _OFirst_ch)); - _CSTD memcpy(_OFirst_ch, _IFirst_ch, _Count); - return reinterpret_cast<_OutIt>(_OFirst_ch + _Count); -} - // VARIABLE TEMPLATE _Is_vb_iterator template _INLINE_VAR constexpr bool _Is_vb_iterator = false; diff --git a/tests/std/tests/P0896R4_ranges_alg_uninitialized_copy/test.cpp b/tests/std/tests/P0896R4_ranges_alg_uninitialized_copy/test.cpp index f2c607162fe..38c0d687d54 100644 --- a/tests/std/tests/P0896R4_ranges_alg_uninitialized_copy/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_uninitialized_copy/test.cpp @@ -76,21 +76,16 @@ struct holder { } }; -template -void not_ranges_destroy(R&& r) { // TRANSITION, ranges::destroy - for (auto& e : r) { - destroy_at(&e); - } -} - struct instantiator { - static constexpr int expected_output[] = {13, 55, 12345}; - static constexpr int expected_input[] = {13, 55, 12345}; + static constexpr int expected_output[] = {13, 55, 12345}; + static constexpr int expected_output_long[] = {13, 55, 12345, -1}; + static constexpr int expected_input[] = {13, 55, 12345}; + static constexpr int expected_input_long[] = {13, 55, 12345, 42}; template static void call() { - using ranges::uninitialized_copy, ranges::uninitialized_copy_result, ranges::equal, ranges::equal_to, - ranges::iterator_t; + using ranges::destroy, ranges::uninitialized_copy, ranges::uninitialized_copy_result, ranges::equal, + ranges::equal_to, ranges::iterator_t; { // Validate range overload int_wrapper input[3] = {13, 55, 12345}; @@ -107,7 +102,7 @@ struct instantiator { assert(result.out == wrapped_output.end()); assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); - not_ranges_destroy(wrapped_output); + destroy(wrapped_output); assert(int_wrapper::constructions == 3); assert(int_wrapper::destructions == 3); } @@ -127,10 +122,51 @@ struct instantiator { assert(result.out == wrapped_output.end()); assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); - not_ranges_destroy(wrapped_output); + destroy(wrapped_output); assert(int_wrapper::constructions == 3); assert(int_wrapper::destructions == 3); } + + { // Validate range overload shorter output + int_wrapper input[4] = {13, 55, 12345, 42}; + R wrapped_input{input}; + holder mem; + W wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + same_as, iterator_t>> auto result = + uninitialized_copy(wrapped_input, wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(++result.in == wrapped_input.end()); + assert(result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input_long, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 3); + } + + { // Validate range overload shorter input + int_wrapper input[3] = {13, 55, 12345}; + R wrapped_input{input}; + holder mem; + W wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + same_as, iterator_t>> auto result = + uninitialized_copy(wrapped_input, wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(result.in == wrapped_input.end()); + construct_at(addressof(*result.out), -1); // Need to construct non written element for comparison + assert(++result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output_long, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 4); + assert(int_wrapper::destructions == 4); + } } }; @@ -160,6 +196,48 @@ struct throwing_test { } }; +struct memcpy_test { + static constexpr int expected_output[] = {13, 55, 12345}; + static constexpr int expected_output_long[] = {13, 55, 12345, -1}; + static constexpr int expected_input[] = {13, 55, 12345}; + static constexpr int expected_input_long[] = {13, 55, 12345, 42}; + + static void call() { + { // Validate only range overload + int input[] = {13, 55, 12345}; + int output[] = {-1, -1, -1}; + + const auto result = ranges::uninitialized_copy(input, output); + assert(result.in == end(input)); + assert(result.out == end(output)); + assert(ranges::equal(input, expected_input)); + assert(ranges::equal(output, expected_output)); + } + + { // Validate input shorter + int input[] = {13, 55, 12345}; + int output[] = {-1, -1, -1, -1}; + + auto result = ranges::uninitialized_copy(input, output); + assert(result.in == end(input)); + assert(++result.out == end(output)); + assert(ranges::equal(input, expected_input)); + assert(ranges::equal(output, expected_output_long)); + } + + { // Validate output shorter + int input[] = {13, 55, 12345, 42}; + int output[] = {-1, -1, -1}; + + auto result = ranges::uninitialized_copy(input, output); + assert(++result.in == end(input)); + assert(result.out == end(output)); + assert(ranges::equal(input, expected_input_long)); + assert(ranges::equal(output, expected_output)); + } + } +}; + template using test_input = test::range; @@ -174,4 +252,5 @@ int main() { instantiator::call, test_output>(); throwing_test::call, test_output>(); throwing_test::call, test_output>(); + memcpy_test::call(); } diff --git a/tests/std/tests/P0896R4_ranges_alg_uninitialized_copy_n/test.cpp b/tests/std/tests/P0896R4_ranges_alg_uninitialized_copy_n/test.cpp index 9e86c952d8d..3096d91b16a 100644 --- a/tests/std/tests/P0896R4_ranges_alg_uninitialized_copy_n/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_uninitialized_copy_n/test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -66,39 +67,77 @@ struct holder { } }; -template -void not_ranges_destroy(R&& r) { // TRANSITION, ranges::destroy - for (auto& e : r) { - destroy_at(&e); - } -} - struct instantiator { - static constexpr int expected_output[] = {13, 55, 12345}; - static constexpr int expected_input[] = {13, 55, 12345}; + static constexpr int expected_output[] = {13, 55, 12345}; + static constexpr int expected_output_long[] = {13, 55, 12345, -1}; + static constexpr int expected_input[] = {13, 55, 12345}; + static constexpr int expected_input_long[] = {13, 55, 12345, 42}; template static void call() { - using ranges::uninitialized_copy_n, ranges::uninitialized_copy_n_result, ranges::equal, ranges::equal_to, - ranges::iterator_t; + using ranges::destroy, ranges::uninitialized_copy_n, ranges::uninitialized_copy_n_result, ranges::equal, + ranges::equal_to, ranges::iterator_t; + + { // Validate equal ranges + int_wrapper input[3] = {13, 55, 12345}; + Read wrapped_input{input}; + holder mem; + Write wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + const same_as, iterator_t>> auto result = + uninitialized_copy_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end()); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(result.in == wrapped_input.end()); + assert(result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 3); + } - int_wrapper input[3] = {13, 55, 12345}; - Read wrapped_input{input}; - holder mem; - Write wrapped_output{mem.as_span()}; + { // Validate shorter output + int_wrapper input[4] = {13, 55, 12345, 42}; + Read wrapped_input{input}; + holder mem; + Write wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + same_as, iterator_t>> auto result = + uninitialized_copy_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end()); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(++result.in == wrapped_input.end()); + assert(result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input_long, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 3); + } - int_wrapper::clear_counts(); - const same_as, iterator_t>> auto result = - uninitialized_copy_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end()); - assert(int_wrapper::constructions == 3); - assert(int_wrapper::destructions == 0); - assert(result.in == wrapped_input.end()); - assert(result.out == wrapped_output.end()); - assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); - assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); - not_ranges_destroy(wrapped_output); - assert(int_wrapper::constructions == 3); - assert(int_wrapper::destructions == 3); + { // Validate shorter input + int_wrapper input[3] = {13, 55, 12345}; + Read wrapped_input{input}; + holder mem; + Write wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + same_as, iterator_t>> auto result = + uninitialized_copy_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end()); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(result.in == wrapped_input.end()); + construct_at(addressof(*result.out), -1); // Need to construct non written element for comparison + assert(++result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output_long, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 4); + assert(int_wrapper::destructions == 4); + } } }; @@ -126,6 +165,53 @@ struct throwing_test { } }; +struct memcpy_test { + static constexpr int expected_output[] = {13, 55, 12345, -1}; + static constexpr int expected_output_long[] = {13, 55, -1, -1}; + static constexpr int expected_input[] = {13, 55, 12345, 42}; + static constexpr int expected_input_short[] = {13, 55}; + static constexpr int expected_input_long[] = {13, 55, 12345, 42}; + + static void call() { + using ranges::uninitialized_copy_n, ranges::uninitialized_copy_n_result, ranges::equal, ranges::iterator_t; + { // Validate range overload + vector input = {13, 55, 12345, 42}; + vector output = {-1, -1, -1, -1}; + + const same_as>, iterator_t>>> auto result = + uninitialized_copy_n(input.begin(), 3, output.begin(), output.end()); + assert(next(result.in) == input.end()); + assert(next(result.out) == output.end()); + assert(equal(input, expected_input)); + assert(equal(output, expected_output)); + } + + { // Validate shorter input + vector input = {13, 55}; + vector output = {-1, -1, -1, -1}; + + const same_as>, iterator_t>>> auto result = + uninitialized_copy_n(input.begin(), 2, output.begin(), output.end()); + assert(result.in == input.end()); + assert(next(result.out, 2) == output.end()); + assert(equal(input, expected_input_short)); + assert(equal(output, expected_output_long)); + } + + { // Validate shorter output + vector input = {13, 55, 12345, 42}; + vector output = {-1, -1}; + + const same_as>, iterator_t>>> auto result = + uninitialized_copy_n(input.begin(), 2, output.begin(), output.end()); + assert(next(result.in, 2) == input.end()); + assert(result.out == output.end()); + assert(equal(input, expected_input)); + assert(equal(output, expected_input_short)); + } + } +}; + template using test_input = test::range; @@ -140,4 +226,5 @@ int main() { instantiator::call, test_output>(); throwing_test::call, test_output>(); throwing_test::call, test_output>(); + memcpy_test::call(); } diff --git a/tests/std/tests/P0896R4_ranges_alg_uninitialized_move/test.cpp b/tests/std/tests/P0896R4_ranges_alg_uninitialized_move/test.cpp index 8be0b1e8de3..865dcffcccf 100644 --- a/tests/std/tests/P0896R4_ranges_alg_uninitialized_move/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_uninitialized_move/test.cpp @@ -78,8 +78,10 @@ struct holder { }; struct instantiator { - static constexpr int expected_output[] = {13, 55, 12345}; - static constexpr int expected_input[] = {-1, -1, -1}; + static constexpr int expected_output[] = {13, 55, 12345}; + static constexpr int expected_output_long[] = {13, 55, 12345, -1}; + static constexpr int expected_input[] = {-1, -1, -1}; + static constexpr int expected_input_long[] = {-1, -1, -1, 42}; template static void call() { @@ -125,6 +127,47 @@ struct instantiator { assert(int_wrapper::constructions == 3); assert(int_wrapper::destructions == 3); } + + { // Validate range overload shorter output + int_wrapper input[4] = {13, 55, 12345, 42}; + R wrapped_input{input}; + holder mem; + W wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + same_as, iterator_t>> auto result = + uninitialized_move(wrapped_input, wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(++result.in == wrapped_input.end()); + assert(result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input_long, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 3); + } + + { // Validate range overload shorter input + int_wrapper input[3] = {13, 55, 12345}; + R wrapped_input{input}; + holder mem; + W wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + same_as, iterator_t>> auto result = + uninitialized_move(wrapped_input, wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(result.in == wrapped_input.end()); + construct_at(addressof(*result.out), -1); // Need to construct non written element for comparison + assert(++result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output_long, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 4); + assert(int_wrapper::destructions == 4); + } } }; @@ -154,6 +197,46 @@ struct throwing_test { } }; +struct memcpy_test { + static constexpr int expected_output[] = {13, 55, 12345}; + static constexpr int expected_output_long[] = {13, 55, 12345, -1}; + static constexpr int expected_input[] = {13, 55, 12345}; + static constexpr int expected_input_long[] = {13, 55, 12345, 42}; + + static void call() { + { // Validate range + int input[] = {13, 55, 12345}; + int output[] = {-1, -1, -1}; + + ranges::uninitialized_move(input, output); + assert(ranges::equal(input, expected_input)); + assert(ranges::equal(output, expected_output)); + } + + { // Validate input shorter + int input[] = {13, 55, 12345}; + int output[] = {-1, -1, -1, -1}; + + auto result = ranges::uninitialized_move(input, output); + assert(result.in == end(input)); + assert(++result.out == end(output)); + assert(ranges::equal(input, expected_input)); + assert(ranges::equal(output, expected_output_long)); + } + + { // Validate output shorter + int input[] = {13, 55, 12345, 42}; + int output[] = {-1, -1, -1}; + + auto result = ranges::uninitialized_move(input, output); + assert(++result.in == end(input)); + assert(result.out == end(output)); + assert(ranges::equal(input, expected_input_long)); + assert(ranges::equal(output, expected_output)); + } + } +}; + template using test_input = test::range; @@ -168,4 +251,5 @@ int main() { instantiator::call, test_output>(); throwing_test::call, test_output>(); throwing_test::call, test_output>(); + memcpy_test::call(); } diff --git a/tests/std/tests/P0896R4_ranges_alg_uninitialized_move_n/test.cpp b/tests/std/tests/P0896R4_ranges_alg_uninitialized_move_n/test.cpp index eef82b952c4..60d6a79c732 100644 --- a/tests/std/tests/P0896R4_ranges_alg_uninitialized_move_n/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_uninitialized_move_n/test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -67,39 +68,76 @@ struct holder { } }; -template -void not_ranges_destroy(R&& r) { // TRANSITION, ranges::destroy - for (auto& e : r) { - destroy_at(&e); - } -} - struct instantiator { - static constexpr int expected_output[] = {13, 55, 12345}; - static constexpr int expected_input[] = {-1, -1, -1}; + static constexpr int expected_output[] = {13, 55, 12345}; + static constexpr int expected_output_long[] = {13, 55, 12345, -1}; + static constexpr int expected_input[] = {-1, -1, -1}; + static constexpr int expected_input_long[] = {-1, -1, -1, 42}; template static void call() { - using ranges::uninitialized_move_n, ranges::uninitialized_move_n_result, ranges::equal, ranges::equal_to, - ranges::iterator_t; + using ranges::destroy, ranges::uninitialized_move_n, ranges::uninitialized_move_n_result, ranges::equal, + ranges::equal_to, ranges::iterator_t; + { // Validate matching ranges + int_wrapper input[3] = {13, 55, 12345}; + Read wrapped_input{input}; + holder mem; + Write wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + const same_as, iterator_t>> auto result = + uninitialized_move_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end()); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(result.in == wrapped_input.end()); + assert(result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 3); + } - int_wrapper input[3] = {13, 55, 12345}; - Read wrapped_input{input}; - holder mem; - Write wrapped_output{mem.as_span()}; + { // Validate shorter output + int_wrapper input[4] = {13, 55, 12345, 42}; + Read wrapped_input{input}; + holder mem; + Write wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + same_as, iterator_t>> auto result = + uninitialized_move_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end()); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(++result.in == wrapped_input.end()); + assert(result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input_long, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 3); + } - int_wrapper::clear_counts(); - const same_as, iterator_t>> auto result = - uninitialized_move_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end()); - assert(int_wrapper::constructions == 3); - assert(int_wrapper::destructions == 0); - assert(result.in == wrapped_input.end()); - assert(result.out == wrapped_output.end()); - assert(equal(wrapped_output, expected_output, equal_to{}, &int_wrapper::val)); - assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); - not_ranges_destroy(wrapped_output); - assert(int_wrapper::constructions == 3); - assert(int_wrapper::destructions == 3); + { // Validate shorter input + int_wrapper input[3] = {13, 55, 12345}; + Read wrapped_input{input}; + holder mem; + Write wrapped_output{mem.as_span()}; + + int_wrapper::clear_counts(); + same_as, iterator_t>> auto result = + uninitialized_move_n(wrapped_input.begin(), 3, wrapped_output.begin(), wrapped_output.end()); + assert(int_wrapper::constructions == 3); + assert(int_wrapper::destructions == 0); + assert(result.in == wrapped_input.end()); + construct_at(addressof(*result.out), -1); // Need to construct non written element for comparison + assert(++result.out == wrapped_output.end()); + assert(equal(wrapped_output, expected_output_long, equal_to{}, &int_wrapper::val)); + assert(equal(input, expected_input, equal_to{}, &int_wrapper::val)); + destroy(wrapped_output); + assert(int_wrapper::constructions == 4); + assert(int_wrapper::destructions == 4); + } } }; @@ -128,6 +166,53 @@ struct throwing_test { } }; +struct memcpy_test { + static constexpr int expected_output[] = {13, 55, 12345, -1}; + static constexpr int expected_output_long[] = {13, 55, -1, -1}; + static constexpr int expected_input[] = {13, 55, 12345, 42}; + static constexpr int expected_input_short[] = {13, 55}; + static constexpr int expected_input_long[] = {13, 55, 12345, 42}; + + static void call() { + using ranges::uninitialized_move_n, ranges::uninitialized_move_n_result, ranges::equal, ranges::iterator_t; + { // Validate range overload + vector input = {13, 55, 12345, 42}; + vector output = {-1, -1, -1, -1}; + + const same_as>, iterator_t>>> auto result = + uninitialized_move_n(input.begin(), 3, output.begin(), output.end()); + assert(next(result.in) == input.end()); + assert(next(result.out) == output.end()); + assert(equal(input, expected_input)); + assert(equal(output, expected_output)); + } + + { // Validate shorter input + vector input = {13, 55}; + vector output = {-1, -1, -1, -1}; + + const same_as>, iterator_t>>> auto result = + uninitialized_move_n(input.begin(), 2, output.begin(), output.end()); + assert(result.in == input.end()); + assert(next(result.out, 2) == output.end()); + assert(equal(input, expected_input_short)); + assert(equal(output, expected_output_long)); + } + + { // Validate shorter output + vector input = {13, 55, 12345, 42}; + vector output = {-1, -1}; + + const same_as>, iterator_t>>> auto result = + uninitialized_move_n(input.begin(), 2, output.begin(), output.end()); + assert(next(result.in, 2) == input.end()); + assert(result.out == output.end()); + assert(equal(input, expected_input)); + assert(equal(output, expected_input_short)); + } + } +}; + template using test_input = test::range; @@ -142,4 +227,5 @@ int main() { instantiator::call, test_output>(); throwing_test::call, test_output>(); throwing_test::call, test_output>(); + memcpy_test::call(); }