diff --git a/stl/inc/queue b/stl/inc/queue index 787587336e5..e0583c98db7 100644 --- a/stl/inc/queue +++ b/stl/inc/queue @@ -38,6 +38,12 @@ public: explicit queue(_Container&& _Cont) noexcept(is_nothrow_move_constructible_v<_Container>) // strengthened : c(_STD move(_Cont)) {} +#if _HAS_CXX23 + template , int> = 0> + queue(_InIt _First, _InIt _Last) noexcept(is_nothrow_constructible_v<_Container, _InIt, _InIt>) // strengthened + : c(_STD move(_First), _STD move(_Last)) {} +#endif // _HAS_CXX23 + template , int> = 0> explicit queue(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Container, const _Alloc&>) // strengthened : c(_Al) {} @@ -58,6 +64,14 @@ public: is_nothrow_constructible_v<_Container, _Container, const _Alloc&>) // strengthened : c(_STD move(_Right.c), _Al) {} +#if _HAS_CXX23 + template , uses_allocator<_Container, _Alloc>>, int> = 0> + queue(_InIt _First, _InIt _Last, const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Container, _InIt, _InIt, const _Alloc&>) // strengthened + : c(_STD move(_First), _STD move(_Last), _Al) {} +#endif // _HAS_CXX23 + _NODISCARD bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { return c.empty(); } @@ -126,6 +140,12 @@ template queue; #endif // _HAS_CXX17 +#if _HAS_CXX23 +template >, + enable_if_t, _Is_allocator<_Alloc>>, int> = 0> +queue(_InIt, _InIt, _Alloc = _Alloc()) -> queue<_Iter_value_t<_InIt>, deque<_Iter_value_t<_InIt>, _Alloc>>; +#endif // _HAS_CXX23 + template _NODISCARD bool operator==(const queue<_Ty, _Container>& _Left, const queue<_Ty, _Container>& _Right) { return _Left._Get_container() == _Right._Get_container(); @@ -198,23 +218,23 @@ public: _STD make_heap(c.begin(), c.end(), comp); } - template + template , int> = 0> priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, const _Container& _Cont) : c(_Cont), comp(_Pred) { c.insert(c.end(), _First, _Last); _STD make_heap(c.begin(), c.end(), comp); } - template + template , int> = 0> priority_queue(_InIt _First, _InIt _Last) : c(_First, _Last), comp() { _STD make_heap(c.begin(), c.end(), comp); } - template + template , int> = 0> priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred) : c(_First, _Last), comp(_Pred) { _STD make_heap(c.begin(), c.end(), comp); } - template + template , int> = 0> priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, _Container&& _Cont) : c(_STD move(_Cont)), comp(_Pred) { c.insert(c.end(), _First, _Last); _STD make_heap(c.begin(), c.end(), comp); @@ -249,6 +269,35 @@ public: is_nothrow_move_constructible_v) // strengthened : c(_STD move(_Right.c), _Al), comp(_STD move(_Right.comp)) {} + template && uses_allocator_v<_Container, _Alloc>, int> = 0> + priority_queue(_InIt _First, _InIt _Last, const _Alloc& _Al) : c(_First, _Last, _Al), comp() { + _STD make_heap(c.begin(), c.end(), comp); + } + + template && uses_allocator_v<_Container, _Alloc>, int> = 0> + priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, const _Alloc& _Al) + : c(_First, _Last, _Al), comp(_Pred) { + _STD make_heap(c.begin(), c.end(), comp); + } + + template && uses_allocator_v<_Container, _Alloc>, int> = 0> + priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, const _Container& _Cont, const _Alloc& _Al) + : c(_Cont, _Al), comp(_Pred) { + c.insert(c.end(), _First, _Last); + _STD make_heap(c.begin(), c.end(), comp); + } + + template && uses_allocator_v<_Container, _Alloc>, int> = 0> + priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, _Container&& _Cont, const _Alloc& _Al) + : c(_STD move(_Cont), _Al), comp(_Pred) { + c.insert(c.end(), _First, _Last); + _STD make_heap(c.begin(), c.end(), comp); + } + _NODISCARD bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { return c.empty(); } @@ -309,6 +358,19 @@ template >, int> = 0> priority_queue(_Pr, _Container, _Alloc) -> priority_queue; + +template , _Alloc>, + enable_if_t, _Is_allocator<_Alloc>, uses_allocator<_Container, _Alloc>>, int> = 0> +priority_queue(_Iter, _Iter, _Alloc) -> priority_queue<_Iter_value_t<_Iter>, _Container, less<_Iter_value_t<_Iter>>>; + +template , _Alloc>, + enable_if_t, _Is_allocator<_Alloc>, uses_allocator<_Container, _Alloc>>, int> = 0> +priority_queue(_Iter, _Iter, _Compare, _Alloc) -> priority_queue<_Iter_value_t<_Iter>, _Container, _Compare>; + +template , _Is_allocator<_Alloc>, uses_allocator<_Container, _Alloc>>, int> = 0> +priority_queue(_Iter, _Iter, _Compare, _Container, _Alloc) + -> priority_queue; #endif // _HAS_CXX17 template ) // strengthened : c(_STD move(_Cont)) {} +#if _HAS_CXX23 + template , int> = 0> + stack(_InIt _First, _InIt _Last) noexcept(is_nothrow_constructible_v<_Container, _InIt, _InIt>) // strengthened + : c(_STD move(_First), _STD move(_Last)) {} +#endif // _HAS_CXX23 + template , int> = 0> explicit stack(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Container, const _Alloc&>) // strengthened : c(_Al) {} @@ -56,6 +62,14 @@ public: is_nothrow_constructible_v<_Container, _Container, const _Alloc&>) // strengthened : c(_STD move(_Right.c), _Al) {} +#if _HAS_CXX23 + template , uses_allocator<_Container, _Alloc>>, int> = 0> + stack(_InIt _First, _InIt _Last, const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Container, _InIt, _InIt, const _Alloc&>) // strengthened + : c(_STD move(_First), _STD move(_Last), _Al) {} +#endif // _HAS_CXX23 + _NODISCARD bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { return c.empty(); } @@ -116,6 +130,12 @@ template stack; #endif // _HAS_CXX17 +#if _HAS_CXX23 +template >, + enable_if_t, _Is_allocator<_Alloc>>, int> = 0> +stack(_InIt, _InIt, _Alloc = _Alloc()) -> stack<_Iter_value_t<_InIt>, deque<_Iter_value_t<_InIt>, _Alloc>>; +#endif // _HAS_CXX23 + template _NODISCARD bool operator==(const stack<_Ty, _Container>& _Left, const stack<_Ty, _Container>& _Right) { return _Left._Get_container() == _Right._Get_container(); diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 15342805fc4..9665e76d63f 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -265,6 +265,7 @@ // P0401R6 Providing Size Feedback In The Allocator Interface // P1048R1 is_scoped_enum // P1132R7 out_ptr(), inout_ptr() +// P1425R4 Iterator Pair Constructors For stack And queue // P1679R3 contains() For basic_string/basic_string_view // P1682R3 to_underlying() For Enumerations // P1951R1 Default Template Arguments For pair's Forwarding Constructor @@ -1352,6 +1353,8 @@ // C++23 #if _HAS_CXX23 +#define __cpp_lib_adaptor_iterator_pair_constructor 202106L + #ifdef __cpp_lib_concepts #define __cpp_lib_allocate_at_least 202106L #endif // __cpp_lib_concepts diff --git a/tests/std/test.lst b/tests/std/test.lst index a4dbad8364e..dd989e61b92 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -423,6 +423,7 @@ tests\P1135R6_semaphore tests\P1165R1_consistently_propagating_stateful_allocators tests\P1208R6_source_location tests\P1423R3_char8_t_remediation +tests\P1425R4_queue_stack_constructors tests\P1502R1_standard_library_header_units tests\P1614R2_spaceship tests\P1645R1_constexpr_numeric diff --git a/tests/std/tests/P1425R4_queue_stack_constructors/env.lst b/tests/std/tests/P1425R4_queue_stack_constructors/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/P1425R4_queue_stack_constructors/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/P1425R4_queue_stack_constructors/test.cpp b/tests/std/tests/P1425R4_queue_stack_constructors/test.cpp new file mode 100644 index 00000000000..b2588665e63 --- /dev/null +++ b/tests/std/tests/P1425R4_queue_stack_constructors/test.cpp @@ -0,0 +1,211 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +constexpr int some_data[] = {0, 1, 2, 3, 4, 5}; +constexpr int additional_data[] = {6, 7, 8, 9, 10, 11}; + +template +struct custom_allocator { + using value_type = T; + + custom_allocator() noexcept = default; + template + custom_allocator(const custom_allocator&) noexcept {} + + T* allocate(const size_t n) { + return allocator{}.allocate(n); + } + + void deallocate(T* const p, const size_t n) noexcept { + allocator{}.deallocate(p, n); + } + + template + bool operator==(const custom_allocator&) const noexcept { + return true; + } + +#if !_HAS_CXX20 + template + bool operator!=(const custom_allocator&) const noexcept { + return false; + } +#endif // !_HAS_CXX20 +}; + +template +void test_container() { + Range range{begin(some_data), end(some_data)}; + + int result; +#if _HAS_CXX23 + stack s1(range.begin(), range.end()); + static_assert(is_same_v>>>); + assert(s1.size() == size(some_data)); + result = 5; + while (!s1.empty()) { + assert(s1.top() == result--); + s1.pop(); + } + + stack s2(range.begin(), range.end(), custom_allocator{}); + static_assert(is_same_v>>>); + assert(s2.size() == size(some_data)); + result = 5; + while (!s2.empty()) { + assert(s2.top() == result--); + s2.pop(); + } + + queue q1(range.begin(), range.end()); + static_assert(is_same_v>>>); + assert(q1.size() == size(some_data)); + result = 0; + while (!q1.empty()) { + assert(q1.front() == result++); + q1.pop(); + } + + queue q2(range.begin(), range.end(), custom_allocator{}); + static_assert(is_same_v>>>); + assert(q2.size() == size(some_data)); + result = 0; + while (!q2.empty()) { + assert(q2.front() == result++); + q2.pop(); + } +#endif // _HAS_CXX23 + +#if _HAS_CXX17 + priority_queue pq1(range.begin(), range.end()); + static_assert(is_same_v, less>>); +#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv + priority_queue, less> pq1(range.begin(), range.end()); +#endif // !_HAS_CXX17 + assert(pq1.size() == size(some_data)); + result = 5; + while (!pq1.empty()) { + assert(pq1.top() == result--); + pq1.pop(); + } + +#if _HAS_CXX17 + priority_queue pq2(range.begin(), range.end(), greater{}); + static_assert(is_same_v, greater>>); +#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv + priority_queue, greater> pq2(range.begin(), range.end(), greater{}); +#endif // !_HAS_CXX17 + assert(pq2.size() == size(some_data)); + result = 0; + while (!pq2.empty()) { + assert(pq2.top() == result++); + pq2.pop(); + } + +#if _HAS_CXX17 + priority_queue pq3(range.begin(), range.end(), custom_allocator{}); + static_assert(is_same_v>, less>>); +#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv + priority_queue>, less> pq3( + range.begin(), range.end(), custom_allocator{}); +#endif // !_HAS_CXX17 + assert(pq3.size() == size(some_data)); + result = 5; + while (!pq3.empty()) { + assert(pq3.top() == result--); + pq3.pop(); + } + +#if _HAS_CXX17 + priority_queue pq4(range.begin(), range.end(), greater{}, custom_allocator{}); + static_assert(is_same_v>, greater>>); +#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv + priority_queue>, greater> pq4( + range.begin(), range.end(), greater{}, custom_allocator{}); +#endif // !_HAS_CXX17 + assert(pq4.size() == size(some_data)); + result = 0; + while (!pq4.empty()) { + assert(pq4.top() == result++); + pq4.pop(); + } + + deque cont(begin(additional_data), end(additional_data)); +#if _HAS_CXX17 + priority_queue pq5(range.begin(), range.end(), greater{}, cont); + static_assert(is_same_v, greater>>); +#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv + priority_queue, greater> pq5(range.begin(), range.end(), greater{}, cont); +#endif // !_HAS_CXX17 + assert(pq5.size() == size(some_data) + size(additional_data)); + result = 0; + while (!pq5.empty()) { + assert(pq5.top() == result++); + pq5.pop(); + } + +#if _HAS_CXX17 + priority_queue pq6( + range.begin(), range.end(), greater{}, deque{begin(additional_data), end(additional_data)}); + static_assert(is_same_v, greater>>); +#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv + priority_queue, greater> pq6( + range.begin(), range.end(), greater{}, deque{begin(additional_data), end(additional_data)}); +#endif // !_HAS_CXX17 + assert(pq6.size() == size(some_data) + size(additional_data)); + result = 0; + while (!pq6.empty()) { + assert(pq6.top() == result++); + pq6.pop(); + } + + deque> cont2(begin(additional_data), end(additional_data), custom_allocator{}); +#if _HAS_CXX17 + priority_queue pq7(range.begin(), range.end(), greater{}, cont2, custom_allocator{}); + static_assert(is_same_v>, greater>>); +#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv + priority_queue>, greater> pq7( + range.begin(), range.end(), greater{}, cont2, custom_allocator{}); +#endif // !_HAS_CXX17 + assert(pq7.size() == size(some_data) + size(additional_data)); + result = 0; + while (!pq7.empty()) { + assert(pq7.top() == result++); + pq7.pop(); + } + +#if _HAS_CXX17 + priority_queue pq8(range.begin(), range.end(), greater{}, + deque>{begin(additional_data), end(additional_data)}, custom_allocator{}); + static_assert(is_same_v>, greater>>); +#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv + priority_queue>, greater> pq8(range.begin(), range.end(), greater{}, + deque>{begin(additional_data), end(additional_data)}, custom_allocator{}); +#endif // !_HAS_CXX17 + assert(pq8.size() == size(some_data) + size(additional_data)); + result = 0; + while (!pq8.empty()) { + assert(pq8.top() == result++); + pq8.pop(); + } +} + +int main() { + test_container>(); + test_container>(); + test_container>(); + test_container>(); +} diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 7872191f8be..53f55e7ecf3 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -8,6 +8,19 @@ int main() {} // COMPILE-ONLY // LIBRARY FEATURE-TEST MACROS +#if _HAS_CXX23 +#ifndef __cpp_lib_adaptor_iterator_pair_constructor +#error __cpp_lib_adaptor_iterator_pair_constructor is not defined +#elif __cpp_lib_adaptor_iterator_pair_constructor != 202106L +#error __cpp_lib_adaptor_iterator_pair_constructor is not 202106L +#else +STATIC_ASSERT(__cpp_lib_adaptor_iterator_pair_constructor == 202106L); +#endif +#else +#ifdef __cpp_lib_adaptor_iterator_pair_constructor +#error __cpp_lib_adaptor_iterator_pair_constructor is defined +#endif +#endif #ifndef __cpp_lib_addressof_constexpr #error __cpp_lib_addressof_constexpr is not defined