Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P2387R3 Pipe for user defined range adaptors #2661

Merged
merged 37 commits into from
Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
341aa78
P2387R3 add bind_back
Ukilele Apr 10, 2022
ac7e672
Use cassert instead of assert.h in test. Move tests into extra function
Ukilele Apr 12, 2022
0aa40df
Merge branch 'microsoft:main' into pipe_for_user_defined_range_adaptors
Ukilele Apr 19, 2022
1f390cb
Add std::ranges::range_adaptor_closure as well as tests
Ukilele Apr 21, 2022
17f7b9a
Use strict_concepts_latest_matrix.lst
Ukilele Apr 21, 2022
ccb8f5a
clang-format stl/inc/functional
Ukilele Apr 21, 2022
82d74a5
clang-format yvals_core.h
Ukilele Apr 21, 2022
57026a2
Use correct naming convetions
Ukilele Apr 21, 2022
0a8b75c
Remove superfluous empty line
Ukilele Apr 21, 2022
fe9aaf2
Adopt test for feature_test_macro to increased value of __cpp_lib_ran…
Ukilele Apr 21, 2022
c922228
Add missing const
Ukilele Apr 21, 2022
097bde2
Define value of __cpp_lib_ranges depending on c++20 or c++23 mode
Ukilele Apr 22, 2022
2e16ab5
A function object only requires callable, not invocable
Ukilele Apr 22, 2022
0afb061
Overloads of ref-qualifier & and const&& for operator| composing two …
Ukilele Apr 22, 2022
d1a5c1b
Add __EDG__ workaround to range_adaptor_closure to mimic _Pipe::_Base
Ukilele Apr 22, 2022
55256e4
Let the standard range adaptor closure types inherit from range_adapt…
Ukilele Apr 22, 2022
383ecfa
Remove namespace _Pipe and its content
Ukilele Apr 22, 2022
cbf346a
Rename _StdPipe to _Pipe
Ukilele Apr 22, 2022
c9ac78e
Correct indentation of clang-format on comment
Ukilele Apr 22, 2022
c56d373
clang-format
Ukilele Apr 22, 2022
26d9bc5
Add tests for mixing user defined and standard range adaptor closures
Ukilele Apr 22, 2022
ababc87
Only provide and use range_adaptor_closure when _HAS_CXX23 is defined
Ukilele Apr 22, 2022
a32c71d
Fix typo Base -> _Base
Ukilele Apr 22, 2022
1ba884e
As __cpp_lib_ranges is language mode sensitive, move it to the corres…
Ukilele Apr 22, 2022
b03523e
Merge content of _Pipe_cpp23 into _Pipe
Ukilele Apr 22, 2022
5faa912
Add missing new line
Ukilele Apr 22, 2022
f191335
Add // to overcome clang-format and improve readability
Ukilele Apr 23, 2022
bb1033d
Remove std:: because of using namespace std;
Ukilele Apr 23, 2022
31f5f75
Merge remote-tracking branch 'upstream/main' into pr/Ukilele/2661
strega-nil Jul 14, 2022
3278979
Nicole suggestions
strega-nil Jul 14, 2022
3c88b92
fix formatting
strega-nil Jul 14, 2022
ecd1631
Merge branch 'main' into pipe_for_user_defined_range_adaptors
CaseyCarter Aug 18, 2022
f3cfad7
Derive _As_rvalue_fn from _Range_Adaptor_base
CaseyCarter Aug 18, 2022
42752a1
Rename `_Range_Adaptor_base` => `_Range_adaptor_base`
CaseyCarter Aug 18, 2022
c6206c4
Address review comments
CaseyCarter Aug 19, 2022
32e6cbb
Code review nitpicks: Newline, comment.
StephanTLavavej Aug 20, 2022
2aed2b5
Add `_NODISCARD` to `operator|` overloads.
StephanTLavavej Aug 20, 2022
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
8 changes: 8 additions & 0 deletions stl/debugger/STL.natvis
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,14 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
</Expand>
</Type>

<Type Name="std::_Back_binder&lt;*&gt;">
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
<DisplayString>bind_back({_Mypair}, {_Mypair._Myval2,view(noparens)})</DisplayString>
<Expand>
<Item Name="[f]">_Mypair</Item>
<Item Name="[bound_args]">_Mypair._Myval2</Item>
</Expand>
</Type>


<!-- VC 2015 -->
<Type Name="std::_Mem_fn&lt;*&gt;">
Expand Down
76 changes: 76 additions & 0 deletions stl/inc/functional
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,82 @@ _NODISCARD constexpr auto bind_front(_Fx&& _Func, _Types&&... _Args) {
}
#endif // _HAS_CXX20

#if _HAS_CXX23
template <size_t... _Ix, class _Cv_FD, class _Cv_tuple_TiD, class... _Unbound>
constexpr auto _Call_back_binder(index_sequence<_Ix...>, _Cv_FD&& _Obj, _Cv_tuple_TiD&& _Tpl,
_Unbound&&... _Unbargs) noexcept(noexcept(_STD invoke(_STD forward<_Cv_FD>(_Obj),
_STD forward<_Unbound>(_Unbargs)..., _STD get<_Ix>(_STD forward<_Cv_tuple_TiD>(_Tpl))...)))
-> decltype(_STD invoke(_STD forward<_Cv_FD>(_Obj), _STD forward<_Unbound>(_Unbargs)...,
_STD get<_Ix>(_STD forward<_Cv_tuple_TiD>(_Tpl))...)) {
return _STD invoke(_STD forward<_Cv_FD>(_Obj), _STD forward<_Unbound>(_Unbargs)...,
_STD get<_Ix>(_STD forward<_Cv_tuple_TiD>(_Tpl))...);
}

template <class _Fx, class... _Types>
class _Back_binder { // wrap bound callable object and arguments
private:
using _Seq = index_sequence_for<_Types...>;

_Compressed_pair<_Fx, tuple<_Types...>> _Mypair;

_STL_INTERNAL_STATIC_ASSERT(is_same_v<_Fx, decay_t<_Fx>>);
_STL_INTERNAL_STATIC_ASSERT((is_same_v<_Types, decay_t<_Types>> && ...));

public:
template <class _FxInit, class... _TypesInit,
enable_if_t<sizeof...(_TypesInit) != 0 || !is_same_v<remove_cvref_t<_FxInit>, _Back_binder>, int> = 0>
constexpr explicit _Back_binder(_FxInit&& _Func, _TypesInit&&... _Args)
: _Mypair(_One_then_variadic_args_t{}, _STD forward<_FxInit>(_Func), _STD forward<_TypesInit>(_Args)...) {}

template <class... _Unbound>
constexpr auto operator()(_Unbound&&... _Unbargs) & noexcept(
noexcept(_Call_back_binder(_Seq{}, _Mypair._Get_first(), _Mypair._Myval2, _STD forward<_Unbound>(_Unbargs)...)))
-> decltype(_Call_back_binder(
_Seq{}, _Mypair._Get_first(), _Mypair._Myval2, _STD forward<_Unbound>(_Unbargs)...)) {
return _Call_back_binder(_Seq{}, _Mypair._Get_first(), _Mypair._Myval2, _STD forward<_Unbound>(_Unbargs)...);
}

template <class... _Unbound>
constexpr auto operator()(_Unbound&&... _Unbargs) const& noexcept(
noexcept(_Call_back_binder(_Seq{}, _Mypair._Get_first(), _Mypair._Myval2, _STD forward<_Unbound>(_Unbargs)...)))
-> decltype(_Call_back_binder(
_Seq{}, _Mypair._Get_first(), _Mypair._Myval2, _STD forward<_Unbound>(_Unbargs)...)) {
return _Call_back_binder(_Seq{}, _Mypair._Get_first(), _Mypair._Myval2, _STD forward<_Unbound>(_Unbargs)...);
}

template <class... _Unbound>
constexpr auto operator()(_Unbound&&... _Unbargs) && noexcept(noexcept(_Call_back_binder(
_Seq{}, _STD move(_Mypair._Get_first()), _STD move(_Mypair._Myval2), _STD forward<_Unbound>(_Unbargs)...)))
-> decltype(_Call_back_binder(
_Seq{}, _STD move(_Mypair._Get_first()), _STD move(_Mypair._Myval2), _STD forward<_Unbound>(_Unbargs)...)) {
return _Call_back_binder(
_Seq{}, _STD move(_Mypair._Get_first()), _STD move(_Mypair._Myval2), _STD forward<_Unbound>(_Unbargs)...);
}

template <class... _Unbound>
constexpr auto operator()(_Unbound&&... _Unbargs) const&& noexcept(noexcept(_Call_back_binder(
_Seq{}, _STD move(_Mypair._Get_first()), _STD move(_Mypair._Myval2), _STD forward<_Unbound>(_Unbargs)...)))
-> decltype(_Call_back_binder(
_Seq{}, _STD move(_Mypair._Get_first()), _STD move(_Mypair._Myval2), _STD forward<_Unbound>(_Unbargs)...)) {
return _Call_back_binder(
_Seq{}, _STD move(_Mypair._Get_first()), _STD move(_Mypair._Myval2), _STD forward<_Unbound>(_Unbargs)...);
}
};
template <class _Fx, class... _Types>
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
_NODISCARD constexpr auto bind_back(_Fx&& _Func, _Types&&... _Args) {
static_assert(is_constructible_v<decay_t<_Fx>, _Fx>,
"std::bind_back requires the decayed callable to be constructible from an undecayed callable");
static_assert(
is_move_constructible_v<decay_t<_Fx>>, "std::bind_back requires the decayed callable to be move constructible");
static_assert(conjunction_v<is_constructible<decay_t<_Types>, _Types>...>,
"std::bind_back requires the decayed bound arguments to be constructible from undecayed bound arguments");
static_assert(conjunction_v<is_move_constructible<decay_t<_Types>>...>,
"std::bind_back requires the decayed bound arguments to be move constructible");

return _Back_binder<decay_t<_Fx>, decay_t<_Types>...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...);
}
#endif // _HAS_CXX23

#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
template <class _Fty, class _Alloc>
struct uses_allocator<function<_Fty>, _Alloc> : true_type {}; // true_type if container allocator enabled
Expand Down
156 changes: 67 additions & 89 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -61,108 +61,80 @@ namespace ranges {
using _Maybe_wrapped = conditional_t<_IsWrapped, _Ty, _Unwrapped_t<_Ty>>;

namespace _Pipe {
// clang-format off
template <class _Left, class _Right>
concept _Can_pipe = requires(_Left&& __l, _Right&& __r) {
static_cast<_Right&&>(__r)(static_cast<_Left&&>(__l));
};

template <class _Left, class _Right>
concept _Can_compose = constructible_from<remove_cvref_t<_Left>, _Left>
&& constructible_from<remove_cvref_t<_Right>, _Right>;
// clang-format on

template <class, class>
struct _Pipeline;

template <class _Derived>
struct _Base {
template <class _Other>
requires _Can_compose<_Derived, _Other>
constexpr auto operator|(_Base<_Other>&& __r) && noexcept(
noexcept(_Pipeline{static_cast<_Derived&&>(*this), static_cast<_Other&&>(__r)})) {
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>);
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>);
return _Pipeline{static_cast<_Derived&&>(*this), static_cast<_Other&&>(__r)};
}

template <class _Other>
requires _Can_compose<_Derived, const _Other&>
constexpr auto operator|(const _Base<_Other>& __r) && noexcept(
noexcept(_Pipeline{static_cast<_Derived&&>(*this), static_cast<const _Other&>(__r)})) {
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>);
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>);
return _Pipeline{static_cast<_Derived&&>(*this), static_cast<const _Other&>(__r)};
}

template <class _Other>
requires _Can_compose<const _Derived&, _Other>
constexpr auto operator|(_Base<_Other>&& __r) const& noexcept(
noexcept(_Pipeline{static_cast<const _Derived&>(*this), static_cast<_Other&&>(__r)})) {
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>);
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>);
return _Pipeline{static_cast<const _Derived&>(*this), static_cast<_Other&&>(__r)};
}

template <class _Other>
requires _Can_compose<const _Derived&, const _Other&>
constexpr auto operator|(const _Base<_Other>& __r) const& noexcept(
noexcept(_Pipeline{static_cast<const _Derived&>(*this), static_cast<const _Other&>(__r)})) {
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>);
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>);
return _Pipeline{static_cast<const _Derived&>(*this), static_cast<const _Other&>(__r)};
}

template <_Can_pipe<const _Derived&> _Left>
friend constexpr auto operator|(_Left&& __l, const _Base& __r)
#ifdef __EDG__ // TRANSITION, VSO-1222776
noexcept(noexcept(_STD declval<const _Derived&>()(_STD forward<_Left>(__l))))
#else // ^^^ workaround / no workaround vvv
noexcept(noexcept(static_cast<const _Derived&>(__r)(_STD forward<_Left>(__l))))
#endif // TRANSITION, VSO-1222776
{
return static_cast<const _Derived&>(__r)(_STD forward<_Left>(__l));
}
struct _Base {};

template <_Can_pipe<_Derived> _Left>
friend constexpr auto operator|(_Left&& __l, _Base&& __r)
#ifdef __EDG__ // TRANSITION, VSO-1222776
noexcept(noexcept(_STD declval<_Derived>()(_STD forward<_Left>(__l))))
#else // ^^^ workaround / no workaround vvv
noexcept(noexcept(static_cast<_Derived&&>(__r)(_STD forward<_Left>(__l))))
#endif // TRANSITION, VSO-1222776
{
return static_cast<_Derived&&>(__r)(_STD forward<_Left>(__l));
}
template <class _Ty>
_Ty* _Derived_from_range_adaptor_closure(_Base<_Ty>&); // not defined

template <class _Ty>
concept _Range_adaptor_closure_object = !range<remove_cvref_t<_Ty>> && requires(remove_cvref_t<_Ty> & __t) {
{ _Pipe::_Derived_from_range_adaptor_closure(__t) } -> same_as<remove_cvref_t<_Ty>*>;
};

template <class _Left, class _Right>
struct _Pipeline : _Base<_Pipeline<_Left, _Right>> {
/* [[no_unique_address]] */ _Left __l;
/* [[no_unique_address]] */ _Right __r;
template <class _ClosureLeft, class _ClosureRight>
struct _Pipeline : _Base<_Pipeline<_ClosureLeft, _ClosureRight>> {
_STL_INTERNAL_STATIC_ASSERT(_Range_adaptor_closure_object<_ClosureLeft>);
_STL_INTERNAL_STATIC_ASSERT(_Range_adaptor_closure_object<_ClosureRight>);

/* [[no_unique_address]] */ _ClosureLeft _Left;
/* [[no_unique_address]] */ _ClosureRight _Right;

template <class _Ty1, class _Ty2>
constexpr explicit _Pipeline(_Ty1&& _Val1, _Ty2&& _Val2) noexcept(
is_nothrow_convertible_v<_Ty1, _Left>&& is_nothrow_convertible_v<_Ty2, _Right>)
: __l(_STD forward<_Ty1>(_Val1)), __r(_STD forward<_Ty2>(_Val2)) {}
is_nothrow_constructible_v<_Ty1, _ClosureLeft>&& is_nothrow_constructible_v<_Ty2, _ClosureRight>)
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
: _Left(_STD forward<_Ty1>(_Val1)), _Right(_STD forward<_Ty2>(_Val2)) {}

template <class _Ty>
_NODISCARD constexpr auto operator()(_Ty&& _Val) noexcept(
noexcept(__r(__l(_STD forward<_Ty>(_Val))))) requires requires {
__r(__l(static_cast<_Ty&&>(_Val)));
_NODISCARD constexpr auto operator()(_Ty&& _Val) & noexcept(
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
noexcept(_Right(_Left(_STD forward<_Ty>(_Val))))) requires requires {
_Right(_Left(_STD forward<_Ty>(_Val)));
}
{ return __r(__l(_STD forward<_Ty>(_Val))); }
{ return _Right(_Left(_STD forward<_Ty>(_Val))); }

template <class _Ty>
_NODISCARD constexpr auto operator()(_Ty&& _Val) const
noexcept(noexcept(__r(__l(_STD forward<_Ty>(_Val))))) requires requires {
__r(__l(static_cast<_Ty&&>(_Val)));
_NODISCARD constexpr auto operator()(_Ty&& _Val) const& noexcept(
noexcept(_Right(_Left(_STD forward<_Ty>(_Val))))) requires requires {
_Right(_Left(_STD forward<_Ty>(_Val)));
}
{ return __r(__l(_STD forward<_Ty>(_Val))); }
{ return _Right(_Left(_STD forward<_Ty>(_Val))); }

template <class _Ty>
_NODISCARD constexpr auto operator()(_Ty&& _Val) && noexcept(
noexcept(_STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))))) requires requires {
_STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val)));
}
{ return _STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))); }

template <class _Ty>
_NODISCARD constexpr auto operator()(_Ty&& _Val) const&& noexcept(
noexcept(_STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))))) requires requires {
_STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val)));
}
{ return _STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))); }
};

template <class _Ty1, class _Ty2>
_Pipeline(_Ty1, _Ty2) -> _Pipeline<_Ty1, _Ty2>;

template <class _Left, class _Right>
requires _Range_adaptor_closure_object<_Left> //
&& _Range_adaptor_closure_object<_Right> //
&& constructible_from<remove_cvref_t<_Left>, _Left> //
&& constructible_from<remove_cvref_t<_Right>, _Right>
constexpr auto operator|(_Left&& __l, _Right&& __r) noexcept(
noexcept(_Pipeline{static_cast<_Left&&>(__l), static_cast<_Right&&>(__r)})) {
return _Pipeline{static_cast<_Left&&>(__l), static_cast<_Right&&>(__r)};
}
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

template <class _Left, class _Right>
requires _Range_adaptor_closure_object<_Right> && range<_Left>
constexpr auto operator|(_Left&& __l, _Right&& __r) noexcept(
noexcept(_STD forward<_Right>(__r)(_STD forward<_Left>(__l)))) //
requires requires {
static_cast<_Right&&>(__r)(static_cast<_Left&&>(__l));
}
{ return _STD forward<_Right>(__r)(_STD forward<_Left>(__l)); }
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
} // namespace _Pipe

template <range _Rng, class _Derived>
Expand Down Expand Up @@ -805,6 +777,13 @@ namespace ranges {
};
};

#if _HAS_CXX23
template <class _Derived>
requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
class range_adaptor_closure : public _Pipe::_Base<_Derived> {
};
#endif
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

template <class _Fn, class... _Types>
class _Range_closure : public _Pipe::_Base<_Range_closure<_Fn, _Types...>> {
public:
Expand Down Expand Up @@ -4289,7 +4268,6 @@ namespace ranges {
}
}


public:
using iterator_concept = typename _Outer_iter<_Const>::iterator_concept;
using value_type = range_value_t<_BaseTy>;
Expand Down Expand Up @@ -4506,7 +4484,7 @@ namespace ranges {
#else // ^^^ no workaround / workaround vvv
auto _Match = _RANGES search(subrange{_Current, _Last}, _Parent->_Pattern);
auto _Begin = _Match.begin();
auto _End = _Match.end();
auto _End = _Match.end();
#endif // TRANSITION, DevCom-1559808
if (_Begin != _Last && _RANGES empty(_Parent->_Pattern)) {
++_Begin;
Expand Down Expand Up @@ -4558,7 +4536,7 @@ namespace ranges {
#else // ^^^ no workaround / workaround vvv
auto _Match = _RANGES search(subrange{_It, _Last}, _Pattern);
auto _Begin = _Match.begin();
auto _End = _Match.end();
auto _End = _Match.end();
#endif // TRANSITION, DevCom-1559808
if (_Begin != _Last && _RANGES empty(_Pattern)) {
++_Begin;
Expand Down Expand Up @@ -5086,7 +5064,7 @@ namespace ranges {
(void) _Off;
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv
if constexpr (_Offset_verifiable_v<iterator_t<_Base>>) {
_Current._Verify_offset(_Off);
_Current._Verify_offset(_Off);
}
#endif // _ITERATOR_DEBUG_LEVEL == 0
}
Expand Down
14 changes: 10 additions & 4 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@
// P2302R4 ranges::contains, ranges::contains_subrange
// P2321R2 zip
// (changes to pair, tuple, and vector<bool>::reference only)
// P2387R3 Pipe Support For User-Defined Range Adaptors
// P2417R2 More constexpr bitset
// P2440R1 ranges::iota, ranges::shift_left, ranges::shift_right
// P2441R2 views::join_with
Expand Down Expand Up @@ -1459,10 +1460,6 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect

#define __cpp_lib_polymorphic_allocator 201902L

#ifdef __cpp_lib_concepts // TRANSITION, GH-395
#define __cpp_lib_ranges 202110L
#endif // __cpp_lib_concepts

#define __cpp_lib_remove_cvref 201711L
#define __cpp_lib_semaphore 201907L
#define __cpp_lib_smart_ptr_for_overwrite 202002L
Expand Down Expand Up @@ -1495,6 +1492,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
#endif // __cpp_lib_concepts

#define __cpp_lib_associative_heterogeneous_erasure 202110L
#define __cpp_lib_bind_back 202202L
#define __cpp_lib_byteswap 202110L
#define __cpp_lib_constexpr_bitset 202207L
#define __cpp_lib_constexpr_typeinfo 202106L
Expand Down Expand Up @@ -1569,6 +1567,14 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
#define __cpp_lib_optional 201606L // P0307R2 Making Optional Greater Equal Again
#endif // _HAS_CXX17

#if defined(__cpp_lib_concepts) // TRANSITION, GH-395
#if _HAS_CXX23
#define __cpp_lib_ranges 202202L // P2387R3 Pipe Support For User-Defined Range Adaptors
#elif _HAS_CXX20 // ^^^ _HAS_CXX23 / _HAS_CXX20 vvv
#define __cpp_lib_ranges 202110L // P2415R2 What Is A `view`?
#endif // _HAS_CXX20
#endif // defined(__cpp_lib_concepts)

#if _HAS_CXX20
#define __cpp_lib_shared_ptr_arrays 201707L // P0674R1 make_shared() For Arrays
#else // _HAS_CXX20
Expand Down
2 changes: 2 additions & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ tests\P2273R3_constexpr_unique_ptr
tests\P2302R4_ranges_alg_contains
tests\P2302R4_ranges_alg_contains_subrange
tests\P2321R2_proxy_reference
tests\P2387R3_bind_back
tests\P2387R3_pipe_support_for_user_defined_range_adaptors
tests\P2401R0_conditional_noexcept_for_exchange
tests\P2408R5_ranges_iterators_to_classic_algorithms
tests\P2415R2_owning_view
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2387R3_bind_back/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 ..\usual_latest_matrix.lst
Loading