111 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 11// <flat_set>12 13// container_type extract() &&;14 15#include <algorithm>16#include <concepts>17#include <deque>18#include <flat_set>19#include <functional>20#include <vector>21 22#include "MinSequenceContainer.h"23#include "../helpers.h"24#include "test_macros.h"25#include "min_allocator.h"26 27template <class T>28concept CanExtract = requires(T&& t) { std::forward<T>(t).extract(); };29 30static_assert(CanExtract<std::flat_multiset<int>&&>);31static_assert(!CanExtract<std::flat_multiset<int>&>);32static_assert(!CanExtract<std::flat_multiset<int> const&>);33static_assert(!CanExtract<std::flat_multiset<int> const&&>);34 35template <class KeyContainer>36constexpr void test_one() {37 using M = std::flat_multiset<int, std::less<int>, KeyContainer>;38 {39 M m = M({1, 1, 3});40 41 std::same_as<KeyContainer> auto keys = std::move(m).extract();42 43 auto expected_keys = {1, 1, 3};44 assert(std::ranges::equal(keys, expected_keys));45 check_invariant(m);46 LIBCPP_ASSERT(m.empty());47 }48 {49 // was empty50 M m;51 assert(m.empty());52 auto keys = std::move(m).extract();53 assert(keys.empty());54 LIBCPP_ASSERT(m.empty());55 }56}57 58constexpr bool test() {59 test_one<std::vector<int>>();60#ifndef __cpp_lib_constexpr_deque61 if (!TEST_IS_CONSTANT_EVALUATED)62#endif63 test_one<std::deque<int>>();64 test_one<MinSequenceContainer<int>>();65 test_one<std::vector<int, min_allocator<int>>>();66 67 {68 // extracted object maintains invariant if the underlying container does not clear after move69 using M = std::flat_multiset<int, std::less<>, CopyOnlyVector<int>>;70 M m = M({1, 1, 3});71 std::same_as<M::container_type> auto keys = std::move(m).extract();72 assert(keys.size() == 3);73 check_invariant(m);74 LIBCPP_ASSERT(m.empty());75 }76 77 return true;78}79 80void test_exception() {81 {82#ifndef TEST_HAS_NO_EXCEPTIONS83 using KeyContainer = ThrowOnMoveContainer<int>;84 using M = std::flat_multiset<int, std::ranges::less, KeyContainer>;85 86 M m;87 m.emplace(1);88 m.emplace(2);89 try {90 auto c = std::move(m).extract();91 assert(false);92 } catch (int) {93 check_invariant(m);94 // In libc++, we try to erase the key after value emplacement failure.95 // and after erasure failure, we clear the flat_multiset96 LIBCPP_ASSERT(m.size() == 0);97 }98#endif99 }100}101 102int main(int, char**) {103 test();104#if TEST_STD_VER >= 26105 static_assert(test());106#endif107 test_exception();108 109 return 0;110}111