Skip to content

Commit

Permalink
[libc++] priority_queue::displace_top, {flat_,}set::displace, `{v…
Browse files Browse the repository at this point in the history
…ector,deque}::displace_back`
  • Loading branch information
Quuxplusone committed Mar 2, 2023
1 parent 58de28c commit 03d304c
Show file tree
Hide file tree
Showing 11 changed files with 593 additions and 0 deletions.
8 changes: 8 additions & 0 deletions libcxx/include/deque
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,14 @@ public:

_LIBCPP_HIDE_FROM_ABI void pop_front();
_LIBCPP_HIDE_FROM_ABI void pop_back();

_LIBCPP_HIDE_FROM_ABI void displace_back() {
_LIBCPP_ASSERT(!empty(), "deque::displace_back called on an empty deque");
value_type __v = std::move(back());
pop_back();
return __v;
}

_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p);
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l);

Expand Down
10 changes: 10 additions & 0 deletions libcxx/include/flat_set
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,16 @@ public:
return __it;
}

_LIBCPP_HIDE_FROM_ABI
value_type displace(const_iterator __pos) {
auto __guard = std::__make_exception_guard([&] { __restore_invariant(); });
auto __it = __c_.erase(__pos, __pos);
auto __v = std::move(*__it);
__c_.erase(__it);
__guard.__complete();
return __v;
}

_LIBCPP_HIDE_FROM_ABI
void swap(flat_set& __y) noexcept {
using std::swap;
Expand Down
5 changes: 5 additions & 0 deletions libcxx/include/queue
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,11 @@ public:
}
#endif // _LIBCPP_CXX03_LANG

_LIBCPP_HIDE_FROM_ABI value_type displace_top() {
std::pop_heap(c.begin(), c.end(), comp);
return c.displace_back();
}

_LIBCPP_INLINE_VISIBILITY
void swap(priority_queue& __q)
_NOEXCEPT_(__is_nothrow_swappable<container_type>::value &&
Expand Down
16 changes: 16 additions & 0 deletions libcxx/include/set
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,14 @@ public:
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT {__tree_.clear();}

_LIBCPP_HIDE_FROM_ABI
value_type displace(const_iterator __pos) {
_LIBCPP_ASSERT(__pos != end(), "Iterator passed to displace() must be dereferenceable");
value_type __v = std::move(*const_cast<value_type*>(std::addressof(*__pos)));
__tree_.erase(__pos);
return __v;
}

#if _LIBCPP_STD_VER >= 17
_LIBCPP_INLINE_VISIBILITY
insert_return_type insert(node_type&& __nh)
Expand Down Expand Up @@ -1302,6 +1310,14 @@ public:
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT {__tree_.clear();}

_LIBCPP_HIDE_FROM_ABI
value_type displace(const_iterator __pos) {
_LIBCPP_ASSERT(__pos != end(), "Iterator passed to displace() must be dereferenceable");
value_type __v = std::move(*const_cast<value_type*>(std::addressof(*__pos)));
__tree_.erase(__pos);
return __v;
}

#if _LIBCPP_STD_VER >= 17
_LIBCPP_INLINE_VISIBILITY
iterator insert(node_type&& __nh)
Expand Down
38 changes: 38 additions & 0 deletions libcxx/include/vector
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,11 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++
#include <__iterator/wrap_iter.h>
#include <__memory/allocate_at_least.h>
#include <__memory/pointer_traits.h>
#include <__memory/relocate_at.h>
#include <__memory/swap_allocator.h>
#include <__memory/temp_value.h>
#include <__memory/uninitialized_algorithms.h>
#include <__memory/uninitialized_relocate.h>
#include <__memory_resource/polymorphic_allocator.h>
#include <__split_buffer>
#include <__type_traits/is_allocator.h>
Expand Down Expand Up @@ -655,6 +657,42 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last);

_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type displace(const_iterator __pos) {
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__pos)) == this,
"vector::displace(iterator) called with an iterator not referring to this vector");
_LIBCPP_ASSERT(__pos != end(), "vector::displace(iterator) called with a non-dereferenceable iterator");
if (!__libcpp_is_constant_evaluated()) {
pointer __p = __begin_ + (__pos - begin());
value_type __v = std::relocate(std::addressof(*__p));
std::uninitialized_relocate(__p + 1, __end_, __p);
--__end_;
if (!__libcpp_is_constant_evaluated())
__invalidate_iterators_past(__p - 1);
__annotate_shrink(size() + 1);
return __v;
} else {
pointer __p = __begin_ + (__pos - begin());
value_type __v = std::move(*__p);
erase(__pos);
return __v;
}
}

_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type displace_back() {
if (!__libcpp_is_constant_evaluated()) {
value_type __v = std::relocate(std::addressof(back()));
--__end_;
if (!__libcpp_is_constant_evaluated())
__invalidate_iterators_past(__end_ - 1);
__annotate_shrink(size() + 1);
return __v;
} else {
value_type __v = std::move(back());
pop_back();
return __v;
}
}

_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
void clear() _NOEXCEPT
{
Expand Down
105 changes: 105 additions & 0 deletions libcxx/test/std/containers/associative/multiset/displace.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// <set>

// value_type displace(const_iterator position);

#include <functional>
#include <set>
#include <utility>

#include "test_macros.h"
#include "min_allocator.h"
#include "MoveOnly.h"

template<class It>
It Next(It it, int n) {
std::advance(it, n);
return it;
}

int main(int, char**)
{
{
using M = std::multiset<int>;
const int a[] = {1,3,3,4,5,5,8,8};
M m(a, a+8);
assert(m.size() == 8);
ASSERT_SAME_TYPE(decltype(m.displace(m.begin())), int);
ASSERT_SAME_TYPE(decltype(m.displace(m.cbegin())), int);

int v = m.displace(Next(m.cbegin(), 3));
assert(v == 4);
assert(m.size() == 7);
#if TEST_STD_VER >= 11
assert((m == M{1,3,3,5,5,8,8}));
#endif

v = m.displace(m.cbegin());
assert(v == 1);
assert(m.size() == 6);

v = m.displace(Next(m.cbegin(), 5));
assert(v == 8);
assert(m.size() == 5);

v = m.displace(Next(m.cbegin(), 1));
assert(v == 3);
assert(m.size() == 4);
#if TEST_STD_VER >= 11
assert((m == M{3,5,5,8}));
#endif
}
{
using M = std::multiset<int, std::less<int>, min_allocator<int> >;
const int a[] = {1,2,3,4};
M m(a, a+4);
ASSERT_SAME_TYPE(decltype(m.displace(m.begin())), int);
ASSERT_SAME_TYPE(decltype(m.displace(m.cbegin())), int);
int v = m.displace(Next(m.cbegin(), 1));
assert(v == 2);
assert(m.size() == 3);
v = m.displace(Next(m.cbegin(), 1));
assert(v == 3);
assert(m.size() == 2);
v = m.displace(m.cbegin());
assert(v == 1);
assert(m.size() == 1);
v = m.displace(m.cbegin());
assert(v == 4);
assert(m.empty());
}
#if TEST_STD_VER >= 11
{
// Verify that it works with move-only types (its raison d'etre).
using M = std::multiset<MoveOnly>;
M m;
for (int i = 1; i <= 8; ++i) {
m.insert(i);
}
assert(m.size() == 8);
ASSERT_SAME_TYPE(decltype(m.displace(m.begin())), MoveOnly);
ASSERT_SAME_TYPE(decltype(m.displace(m.cbegin())), MoveOnly);

MoveOnly v = m.displace(Next(m.cbegin(), 3));
assert(v == 4);

v = m.displace(m.cbegin());
assert(v == 1);

v = m.displace(Next(m.cbegin(), 5));
assert(v == 8);

v = m.displace(Next(m.cbegin(), 1));
assert(v == 3);
assert(m.size() == 4);
}
#endif
return 0;
}
102 changes: 102 additions & 0 deletions libcxx/test/std/containers/associative/set/displace.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// <set>

// value_type displace(const_iterator position);

#include <functional>
#include <set>
#include <utility>

#include "test_macros.h"
#include "min_allocator.h"
#include "MoveOnly.h"

template<class It>
It Next(It it, int n) {
std::advance(it, n);
return it;
}

int main(int, char**)
{
{
using M = std::set<int>;
const int a[] = {1,2,3,4,5,6,7,8};
M m(a, a+8);
assert(m.size() == 8);
ASSERT_SAME_TYPE(decltype(m.displace(m.begin())), int);
ASSERT_SAME_TYPE(decltype(m.displace(m.cbegin())), int);

int v = m.displace(Next(m.cbegin(), 3));
assert(v == 4);
assert(m.size() == 7);
#if TEST_STD_VER >= 11
assert((m == M{1,2,3,5,6,7,8}));
#endif

v = m.displace(m.cbegin());
assert(v == 1);
assert(m.size() == 6);

v = m.displace(Next(m.cbegin(), 5));
assert(v == 8);
assert(m.size() == 5);

v = m.displace(Next(m.cbegin(), 1));
assert(v == 3);
assert(m.size() == 4);
#if TEST_STD_VER >= 11
assert((m == M{2,5,6,7}));
#endif
}
{
using M = std::set<int, std::less<int>, min_allocator<int> >;
const int a[] = {1,2,3,4};
M m(a, a+4);
ASSERT_SAME_TYPE(decltype(m.displace(m.begin())), int);
ASSERT_SAME_TYPE(decltype(m.displace(m.cbegin())), int);
int v = m.displace(Next(m.cbegin(), 1));
assert(v == 2);
v = m.displace(Next(m.cbegin(), 1));
assert(v == 3);
v = m.displace(m.cbegin());
assert(v == 1);
v = m.displace(m.cbegin());
assert(v == 4);
assert(m.empty());
}
#if TEST_STD_VER >= 11
{
// Verify that it works with move-only types (its raison d'etre).
using M = std::set<MoveOnly>;
M m;
for (int i = 1; i <= 8; ++i) {
m.insert(i);
}
assert(m.size() == 8);
ASSERT_SAME_TYPE(decltype(m.displace(m.begin())), MoveOnly);
ASSERT_SAME_TYPE(decltype(m.displace(m.cbegin())), MoveOnly);

MoveOnly v = m.displace(Next(m.cbegin(), 3));
assert(v == 4);

v = m.displace(m.cbegin());
assert(v == 1);

v = m.displace(Next(m.cbegin(), 5));
assert(v == 8);

v = m.displace(Next(m.cbegin(), 1));
assert(v == 3);
assert(m.size() == 4);
}
#endif
return 0;
}
Loading

0 comments on commit 03d304c

Please sign in to comment.