Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 44 additions & 8 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -1554,8 +1554,9 @@ namespace ranges {
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));
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)};
}
Expand Down Expand Up @@ -1589,6 +1590,39 @@ namespace ranges {
};

inline constexpr _Copy_n_fn copy_n{_Not_quite_object::_Construct_tag{}};

// ALIAS TEMPLATE copy_backward_result
template <class _In, class _Out>
using copy_backward_result = in_out_result<_In, _Out>;

// VARIABLE ranges::copy_backward
class _Copy_backward_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

// clang-format off
template <bidirectional_iterator _It1, sentinel_for<_It1> _Se1, bidirectional_iterator _It2>
requires indirectly_copyable<_It1, _It2>
constexpr copy_backward_result<_It1, _It2> operator()(_It1 _First, _Se1 _Last, _It2 _Result) const {
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_STD move(_First));
auto _ULast = _Get_final_iterator_unwrapped<_It1>(_UFirst, _STD move(_Last));
_Seek_wrapped(_First, _ULast);
_Result = _Copy_backward_unchecked(_STD move(_UFirst), _STD move(_ULast), _STD move(_Result));
return {_STD move(_First), _STD move(_Result)};
}

template <bidirectional_range _Rng, bidirectional_iterator _It>
requires indirectly_copyable<iterator_t<_Rng>, _It>
constexpr copy_backward_result<borrowed_iterator_t<_Rng>, _It> operator()(_Rng&& _Range, _It _Result) const {
auto _ULast = _Get_final_iterator_unwrapped(_Range);
_Result = _Copy_backward_unchecked(_Ubegin(_Range), _ULast, _STD move(_Result));
return {_Rewrap_iterator(_Range, _STD move(_ULast)), _STD move(_Result)};
}
// clang-format on
};

inline constexpr _Copy_backward_fn copy_backward{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts

Expand Down Expand Up @@ -2573,7 +2607,8 @@ namespace ranges {

if constexpr (sized_sentinel_for<_Se, _It>) {
const auto _Dist = _ULast - _UFirst;
auto _UResult = _Search_n_sized(_STD move(_UFirst), _Dist, _Val, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj));
auto _UResult =
_Search_n_sized(_STD move(_UFirst), _Dist, _Val, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj));
return _Rewrap_subrange<subrange<_It>>(_First, _STD move(_UResult));
} else {
auto _UResult = _Search_n_unsized(
Expand All @@ -2584,8 +2619,8 @@ namespace ranges {

template <forward_range _Rng, class _Ty, class _Pr = ranges::equal_to, class _Pj = identity>
requires indirectly_comparable<iterator_t<_Rng>, const _Ty*, _Pr, _Pj>
_NODISCARD constexpr borrowed_subrange_t<_Rng> operator()(
_Rng&& _Range, const range_difference_t<_Rng> _Count, const _Ty& _Val, _Pr _Pred = {}, _Pj _Proj = {}) const {
_NODISCARD constexpr borrowed_subrange_t<_Rng> operator()(_Rng&& _Range, const range_difference_t<_Rng> _Count,
const _Ty& _Val, _Pr _Pred = {}, _Pj _Proj = {}) const {
auto _First = _RANGES begin(_Range);

if (_Count <= 0) {
Expand All @@ -2599,8 +2634,8 @@ namespace ranges {
_Search_n_sized(_Get_unwrapped(_First), _Dist, _Val, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj));
return _Rewrap_subrange<borrowed_subrange_t<_Rng>>(_First, _STD move(_UResult));
} else {
auto _UResult = _Search_n_unsized(_Get_unwrapped(_First), _Uend(_Range), _Val,
_Count, _Pass_fn(_Pred), _Pass_fn(_Proj));
auto _UResult = _Search_n_unsized(
_Get_unwrapped(_First), _Uend(_Range), _Val, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj));
return _Rewrap_subrange<borrowed_subrange_t<_Rng>>(_First, _STD move(_UResult));
}
}
Expand Down Expand Up @@ -4562,7 +4597,8 @@ namespace ranges {
}

// clang-format off
template <forward_range _Rng, class _Pj = identity, indirect_unary_predicate<projected<iterator_t<_Rng>, _Pj>> _Pr>
template <forward_range _Rng, class _Pj = identity,
indirect_unary_predicate<projected<iterator_t<_Rng>, _Pj>> _Pr>
requires permutable<iterator_t<_Rng>>
constexpr borrowed_subrange_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const {
auto _UResult = _Partition_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
Expand Down
29 changes: 17 additions & 12 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -4471,27 +4471,32 @@ _BidIt2 _Copy_backward_memmove(move_iterator<_BidIt1> _First, move_iterator<_Bid

#if _HAS_IF_CONSTEXPR
template <class _BidIt1, class _BidIt2>
_CONSTEXPR20 _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) {
_NODISCARD _CONSTEXPR20 _BidIt2 _Copy_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) {
// copy [_First, _Last) backwards to [..., _Dest)
_Adl_verify_range(_First, _Last);
const auto _UFirst = _Get_unwrapped(_First);
auto _ULast = _Get_unwrapped(_Last);
auto _UDest = _Get_unwrapped_n(_Dest, -_Idl_distance<_BidIt1>(_UFirst, _ULast));
if constexpr (_Ptr_copy_cat<decltype(_ULast), decltype(_UDest)>::_Trivially_copyable) {
if constexpr (_Ptr_copy_cat<_BidIt1, _BidIt2>::_Trivially_copyable) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
_UDest = _Copy_backward_memmove(_UFirst, _ULast, _UDest);
_Seek_wrapped(_Dest, _UDest);
return _Dest;
return _Copy_backward_memmove(_First, _Last, _Dest);
}
}

while (_UFirst != _ULast) {
*--_UDest = *--_ULast;
while (_First != _Last) {
*--_Dest = *--_Last;
}
_Seek_wrapped(_Dest, _UDest);

return _Dest;
}

template <class _BidIt1, class _BidIt2>
_CONSTEXPR20 _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) {
// copy [_First, _Last) backwards 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<_BidIt1>(_UFirst, _ULast));
_Seek_wrapped(_Dest, _Copy_backward_unchecked(_UFirst, _ULast, _UDest));
return _Dest;
}
#else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@
#define _MSVC_KNOWN_SEMANTICS
#endif

// Controls whether the STL uses "if constexpr" internally
// Controls whether the STL uses "if constexpr" internally in C++14 mode
#ifndef _HAS_IF_CONSTEXPR
#ifdef __CUDACC__
#define _HAS_IF_CONSTEXPR 0
Expand Down
98 changes: 74 additions & 24 deletions tests/std/include/range_algorithm_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,26 @@ namespace test {
ptr_ = s.peek();
}
// clang-format on

[[nodiscard]] friend constexpr boolish operator==(sentinel const s, Element* const ptr) noexcept {
return {s.ptr_ == ptr};
}
[[nodiscard]] friend constexpr boolish operator==(Element* const ptr, sentinel const s) noexcept {
return {s.ptr_ == ptr};
}
[[nodiscard]] friend constexpr boolish operator!=(sentinel const s, Element* const ptr) noexcept {
return !(s == ptr);
}
[[nodiscard]] friend constexpr boolish operator!=(Element* const ptr, sentinel const s) noexcept {
return !(s == ptr);
}

[[nodiscard]] friend constexpr ptrdiff_t operator-(sentinel const s, Element* const ptr) noexcept {
return s.ptr_ - ptr;
}
[[nodiscard]] friend constexpr ptrdiff_t operator-(Element* const ptr, sentinel const s) noexcept {
return ptr - s.ptr_;
}
};

// clang-format off
Expand Down Expand Up @@ -188,70 +208,86 @@ namespace test {
// clang-format on

template <class Cat, class Elem>
constexpr boolish operator==(proxy_reference<Cat, Elem> that) const requires CanEq<Element, Elem> {
[[nodiscard]] constexpr boolish operator==(proxy_reference<Cat, Elem> that) const
requires CanEq<Element, Elem> {
return {ref_ == that.peek()};
}
template <class Cat, class Elem>
constexpr boolish operator!=(proxy_reference<Cat, Elem> that) const requires CanNEq<Element, Elem> {
[[nodiscard]] constexpr boolish operator!=(proxy_reference<Cat, Elem> that) const
requires CanNEq<Element, Elem> {
return {ref_ != that.peek()};
}
template <class Cat, class Elem>
constexpr boolish operator<(proxy_reference<Cat, Elem> that) const requires CanLt<Element, Elem> {
[[nodiscard]] constexpr boolish operator<(proxy_reference<Cat, Elem> that) const requires CanLt<Element, Elem> {
return {ref_ < that.peek()};
}
template <class Cat, class Elem>
constexpr boolish operator>(proxy_reference<Cat, Elem> that) const requires CanGt<Element, Elem> {
[[nodiscard]] constexpr boolish operator>(proxy_reference<Cat, Elem> that) const requires CanGt<Element, Elem> {
return {ref_ > that.peek()};
}
template <class Cat, class Elem>
constexpr boolish operator<=(proxy_reference<Cat, Elem> that) const requires CanLtE<Element, Elem> {
[[nodiscard]] constexpr boolish operator<=(proxy_reference<Cat, Elem> that) const
requires CanLtE<Element, Elem> {
return {ref_ <= that.peek()};
}
template <class Cat, class Elem>
constexpr boolish operator>=(proxy_reference<Cat, Elem> that) const requires CanGtE<Element, Elem> {
[[nodiscard]] constexpr boolish operator>=(proxy_reference<Cat, Elem> that) const
requires CanGtE<Element, Elem> {
return {ref_ >= that.peek()};
}

// clang-format off
friend constexpr boolish operator==(proxy_reference r, Value const& val) requires CanEq<Element, Value> {
[[nodiscard]] friend constexpr boolish operator==(proxy_reference r, Value const& val)
requires CanEq<Element, Value> {
return {r.ref_ == val};
}
friend constexpr boolish operator==(Value const& val, proxy_reference r) requires CanEq<Element, Value> {
[[nodiscard]] friend constexpr boolish operator==(Value const& val, proxy_reference r)
requires CanEq<Element, Value> {
return {r.ref_ == val};
}
friend constexpr boolish operator!=(proxy_reference r, Value const& val) requires CanNEq<Element, Value> {
[[nodiscard]] friend constexpr boolish operator!=(proxy_reference r, Value const& val)
requires CanNEq<Element, Value> {
return {r.ref_ != val};
}
friend constexpr boolish operator!=(Value const& val, proxy_reference r) requires CanNEq<Element, Value> {
[[nodiscard]] friend constexpr boolish operator!=(Value const& val, proxy_reference r)
requires CanNEq<Element, Value> {
return {r.ref_ != val};
}
friend constexpr boolish operator<(Value const& val, proxy_reference r) requires CanLt<Value, Element> {
[[nodiscard]] friend constexpr boolish operator<(Value const& val, proxy_reference r)
requires CanLt<Value, Element> {
return {val < r.ref_};
}
friend constexpr boolish operator<(proxy_reference r, Value const& val) requires CanLt<Element, Value> {
[[nodiscard]] friend constexpr boolish operator<(proxy_reference r, Value const& val)
requires CanLt<Element, Value> {
return {r.ref_ < val};
}
friend constexpr boolish operator>(Value const& val, proxy_reference r) requires CanGt<Value, Element> {
[[nodiscard]] friend constexpr boolish operator>(Value const& val, proxy_reference r)
requires CanGt<Value, Element> {
return {val > r.ref_};
}
friend constexpr boolish operator>(proxy_reference r, Value const& val) requires CanGt<Element, Value> {
[[nodiscard]] friend constexpr boolish operator>(proxy_reference r, Value const& val)
requires CanGt<Element, Value> {
return {r.ref_ > val};
}
friend constexpr boolish operator<=(Value const& val, proxy_reference r) requires CanLtE<Value, Element> {
[[nodiscard]] friend constexpr boolish operator<=(Value const& val, proxy_reference r)
requires CanLtE<Value, Element> {
return {val <= r.ref_};
}
friend constexpr boolish operator<=(proxy_reference r, Value const& val) requires CanLtE<Element, Value> {
[[nodiscard]] friend constexpr boolish operator<=(proxy_reference r, Value const& val)
requires CanLtE<Element, Value> {
return {r.ref_ <= val};
}
friend constexpr boolish operator>=(Value const& val, proxy_reference r) requires CanGtE<Value, Element> {
[[nodiscard]] friend constexpr boolish operator>=(Value const& val, proxy_reference r)
requires CanGtE<Value, Element> {
return {val >= r.ref_};
}
friend constexpr boolish operator>=(proxy_reference r, Value const& val) requires CanGtE<Element, Value> {
[[nodiscard]] friend constexpr boolish operator>=(proxy_reference r, Value const& val)
requires CanGtE<Element, Value> {
return {r.ref_ >= val};
}
// clang-format on

constexpr Element& peek() const noexcept {
[[nodiscard]] constexpr Element& peek() const noexcept {
return ref_;
}
};
Expand Down Expand Up @@ -466,7 +502,8 @@ namespace test {
// iterator unwrapping operations:
using _Prevent_inheriting_unwrap = iterator;

using unwrap = iterator<Category, Element, Diff, Eq, Proxy, IsWrapped::no>;
using unwrap = std::conditional_t<derived_from<Category, contiguous>, Element*,
iterator<Category, Element, Diff, Eq, Proxy, IsWrapped::no>>;

[[nodiscard]] constexpr auto _Unwrapped() const& noexcept requires (to_bool(Wrapped) && to_bool(Eq)) {
return unwrap{ptr_};
Expand All @@ -479,11 +516,19 @@ namespace test {
static constexpr bool _Unwrap_when_unverified = true;

constexpr void _Seek_to(unwrap const& i) noexcept requires (to_bool(Wrapped) && to_bool(Eq)) {
ptr_ = i.peek();
if constexpr (at_least<contiguous>) {
ptr_ = i;
} else {
ptr_ = i.peek();
}
}

constexpr void _Seek_to(unwrap&& i) noexcept requires (to_bool(Wrapped)) {
ptr_ = i.peek();
if constexpr (at_least<contiguous>) {
ptr_ = i;
} else {
ptr_ = i.peek();
}
}
};
// clang-format on
Expand Down Expand Up @@ -570,8 +615,8 @@ namespace test {
return elements_.data();
}

using UI = iterator<Category, Element, Diff, Eq, Proxy, IsWrapped::no>;
using US = conditional_t<to_bool(IsCommon), I, sentinel<Element, IsWrapped::no>>;
using UI = typename I::unwrap;
using US = conditional_t<to_bool(IsCommon), UI, sentinel<Element, IsWrapped::no>>;

[[nodiscard]] constexpr UI _Unchecked_begin() const noexcept {
if constexpr (!derived_from<Category, fwd>) {
Expand Down Expand Up @@ -1003,6 +1048,11 @@ constexpr void test_fwd_fwd() {
with_forward_ranges<with_forward_ranges<Instantiator, Element2>, Element1>::call();
}

template <class Instantiator, class Element1, class Element2>
constexpr void test_bidi_bidi() {
with_bidirectional_ranges<with_bidirectional_ranges<Instantiator, Element2>, Element1>::call();
}

template <class Instantiator, class Element1, class Element2>
constexpr void test_in_write() {
with_input_ranges<with_writable_iterators<Instantiator, Element2>, Element1>::call();
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ tests\P0896R4_ranges_alg_all_of
tests\P0896R4_ranges_alg_any_of
tests\P0896R4_ranges_alg_binary_search
tests\P0896R4_ranges_alg_copy
tests\P0896R4_ranges_alg_copy_backward
tests\P0896R4_ranges_alg_copy_if
tests\P0896R4_ranges_alg_copy_n
tests\P0896R4_ranges_alg_count
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_copy_backward/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_matrix.lst
Loading