brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.9 KiB · bb41ced Raw
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