diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 59db8eb1959..383890a7a60 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1507,6 +1507,18 @@ namespace ranges { using copy_result = in_out_result<_In, _Out>; // VARIABLE ranges::copy + // clang-format off + template _Se, weakly_incrementable _Out> + requires indirectly_copyable<_It, _Out> + _NODISCARD constexpr copy_result<_It, _Out> _Copy_unchecked(_It _First, const _Se _Last, _Out _Result) { + for (; _First != _Last; ++_First, (void) ++_Result) { + *_Result = *_First; + } + + return {_STD move(_First), _STD move(_Result)}; + } + // clang-format on + class _Copy_fn : private _Not_quite_object { public: using _Not_quite_object::_Not_quite_object; @@ -1516,20 +1528,19 @@ namespace ranges { requires indirectly_copyable<_It, _Out> constexpr copy_result<_It, _Out> operator()(_It _First, _Se _Last, _Out _Result) const { _Adl_verify_range(_First, _Last); - auto _UFirst = _Get_unwrapped(_STD move(_First)); - const auto _ULast = _Get_unwrapped(_STD move(_Last)); - for (; _UFirst != _ULast; ++_UFirst, (void) ++_Result) { - *_Result = *_UFirst; - } - - _Seek_wrapped(_First, _STD move(_UFirst)); - return {_STD move(_First), _STD move(_Result)}; + auto _UResult = _RANGES _Copy_unchecked( + _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _STD move(_Result)); + _Seek_wrapped(_First, _STD move(_UResult.in)); + return {_STD move(_First), _STD move(_UResult.out)}; } template requires indirectly_copyable, _Out> constexpr copy_result, _Out> operator()(_Rng&& _Range, _Out _Result) const { - return (*this)(_RANGES begin(_Range), _RANGES end(_Range), _STD move(_Result)); + auto _First = _RANGES begin(_Range); + auto _UResult = _RANGES _Copy_unchecked(_Get_unwrapped(_STD move(_First)), _Uend(_Range), _STD move(_Result)); + _Seek_wrapped(_First, _STD move(_UResult.in)); + return {_STD move(_First), _STD move(_UResult.out)}; } // clang-format on }; diff --git a/tests/std/tests/P0896R4_ranges_alg_copy/test.cpp b/tests/std/tests/P0896R4_ranges_alg_copy/test.cpp index cb900599857..6fd9130e399 100644 --- a/tests/std/tests/P0896R4_ranges_alg_copy/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_copy/test.cpp @@ -9,51 +9,47 @@ #include -constexpr void smoke_test() { - using ranges::copy, ranges::copy_result, ranges::iterator_t; - using std::same_as; - - // Validate that copy_result aliases in_out_result - STATIC_ASSERT(same_as, ranges::in_out_result>); - - // Validate dangling story - STATIC_ASSERT( - same_as{}, static_cast(nullptr))), copy_result>); - STATIC_ASSERT(same_as{}, static_cast(nullptr))), copy_result>); - - int const input[] = {13, 42, 1729}; - { // Validate range overload - int output[] = {-1, -1, -1}; - auto result = copy(basic_borrowed_range{input}, basic_borrowed_range{output}.begin()); - STATIC_ASSERT(same_as>, iterator_t>>>); - assert(result.in == basic_borrowed_range{input}.end()); - assert(result.out == basic_borrowed_range{output}.end()); - assert(ranges::equal(output, input)); - } - { // Validate iterator + sentinel overload - int output[] = {-1, -1, -1}; - basic_borrowed_range wrapped_input{input}; - auto result = copy(wrapped_input.begin(), wrapped_input.end(), basic_borrowed_range{output}.begin()); - STATIC_ASSERT(same_as>, iterator_t>>>); - assert(result.in == wrapped_input.end()); - assert(result.out == basic_borrowed_range{output}.end()); - assert(ranges::equal(output, input)); - } -} +using namespace std; -int main() { - STATIC_ASSERT((smoke_test(), true)); - smoke_test(); -} +// Validate that copy_result aliases in_out_result +STATIC_ASSERT(same_as, ranges::in_out_result>); + +// Validate dangling story +STATIC_ASSERT(same_as{}, static_cast(nullptr))), + ranges::copy_result>); +STATIC_ASSERT( + same_as{}, static_cast(nullptr))), ranges::copy_result>); struct instantiator { - template - static void call(In&& in = {}, Out out = {}) { - (void) ranges::copy(in, std::move(out)); - (void) ranges::copy(ranges::begin(in), ranges::end(in), std::move(out)); + static constexpr int input[3] = {13, 42, 1729}; + + template > Write> + static constexpr void call() { + using ranges::copy, ranges::copy_result, ranges::iterator_t; + { // Validate iterator + sentinel overload + int output[3] = {-1, -1, -1}; + Read wrapped_input{input}; + + auto result = copy(wrapped_input.begin(), wrapped_input.end(), Write{output}); + STATIC_ASSERT(same_as, Write>>); + assert(result.in == wrapped_input.end()); + assert(result.out.peek() == output + 3); + assert(ranges::equal(output, input)); + } + { // Validate range overload + int output[3] = {-1, -1, -1}; + Read wrapped_input{input}; + + auto result = copy(wrapped_input, Write{output}); + STATIC_ASSERT(same_as, Write>>); + assert(result.in == wrapped_input.end()); + assert(result.out.peek() == output + 3); + assert(ranges::equal(output, input)); + } } }; -template void test_in_write(); +int main() { + STATIC_ASSERT((test_in_write(), true)); + test_in_write(); +}