-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Open
Labels
enhancementSomething can be improvedSomething can be improved
Description
There's an enormous amount of overlap in implementations of the "same" algorithm in namespaces std and std::ranges. For example, std::copy:
Lines 4119 to 4146 in 2d890fd
| template <class _InIt, class _OutIt> | |
| _CONSTEXPR20 _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { | |
| // copy [_First, _Last) to [_Dest, ...) | |
| // note: _Copy_unchecked has callers other than the copy family | |
| if constexpr (_Ptr_copy_cat<_InIt, _OutIt>::_Trivially_copyable) { | |
| #ifdef __cpp_lib_is_constant_evaluated | |
| if (!_STD is_constant_evaluated()) | |
| #endif // __cpp_lib_is_constant_evaluated | |
| { | |
| return _Copy_memmove(_First, _Last, _Dest); | |
| } | |
| } | |
| for (; _First != _Last; ++_Dest, (void) ++_First) { | |
| *_Dest = *_First; | |
| } | |
| return _Dest; | |
| } | |
| template <class _InIt, class _OutIt> | |
| _CONSTEXPR20 _OutIt copy(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) | |
| _Adl_verify_range(_First, _Last); | |
| const auto _UFirst = _Get_unwrapped(_First); | |
| const auto _ULast = _Get_unwrapped(_Last); | |
| const auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); | |
| _Seek_wrapped(_Dest, _Copy_unchecked(_UFirst, _ULast, _UDest)); | |
| return _Dest; |
vs. ranges::copy:
Lines 1507 to 1547 in 2d890fd
| // VARIABLE ranges::copy | |
| // clang-format off | |
| template <input_iterator _It, sentinel_for<_It> _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; | |
| // clang-format off | |
| template <input_iterator _It, sentinel_for<_It> _Se, weakly_incrementable _Out> | |
| requires indirectly_copyable<_It, _Out> | |
| constexpr copy_result<_It, _Out> operator()(_It _First, _Se _Last, _Out _Result) const { | |
| _Adl_verify_range(_First, _Last); | |
| 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 <input_range _Rng, weakly_incrementable _Out> | |
| requires indirectly_copyable<iterator_t<_Rng>, _Out> | |
| constexpr copy_result<borrowed_iterator_t<_Rng>, _Out> operator()(_Rng&& _Range, _Out _Result) const { | |
| 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 | |
| }; | |
| inline constexpr _Copy_fn copy{_Not_quite_object::_Construct_tag{}}; |
There are substantial differences in the interface, but eventually they boil down to identical or nearly identical loops. It would be nice if we could reduce the total amount of code we must maintain by using a common back-end for such algorithms.
Note that in doing so we absolutely must not regress performance or codesize, and should not regress compile throughput or increase the complexity of the overall code.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementSomething can be improvedSomething can be improved