Skip to content

Commit

Permalink
Implement P1425 stack and queue constructors
Browse files Browse the repository at this point in the history
Addresses microsoft#1973
  • Loading branch information
miscco committed Jun 9, 2021
1 parent 4c862ee commit f09df86
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 0 deletions.
19 changes: 19 additions & 0 deletions stl/inc/queue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ public:
explicit queue(_Container&& _Cont) noexcept(is_nothrow_move_constructible_v<_Container>) // strengthened
: c(_STD move(_Cont)) {}

#if _HAS_CXX23
template <class _InIt>
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 <class _Alloc, enable_if_t<uses_allocator_v<_Container, _Alloc>, int> = 0>
explicit queue(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Container, const _Alloc&>) // strengthened
: c(_Al) {}
Expand All @@ -59,6 +65,13 @@ public:
is_nothrow_constructible_v<_Container, _Container, const _Alloc&>) // strengthened
: c(_STD move(_Right.c), _Al) {}

#if _HAS_CXX23
template <class _InIt, class _Alloc, enable_if_t<uses_allocator_v<_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();
}
Expand Down Expand Up @@ -173,6 +186,12 @@ void swap(queue<_Ty, _Container>& _Left, queue<_Ty, _Container>& _Right) noexcep
template <class _Ty, class _Container, class _Alloc>
struct uses_allocator<queue<_Ty, _Container>, _Alloc> : uses_allocator<_Container, _Alloc>::type {};

#if _HAS_CXX23
template <class _InIt, class _Alloc = allocator<iter_value_t<_InIt>>,
enable_if_t<conjunction_v<_Is_iterator<_InIt>, _Is_allocator<_Alloc>>, int> = 0>
queue(_InIt, _InIt, _Alloc = _Alloc()) -> queue<iter_value_t<_InIt>, deque<iter_value_t<_InIt>, _Alloc>>;
#endif // _HAS_CXX23

// CLASS TEMPLATE priority_queue
template <class _Ty, class _Container = vector<_Ty>, class _Pr = less<typename _Container::value_type>>
class priority_queue {
Expand Down
19 changes: 19 additions & 0 deletions stl/inc/stack
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public:
explicit stack(_Container&& _Cont) noexcept(is_nothrow_move_constructible_v<_Container>) // strengthened
: c(_STD move(_Cont)) {}

#if _HAS_CXX23
template <class _InIt>
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 <class _Alloc, enable_if_t<uses_allocator_v<_Container, _Alloc>, int> = 0>
explicit stack(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Container, const _Alloc&>) // strengthened
: c(_Al) {}
Expand All @@ -57,6 +63,13 @@ public:
is_nothrow_constructible_v<_Container, _Container, const _Alloc&>) // strengthened
: c(_STD move(_Right.c), _Al) {}

#if _HAS_CXX23
template <class _InIt, class _Alloc, enable_if_t<uses_allocator_v<_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();
}
Expand Down Expand Up @@ -162,6 +175,12 @@ void swap(stack<_Ty, _Container>& _Left, stack<_Ty, _Container>& _Right) noexcep

template <class _Ty, class _Container, class _Alloc>
struct uses_allocator<stack<_Ty, _Container>, _Alloc> : uses_allocator<_Container, _Alloc>::type {};

#if _HAS_CXX23
template <class _InIt, class _Alloc = allocator<iter_value_t<_InIt>>,
enable_if_t<conjunction_v<_Is_iterator<_InIt>, _Is_allocator<_Alloc>>, int> = 0>
stack(_InIt, _InIt, _Alloc = _Alloc()) -> stack<iter_value_t<_InIt>, deque<iter_value_t<_InIt>, _Alloc>>;
#endif // _HAS_CXX23
_STD_END

#pragma pop_macro("new")
Expand Down
3 changes: 3 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@
// P1831R1 Deprecating volatile In The Standard Library
// Other C++20 deprecation warnings

// _HAS_CXX23 directly controls:
// P1425R4 Iterator Pair Constructors For stack And queue

// Parallel Algorithms Notes
// C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms.
// This implementation parallelizes several common algorithm calls, but not all.
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ tests\P1135R6_semaphore
tests\P1165R1_consistently_propagating_stateful_allocators
tests\P1208R6_source_location
tests\P1423R3_char8_t_remediation
tests\P1425R6_queue_stack_constructors
tests\P1502R1_standard_library_header_units
tests\P1614R2_spaceship
tests\P1645R1_constexpr_numeric
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P1425R6_queue_stack_constructors/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
88 changes: 88 additions & 0 deletions tests/std/tests/P1425R6_queue_stack_constructors/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <algorithm>
#include <cassert>
#include <deque>
#include <forward_list>
#include <iostream>
#include <memory>
#include <queue>
#include <set>
#include <stack>
#include <type_traits>
#include <utility>
#include <vector>
using namespace std;

constexpr int some_data[] = {0, 1, 2, 3, 4, 5};

template <typename T>
struct custom_allocator {
using value_type = T;

custom_allocator() noexcept = default;
template <typename U>
custom_allocator(const custom_allocator<U>&) noexcept {}

T* allocate(const size_t n) {
return allocator<T>{}.allocate(n);
}

void deallocate(T* const p, const size_t n) noexcept {
allocator<T>{}.deallocate(p, n);
}

template <class... Args>
void construct(T* const p, Args&&... args) {
construct_at(p, forward<Args>(args)...);
}
};

template <class Range>
void test_container() {
Range range{begin(some_data), end(some_data)};

stack s1(range.begin(), range.end());
static_assert(is_same_v<decltype(s1), stack<int, deque<int, allocator<int>>>>);
assert(s1.size() == size(some_data));
int result = 5;
while (!s1.empty()) {
assert(s1.top() == result--);
s1.pop();
}

stack s2(range.begin(), range.end(), custom_allocator<int>{});
static_assert(is_same_v<decltype(s2), stack<int, deque<int, custom_allocator<int>>>>);
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<decltype(q1), queue<int, deque<int, allocator<int>>>>);
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<int>{});
static_assert(is_same_v<decltype(q2), queue<int, deque<int, custom_allocator<int>>>>);
assert(q2.size() == size(some_data));
result = 0;
while (!q2.empty()) {
assert(q2.front() == result++);
q2.pop();
}
}

int main() {
test_container<deque<int>>();
test_container<forward_list<int>>();
test_container<vector<int>>();
test_container<set<int>>();
}

0 comments on commit f09df86

Please sign in to comment.