| /* | 
 |  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | // This implementation is borrowed from Chromium. | 
 |  | 
 | #include "rtc_base/containers/flat_tree.h" | 
 |  | 
 | // Following tests are ported and extended tests from libcpp for std::set. | 
 | // They can be found here: | 
 | // https://github.com/llvm/llvm-project/tree/main/libcxx/test/std/containers/associative/set | 
 | // | 
 | // Not ported tests: | 
 | // * No tests with PrivateConstructor and std::less<> changed to std::less<T> | 
 | //   These tests have to do with C++14 std::less<> | 
 | //   http://en.cppreference.com/w/cpp/utility/functional/less_void | 
 | //   and add support for templated versions of lookup functions. | 
 | //   Because we use same implementation, we figured that it's OK just to check | 
 | //   compilation and this is what we do in flat_set_unittest/flat_map_unittest. | 
 | // * No tests for max_size() | 
 | //   Has to do with allocator support. | 
 | // * No tests with DefaultOnly. | 
 | //   Standard containers allocate each element in the separate node on the heap | 
 | //   and then manipulate these nodes. Flat containers store their elements in | 
 | //   contiguous memory and move them around, type is required to be movable. | 
 | // * No tests for N3644. | 
 | //   This proposal suggests that all default constructed iterators compare | 
 | //   equal. Currently we use std::vector iterators and they don't implement | 
 | //   this. | 
 | // * No tests with min_allocator and no tests counting allocations. | 
 | //   Flat sets currently don't support allocators. | 
 |  | 
 | #include <array> | 
 | #include <deque> | 
 | #include <forward_list> | 
 | #include <functional> | 
 | #include <iterator> | 
 | #include <list> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | #include "rtc_base/containers/identity.h" | 
 | #include "rtc_base/containers/move_only_int.h" | 
 | #include "test/gmock.h" | 
 | #include "test/gtest.h" | 
 |  | 
 | namespace webrtc { | 
 | namespace flat_containers_internal { | 
 | namespace { | 
 |  | 
 | template <class It> | 
 | class InputIterator { | 
 |  public: | 
 |   using iterator_category = std::input_iterator_tag; | 
 |   using value_type = typename std::iterator_traits<It>::value_type; | 
 |   using difference_type = typename std::iterator_traits<It>::difference_type; | 
 |   using pointer = It; | 
 |   using reference = typename std::iterator_traits<It>::reference; | 
 |  | 
 |   InputIterator() : it_() {} | 
 |   explicit InputIterator(It it) : it_(it) {} | 
 |  | 
 |   reference operator*() const { return *it_; } | 
 |   pointer operator->() const { return it_; } | 
 |  | 
 |   InputIterator& operator++() { | 
 |     ++it_; | 
 |     return *this; | 
 |   } | 
 |   InputIterator operator++(int) { | 
 |     InputIterator tmp(*this); | 
 |     ++(*this); | 
 |     return tmp; | 
 |   } | 
 |  | 
 |   friend bool operator==(const InputIterator& lhs, const InputIterator& rhs) { | 
 |     return lhs.it_ == rhs.it_; | 
 |   } | 
 |   friend bool operator!=(const InputIterator& lhs, const InputIterator& rhs) { | 
 |     return !(lhs == rhs); | 
 |   } | 
 |  | 
 |  private: | 
 |   It it_; | 
 | }; | 
 |  | 
 | template <typename It> | 
 | InputIterator<It> MakeInputIterator(It it) { | 
 |   return InputIterator<It>(it); | 
 | } | 
 |  | 
 | class Emplaceable { | 
 |  public: | 
 |   Emplaceable() : Emplaceable(0, 0.0) {} | 
 |   Emplaceable(int i, double d) : int_(i), double_(d) {} | 
 |   Emplaceable(Emplaceable&& other) : int_(other.int_), double_(other.double_) { | 
 |     other.int_ = 0; | 
 |     other.double_ = 0.0; | 
 |   } | 
 |   Emplaceable(const Emplaceable&) = delete; | 
 |   Emplaceable& operator=(const Emplaceable&) = delete; | 
 |  | 
 |   Emplaceable& operator=(Emplaceable&& other) { | 
 |     int_ = other.int_; | 
 |     other.int_ = 0; | 
 |     double_ = other.double_; | 
 |     other.double_ = 0.0; | 
 |     return *this; | 
 |   } | 
 |  | 
 |   friend bool operator==(const Emplaceable& lhs, const Emplaceable& rhs) { | 
 |     return std::tie(lhs.int_, lhs.double_) == std::tie(rhs.int_, rhs.double_); | 
 |   } | 
 |  | 
 |   friend bool operator<(const Emplaceable& lhs, const Emplaceable& rhs) { | 
 |     return std::tie(lhs.int_, lhs.double_) < std::tie(rhs.int_, rhs.double_); | 
 |   } | 
 |  | 
 |  private: | 
 |   int int_; | 
 |   double double_; | 
 | }; | 
 |  | 
 | struct TemplateConstructor { | 
 |   template <typename T> | 
 |   explicit TemplateConstructor(const T&) {} | 
 |  | 
 |   friend bool operator<(const TemplateConstructor&, | 
 |                         const TemplateConstructor&) { | 
 |     return false; | 
 |   } | 
 | }; | 
 |  | 
 | class NonDefaultConstructibleCompare { | 
 |  public: | 
 |   explicit NonDefaultConstructibleCompare(int) {} | 
 |  | 
 |   template <typename T> | 
 |   bool operator()(const T& lhs, const T& rhs) const { | 
 |     return std::less<T>()(lhs, rhs); | 
 |   } | 
 | }; | 
 |  | 
 | template <class PairType> | 
 | struct LessByFirst { | 
 |   bool operator()(const PairType& lhs, const PairType& rhs) const { | 
 |     return lhs.first < rhs.first; | 
 |   } | 
 | }; | 
 |  | 
 | // Common test trees. | 
 | template <typename ContainerT> | 
 | using TypedTree = flat_tree<typename ContainerT::value_type, | 
 |                             identity, | 
 |                             std::less<>, | 
 |                             ContainerT>; | 
 | using IntTree = TypedTree<std::vector<int>>; | 
 | using IntPair = std::pair<int, int>; | 
 | using IntPairTree = | 
 |     flat_tree<IntPair, identity, LessByFirst<IntPair>, std::vector<IntPair>>; | 
 | using MoveOnlyTree = | 
 |     flat_tree<MoveOnlyInt, identity, std::less<>, std::vector<MoveOnlyInt>>; | 
 | using EmplaceableTree = | 
 |     flat_tree<Emplaceable, identity, std::less<>, std::vector<Emplaceable>>; | 
 | using ReversedTree = | 
 |     flat_tree<int, identity, std::greater<int>, std::vector<int>>; | 
 |  | 
 | using TreeWithStrangeCompare = | 
 |     flat_tree<int, identity, NonDefaultConstructibleCompare, std::vector<int>>; | 
 |  | 
 | using ::testing::ElementsAre; | 
 | using ::testing::IsEmpty; | 
 |  | 
 | template <typename T> | 
 | class FlatTreeTest : public testing::Test {}; | 
 | TYPED_TEST_SUITE_P(FlatTreeTest); | 
 |  | 
 | TEST(FlatTree, IsMultipass) { | 
 |   static_assert(!is_multipass<std::istream_iterator<int>>(), | 
 |                 "InputIterator is not multipass"); | 
 |   static_assert(!is_multipass<std::ostream_iterator<int>>(), | 
 |                 "OutputIterator is not multipass"); | 
 |  | 
 |   static_assert(is_multipass<std::forward_list<int>::iterator>(), | 
 |                 "ForwardIterator is multipass"); | 
 |   static_assert(is_multipass<std::list<int>::iterator>(), | 
 |                 "BidirectionalIterator is multipass"); | 
 |   static_assert(is_multipass<std::vector<int>::iterator>(), | 
 |                 "RandomAccessIterator is multipass"); | 
 | } | 
 |  | 
 | // Tests that the compiler generated move operators propagrate noexcept | 
 | // specifiers. | 
 | TEST(FlatTree, NoExcept) { | 
 |   struct MoveThrows { | 
 |     MoveThrows(MoveThrows&&) noexcept(false) {} | 
 |     MoveThrows& operator=(MoveThrows&&) noexcept(false) { return *this; } | 
 |   }; | 
 |  | 
 |   using MoveThrowsTree = | 
 |       flat_tree<MoveThrows, identity, std::less<>, std::array<MoveThrows, 1>>; | 
 |  | 
 |   static_assert(std::is_nothrow_move_constructible<IntTree>::value, | 
 |                 "Error: IntTree is not nothrow move constructible"); | 
 |   static_assert(std::is_nothrow_move_assignable<IntTree>::value, | 
 |                 "Error: IntTree is not nothrow move assignable"); | 
 |  | 
 |   static_assert(!std::is_nothrow_move_constructible<MoveThrowsTree>::value, | 
 |                 "Error: MoveThrowsTree is nothrow move constructible"); | 
 |   static_assert(!std::is_nothrow_move_assignable<MoveThrowsTree>::value, | 
 |                 "Error: MoveThrowsTree is nothrow move assignable"); | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Class. | 
 |  | 
 | // Check that flat_tree and its iterators can be instantiated with an | 
 | // incomplete type. | 
 |  | 
 | TEST(FlatTree, IncompleteType) { | 
 |   struct A { | 
 |     using Tree = flat_tree<A, identity, std::less<A>, std::vector<A>>; | 
 |     int data; | 
 |     Tree set_with_incomplete_type; | 
 |     Tree::iterator it; | 
 |     Tree::const_iterator cit; | 
 |  | 
 |     // We do not declare operator< because clang complains that it's unused. | 
 |   }; | 
 |  | 
 |   A a; | 
 | } | 
 |  | 
 | TEST(FlatTree, Stability) { | 
 |   using Pair = std::pair<int, int>; | 
 |  | 
 |   using Tree = flat_tree<Pair, identity, LessByFirst<Pair>, std::vector<Pair>>; | 
 |  | 
 |   // Constructors are stable. | 
 |   Tree cont({{0, 0}, {1, 0}, {0, 1}, {2, 0}, {0, 2}, {1, 1}}); | 
 |  | 
 |   auto AllOfSecondsAreZero = [&cont] { | 
 |     return absl::c_all_of(cont, | 
 |                           [](const Pair& elem) { return elem.second == 0; }); | 
 |   }; | 
 |  | 
 |   EXPECT_TRUE(AllOfSecondsAreZero()) << "constructor should be stable"; | 
 |  | 
 |   // Should not replace existing. | 
 |   cont.insert(Pair(0, 2)); | 
 |   cont.insert(Pair(1, 2)); | 
 |   cont.insert(Pair(2, 2)); | 
 |  | 
 |   EXPECT_TRUE(AllOfSecondsAreZero()) << "insert should be stable"; | 
 |  | 
 |   cont.insert(Pair(3, 0)); | 
 |   cont.insert(Pair(3, 2)); | 
 |  | 
 |   EXPECT_TRUE(AllOfSecondsAreZero()) << "insert should be stable"; | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Types. | 
 |  | 
 | // key_type | 
 | // key_compare | 
 | // value_type | 
 | // value_compare | 
 | // pointer | 
 | // const_pointer | 
 | // reference | 
 | // const_reference | 
 | // size_type | 
 | // difference_type | 
 | // iterator | 
 | // const_iterator | 
 | // reverse_iterator | 
 | // const_reverse_iterator | 
 |  | 
 | TEST(FlatTree, Types) { | 
 |   // These are guaranteed to be portable. | 
 |   static_assert((std::is_same<int, IntTree::key_type>::value), ""); | 
 |   static_assert((std::is_same<int, IntTree::value_type>::value), ""); | 
 |   static_assert((std::is_same<std::less<>, IntTree::key_compare>::value), ""); | 
 |   static_assert((std::is_same<int&, IntTree::reference>::value), ""); | 
 |   static_assert((std::is_same<const int&, IntTree::const_reference>::value), | 
 |                 ""); | 
 |   static_assert((std::is_same<int*, IntTree::pointer>::value), ""); | 
 |   static_assert((std::is_same<const int*, IntTree::const_pointer>::value), ""); | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Lifetime. | 
 |  | 
 | // flat_tree() | 
 | // flat_tree(const Compare& comp) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, DefaultConstructor) { | 
 |   { | 
 |     TypedTree<TypeParam> cont; | 
 |     EXPECT_THAT(cont, ElementsAre()); | 
 |   } | 
 |  | 
 |   { | 
 |     TreeWithStrangeCompare cont(NonDefaultConstructibleCompare(0)); | 
 |     EXPECT_THAT(cont, ElementsAre()); | 
 |   } | 
 | } | 
 |  | 
 | // flat_tree(const flat_tree& x) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, CopyConstructor) { | 
 |   TypedTree<TypeParam> original({1, 2, 3, 4}); | 
 |   TypedTree<TypeParam> copied(original); | 
 |  | 
 |   EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4)); | 
 |  | 
 |   EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4)); | 
 |   EXPECT_THAT(original, ElementsAre(1, 2, 3, 4)); | 
 |   EXPECT_EQ(original, copied); | 
 | } | 
 |  | 
 | // flat_tree(flat_tree&& x) | 
 |  | 
 | TEST(FlatTree, MoveConstructor) { | 
 |   int input_range[] = {1, 2, 3, 4}; | 
 |  | 
 |   MoveOnlyTree original(std::begin(input_range), std::end(input_range)); | 
 |   MoveOnlyTree moved(std::move(original)); | 
 |  | 
 |   EXPECT_EQ(1U, moved.count(MoveOnlyInt(1))); | 
 |   EXPECT_EQ(1U, moved.count(MoveOnlyInt(2))); | 
 |   EXPECT_EQ(1U, moved.count(MoveOnlyInt(3))); | 
 |   EXPECT_EQ(1U, moved.count(MoveOnlyInt(4))); | 
 | } | 
 |  | 
 | // flat_tree(InputIterator first, | 
 | //           InputIterator last, | 
 | //           const Compare& comp = Compare()) | 
 |  | 
 | TEST(FlatTree, RangeConstructor) { | 
 |   { | 
 |     IntPair input_vals[] = {{1, 1}, {1, 2}, {2, 1}, {2, 2}, {1, 3}, | 
 |                             {2, 3}, {3, 1}, {3, 2}, {3, 3}}; | 
 |  | 
 |     IntPairTree first_of(MakeInputIterator(std::begin(input_vals)), | 
 |                          MakeInputIterator(std::end(input_vals))); | 
 |     EXPECT_THAT(first_of, | 
 |                 ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1))); | 
 |   } | 
 |   { | 
 |     TreeWithStrangeCompare::value_type input_vals[] = {1, 1, 1, 2, 2, | 
 |                                                        2, 3, 3, 3}; | 
 |  | 
 |     TreeWithStrangeCompare cont(MakeInputIterator(std::begin(input_vals)), | 
 |                                 MakeInputIterator(std::end(input_vals)), | 
 |                                 NonDefaultConstructibleCompare(0)); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3)); | 
 |   } | 
 | } | 
 |  | 
 | // flat_tree(const container_type&) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, ContainerCopyConstructor) { | 
 |   TypeParam items = {1, 2, 3, 4}; | 
 |   TypedTree<TypeParam> tree(items); | 
 |  | 
 |   EXPECT_THAT(tree, ElementsAre(1, 2, 3, 4)); | 
 |   EXPECT_THAT(items, ElementsAre(1, 2, 3, 4)); | 
 | } | 
 |  | 
 | // flat_tree(container_type&&) | 
 |  | 
 | TEST(FlatTree, ContainerMoveConstructor) { | 
 |   using Pair = std::pair<int, MoveOnlyInt>; | 
 |  | 
 |   // Construct an unsorted vector with a duplicate item in it. Sorted by the | 
 |   // first item, the second allows us to test for stability. Using a move | 
 |   // only type to ensure the vector is not copied. | 
 |   std::vector<Pair> storage; | 
 |   storage.push_back(Pair(2, MoveOnlyInt(0))); | 
 |   storage.push_back(Pair(1, MoveOnlyInt(0))); | 
 |   storage.push_back(Pair(2, MoveOnlyInt(1))); | 
 |  | 
 |   using Tree = flat_tree<Pair, identity, LessByFirst<Pair>, std::vector<Pair>>; | 
 |   Tree tree(std::move(storage)); | 
 |  | 
 |   // The list should be two items long, with only the first "2" saved. | 
 |   ASSERT_EQ(2u, tree.size()); | 
 |   const Pair& zeroth = *tree.begin(); | 
 |   ASSERT_EQ(1, zeroth.first); | 
 |   ASSERT_EQ(0, zeroth.second.data()); | 
 |  | 
 |   const Pair& first = *(tree.begin() + 1); | 
 |   ASSERT_EQ(2, first.first); | 
 |   ASSERT_EQ(0, first.second.data()); | 
 | } | 
 |  | 
 | // flat_tree(std::initializer_list<value_type> ilist, | 
 | //           const Compare& comp = Compare()) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, InitializerListConstructor) { | 
 |   { | 
 |     TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 10, 8}); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); | 
 |   } | 
 |   { | 
 |     TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 10, 8}); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); | 
 |   } | 
 |   { | 
 |     TreeWithStrangeCompare cont({1, 2, 3, 4, 5, 6, 10, 8}, | 
 |                                 NonDefaultConstructibleCompare(0)); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); | 
 |   } | 
 |   { | 
 |     IntPairTree first_of({{1, 1}, {2, 1}, {1, 2}}); | 
 |     EXPECT_THAT(first_of, ElementsAre(IntPair(1, 1), IntPair(2, 1))); | 
 |   } | 
 | } | 
 |  | 
 | // flat_tree(sorted_unique_t, | 
 | //           InputIterator first, | 
 | //           InputIterator last, | 
 | //           const Compare& comp = Compare()) | 
 |  | 
 | TEST(FlatTree, SortedUniqueRangeConstructor) { | 
 |   { | 
 |     IntPair input_vals[] = {{1, 1}, {2, 1}, {3, 1}}; | 
 |  | 
 |     IntPairTree first_of(sorted_unique, | 
 |                          MakeInputIterator(std::begin(input_vals)), | 
 |                          MakeInputIterator(std::end(input_vals))); | 
 |     EXPECT_THAT(first_of, | 
 |                 ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1))); | 
 |   } | 
 |   { | 
 |     TreeWithStrangeCompare::value_type input_vals[] = {1, 2, 3}; | 
 |  | 
 |     TreeWithStrangeCompare cont(sorted_unique, | 
 |                                 MakeInputIterator(std::begin(input_vals)), | 
 |                                 MakeInputIterator(std::end(input_vals)), | 
 |                                 NonDefaultConstructibleCompare(0)); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3)); | 
 |   } | 
 | } | 
 |  | 
 | // flat_tree(sorted_unique_t, const container_type&) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, SortedUniqueContainerCopyConstructor) { | 
 |   TypeParam items = {1, 2, 3, 4}; | 
 |   TypedTree<TypeParam> tree(sorted_unique, items); | 
 |  | 
 |   EXPECT_THAT(tree, ElementsAre(1, 2, 3, 4)); | 
 |   EXPECT_THAT(items, ElementsAre(1, 2, 3, 4)); | 
 | } | 
 |  | 
 | // flat_tree(sorted_unique_t, std::vector<value_type>&&) | 
 |  | 
 | TEST(FlatTree, SortedUniqueVectorMoveConstructor) { | 
 |   using Pair = std::pair<int, MoveOnlyInt>; | 
 |  | 
 |   std::vector<Pair> storage; | 
 |   storage.push_back(Pair(1, MoveOnlyInt(0))); | 
 |   storage.push_back(Pair(2, MoveOnlyInt(0))); | 
 |  | 
 |   using Tree = flat_tree<Pair, identity, LessByFirst<Pair>, std::vector<Pair>>; | 
 |   Tree tree(sorted_unique, std::move(storage)); | 
 |  | 
 |   ASSERT_EQ(2u, tree.size()); | 
 |   const Pair& zeroth = *tree.begin(); | 
 |   ASSERT_EQ(1, zeroth.first); | 
 |   ASSERT_EQ(0, zeroth.second.data()); | 
 |  | 
 |   const Pair& first = *(tree.begin() + 1); | 
 |   ASSERT_EQ(2, first.first); | 
 |   ASSERT_EQ(0, first.second.data()); | 
 | } | 
 |  | 
 | // flat_tree(sorted_unique_t, | 
 | //           std::initializer_list<value_type> ilist, | 
 | //           const Compare& comp = Compare()) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, SortedUniqueInitializerListConstructor) { | 
 |   { | 
 |     TypedTree<TypeParam> cont(sorted_unique, {1, 2, 3, 4, 5, 6, 8, 10}); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); | 
 |   } | 
 |   { | 
 |     TypedTree<TypeParam> cont(sorted_unique, {1, 2, 3, 4, 5, 6, 8, 10}); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); | 
 |   } | 
 |   { | 
 |     TreeWithStrangeCompare cont(sorted_unique, {1, 2, 3, 4, 5, 6, 8, 10}, | 
 |                                 NonDefaultConstructibleCompare(0)); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); | 
 |   } | 
 |   { | 
 |     IntPairTree first_of(sorted_unique, {{1, 1}, {2, 1}}); | 
 |     EXPECT_THAT(first_of, ElementsAre(IntPair(1, 1), IntPair(2, 1))); | 
 |   } | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Assignments. | 
 |  | 
 | // flat_tree& operator=(const flat_tree&) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, CopyAssignable) { | 
 |   TypedTree<TypeParam> original({1, 2, 3, 4}); | 
 |   TypedTree<TypeParam> copied; | 
 |   copied = original; | 
 |  | 
 |   EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4)); | 
 |   EXPECT_THAT(original, ElementsAre(1, 2, 3, 4)); | 
 |   EXPECT_EQ(original, copied); | 
 | } | 
 |  | 
 | // flat_tree& operator=(flat_tree&&) | 
 |  | 
 | TEST(FlatTree, MoveAssignable) { | 
 |   int input_range[] = {1, 2, 3, 4}; | 
 |  | 
 |   MoveOnlyTree original(std::begin(input_range), std::end(input_range)); | 
 |   MoveOnlyTree moved; | 
 |   moved = std::move(original); | 
 |  | 
 |   EXPECT_EQ(1U, moved.count(MoveOnlyInt(1))); | 
 |   EXPECT_EQ(1U, moved.count(MoveOnlyInt(2))); | 
 |   EXPECT_EQ(1U, moved.count(MoveOnlyInt(3))); | 
 |   EXPECT_EQ(1U, moved.count(MoveOnlyInt(4))); | 
 | } | 
 |  | 
 | // flat_tree& operator=(std::initializer_list<value_type> ilist) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, InitializerListAssignable) { | 
 |   TypedTree<TypeParam> cont({0}); | 
 |   cont = {1, 2, 3, 4, 5, 6, 10, 8}; | 
 |  | 
 |   EXPECT_EQ(0U, cont.count(0)); | 
 |   EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); | 
 | } | 
 |  | 
 | // -------------------------------------------------------------------------- | 
 | // Memory management. | 
 |  | 
 | // void reserve(size_type new_capacity) | 
 |  | 
 | TEST(FlatTreeTest, Reserve) { | 
 |   IntTree cont({1, 2, 3}); | 
 |  | 
 |   cont.reserve(5); | 
 |   EXPECT_LE(5U, cont.capacity()); | 
 | } | 
 |  | 
 | // size_type capacity() const | 
 |  | 
 | TEST(FlatTreeTest, Capacity) { | 
 |   IntTree cont({1, 2, 3}); | 
 |  | 
 |   EXPECT_LE(cont.size(), cont.capacity()); | 
 |   cont.reserve(5); | 
 |   EXPECT_LE(cont.size(), cont.capacity()); | 
 | } | 
 |  | 
 | // void shrink_to_fit() | 
 |  | 
 | TEST(FlatTreeTest, ShrinkToFit) { | 
 |   IntTree cont({1, 2, 3}); | 
 |  | 
 |   IntTree::size_type capacity_before = cont.capacity(); | 
 |   cont.shrink_to_fit(); | 
 |   EXPECT_GE(capacity_before, cont.capacity()); | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Size management. | 
 |  | 
 | // void clear() | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Clear) { | 
 |   TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); | 
 |   cont.clear(); | 
 |   EXPECT_THAT(cont, ElementsAre()); | 
 | } | 
 |  | 
 | // size_type size() const | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Size) { | 
 |   TypedTree<TypeParam> cont; | 
 |  | 
 |   EXPECT_EQ(0U, cont.size()); | 
 |   cont.insert(2); | 
 |   EXPECT_EQ(1U, cont.size()); | 
 |   cont.insert(1); | 
 |   EXPECT_EQ(2U, cont.size()); | 
 |   cont.insert(3); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   cont.erase(cont.begin()); | 
 |   EXPECT_EQ(2U, cont.size()); | 
 |   cont.erase(cont.begin()); | 
 |   EXPECT_EQ(1U, cont.size()); | 
 |   cont.erase(cont.begin()); | 
 |   EXPECT_EQ(0U, cont.size()); | 
 | } | 
 |  | 
 | // bool empty() const | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Empty) { | 
 |   TypedTree<TypeParam> cont; | 
 |  | 
 |   EXPECT_TRUE(cont.empty()); | 
 |   cont.insert(1); | 
 |   EXPECT_FALSE(cont.empty()); | 
 |   cont.clear(); | 
 |   EXPECT_TRUE(cont.empty()); | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Iterators. | 
 |  | 
 | // iterator begin() | 
 | // const_iterator begin() const | 
 | // iterator end() | 
 | // const_iterator end() const | 
 | // | 
 | // reverse_iterator rbegin() | 
 | // const_reverse_iterator rbegin() const | 
 | // reverse_iterator rend() | 
 | // const_reverse_iterator rend() const | 
 | // | 
 | // const_iterator cbegin() const | 
 | // const_iterator cend() const | 
 | // const_reverse_iterator crbegin() const | 
 | // const_reverse_iterator crend() const | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Iterators) { | 
 |   TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); | 
 |  | 
 |   auto size = | 
 |       static_cast<typename TypedTree<TypeParam>::difference_type>(cont.size()); | 
 |  | 
 |   EXPECT_EQ(size, std::distance(cont.begin(), cont.end())); | 
 |   EXPECT_EQ(size, std::distance(cont.cbegin(), cont.cend())); | 
 |   EXPECT_EQ(size, std::distance(cont.rbegin(), cont.rend())); | 
 |   EXPECT_EQ(size, std::distance(cont.crbegin(), cont.crend())); | 
 |  | 
 |   { | 
 |     auto it = cont.begin(); | 
 |     auto c_it = cont.cbegin(); | 
 |     EXPECT_EQ(it, c_it); | 
 |     for (int j = 1; it != cont.end(); ++it, ++c_it, ++j) { | 
 |       EXPECT_EQ(j, *it); | 
 |       EXPECT_EQ(j, *c_it); | 
 |     } | 
 |   } | 
 |   { | 
 |     auto rit = cont.rbegin(); | 
 |     auto c_rit = cont.crbegin(); | 
 |     EXPECT_EQ(rit, c_rit); | 
 |     for (int j = static_cast<int>(size); rit != cont.rend(); | 
 |          ++rit, ++c_rit, --j) { | 
 |       EXPECT_EQ(j, *rit); | 
 |       EXPECT_EQ(j, *c_rit); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Insert operations. | 
 |  | 
 | // pair<iterator, bool> insert(const value_type& val) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, InsertLValue) { | 
 |   TypedTree<TypeParam> cont; | 
 |  | 
 |   int value = 2; | 
 |   std::pair<typename TypedTree<TypeParam>::iterator, bool> result = | 
 |       cont.insert(value); | 
 |   EXPECT_TRUE(result.second); | 
 |   EXPECT_EQ(cont.begin(), result.first); | 
 |   EXPECT_EQ(1U, cont.size()); | 
 |   EXPECT_EQ(2, *result.first); | 
 |  | 
 |   value = 1; | 
 |   result = cont.insert(value); | 
 |   EXPECT_TRUE(result.second); | 
 |   EXPECT_EQ(cont.begin(), result.first); | 
 |   EXPECT_EQ(2U, cont.size()); | 
 |   EXPECT_EQ(1, *result.first); | 
 |  | 
 |   value = 3; | 
 |   result = cont.insert(value); | 
 |   EXPECT_TRUE(result.second); | 
 |   EXPECT_EQ(std::prev(cont.end()), result.first); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   EXPECT_EQ(3, *result.first); | 
 |  | 
 |   value = 3; | 
 |   result = cont.insert(value); | 
 |   EXPECT_FALSE(result.second); | 
 |   EXPECT_EQ(std::prev(cont.end()), result.first); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   EXPECT_EQ(3, *result.first); | 
 | } | 
 |  | 
 | // pair<iterator, bool> insert(value_type&& val) | 
 |  | 
 | TEST(FlatTree, InsertRValue) { | 
 |   MoveOnlyTree cont; | 
 |  | 
 |   std::pair<MoveOnlyTree::iterator, bool> result = cont.insert(MoveOnlyInt(2)); | 
 |   EXPECT_TRUE(result.second); | 
 |   EXPECT_EQ(cont.begin(), result.first); | 
 |   EXPECT_EQ(1U, cont.size()); | 
 |   EXPECT_EQ(2, result.first->data()); | 
 |  | 
 |   result = cont.insert(MoveOnlyInt(1)); | 
 |   EXPECT_TRUE(result.second); | 
 |   EXPECT_EQ(cont.begin(), result.first); | 
 |   EXPECT_EQ(2U, cont.size()); | 
 |   EXPECT_EQ(1, result.first->data()); | 
 |  | 
 |   result = cont.insert(MoveOnlyInt(3)); | 
 |   EXPECT_TRUE(result.second); | 
 |   EXPECT_EQ(std::prev(cont.end()), result.first); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   EXPECT_EQ(3, result.first->data()); | 
 |  | 
 |   result = cont.insert(MoveOnlyInt(3)); | 
 |   EXPECT_FALSE(result.second); | 
 |   EXPECT_EQ(std::prev(cont.end()), result.first); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   EXPECT_EQ(3, result.first->data()); | 
 | } | 
 |  | 
 | // iterator insert(const_iterator position_hint, const value_type& val) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, InsertPositionLValue) { | 
 |   TypedTree<TypeParam> cont; | 
 |  | 
 |   auto result = cont.insert(cont.cend(), 2); | 
 |   EXPECT_EQ(cont.begin(), result); | 
 |   EXPECT_EQ(1U, cont.size()); | 
 |   EXPECT_EQ(2, *result); | 
 |  | 
 |   result = cont.insert(cont.cend(), 1); | 
 |   EXPECT_EQ(cont.begin(), result); | 
 |   EXPECT_EQ(2U, cont.size()); | 
 |   EXPECT_EQ(1, *result); | 
 |  | 
 |   result = cont.insert(cont.cend(), 3); | 
 |   EXPECT_EQ(std::prev(cont.end()), result); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   EXPECT_EQ(3, *result); | 
 |  | 
 |   result = cont.insert(cont.cend(), 3); | 
 |   EXPECT_EQ(std::prev(cont.end()), result); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   EXPECT_EQ(3, *result); | 
 | } | 
 |  | 
 | // iterator insert(const_iterator position_hint, value_type&& val) | 
 |  | 
 | TEST(FlatTree, InsertPositionRValue) { | 
 |   MoveOnlyTree cont; | 
 |  | 
 |   auto result = cont.insert(cont.cend(), MoveOnlyInt(2)); | 
 |   EXPECT_EQ(cont.begin(), result); | 
 |   EXPECT_EQ(1U, cont.size()); | 
 |   EXPECT_EQ(2, result->data()); | 
 |  | 
 |   result = cont.insert(cont.cend(), MoveOnlyInt(1)); | 
 |   EXPECT_EQ(cont.begin(), result); | 
 |   EXPECT_EQ(2U, cont.size()); | 
 |   EXPECT_EQ(1, result->data()); | 
 |  | 
 |   result = cont.insert(cont.cend(), MoveOnlyInt(3)); | 
 |   EXPECT_EQ(std::prev(cont.end()), result); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   EXPECT_EQ(3, result->data()); | 
 |  | 
 |   result = cont.insert(cont.cend(), MoveOnlyInt(3)); | 
 |   EXPECT_EQ(std::prev(cont.end()), result); | 
 |   EXPECT_EQ(3U, cont.size()); | 
 |   EXPECT_EQ(3, result->data()); | 
 | } | 
 |  | 
 | // template <class InputIterator> | 
 | //   void insert(InputIterator first, InputIterator last); | 
 |  | 
 | TEST(FlatTree, InsertIterIter) { | 
 |   struct GetKeyFromIntIntPair { | 
 |     const int& operator()(const std::pair<int, int>& p) const { | 
 |       return p.first; | 
 |     } | 
 |   }; | 
 |  | 
 |   using IntIntMap = flat_tree<int, GetKeyFromIntIntPair, std::less<int>, | 
 |                               std::vector<IntPair>>; | 
 |  | 
 |   { | 
 |     IntIntMap cont; | 
 |     IntPair int_pairs[] = {{3, 1}, {1, 1}, {4, 1}, {2, 1}}; | 
 |     cont.insert(std::begin(int_pairs), std::end(int_pairs)); | 
 |     EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), | 
 |                                   IntPair(4, 1))); | 
 |   } | 
 |  | 
 |   { | 
 |     IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); | 
 |     std::vector<IntPair> int_pairs; | 
 |     cont.insert(std::begin(int_pairs), std::end(int_pairs)); | 
 |     EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), | 
 |                                   IntPair(4, 1))); | 
 |   } | 
 |  | 
 |   { | 
 |     IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); | 
 |     IntPair int_pairs[] = {{1, 1}}; | 
 |     cont.insert(std::begin(int_pairs), std::end(int_pairs)); | 
 |     EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), | 
 |                                   IntPair(4, 1))); | 
 |   } | 
 |  | 
 |   { | 
 |     IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); | 
 |     IntPair int_pairs[] = {{5, 1}}; | 
 |     cont.insert(std::begin(int_pairs), std::end(int_pairs)); | 
 |     EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), | 
 |                                   IntPair(4, 1), IntPair(5, 1))); | 
 |   } | 
 |  | 
 |   { | 
 |     IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); | 
 |     IntPair int_pairs[] = {{3, 2}, {1, 2}, {4, 2}, {2, 2}}; | 
 |     cont.insert(std::begin(int_pairs), std::end(int_pairs)); | 
 |     EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), | 
 |                                   IntPair(4, 1))); | 
 |   } | 
 |  | 
 |   { | 
 |     IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); | 
 |     IntPair int_pairs[] = {{3, 2}, {1, 2}, {4, 2}, {2, 2}, {7, 2}, {6, 2}, | 
 |                            {8, 2}, {5, 2}, {5, 3}, {6, 3}, {7, 3}, {8, 3}}; | 
 |     cont.insert(std::begin(int_pairs), std::end(int_pairs)); | 
 |     EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), | 
 |                                   IntPair(4, 1), IntPair(5, 2), IntPair(6, 2), | 
 |                                   IntPair(7, 2), IntPair(8, 2))); | 
 |   } | 
 | } | 
 |  | 
 | // template <class... Args> | 
 | // pair<iterator, bool> emplace(Args&&... args) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Emplace) { | 
 |   { | 
 |     EmplaceableTree cont; | 
 |  | 
 |     std::pair<EmplaceableTree::iterator, bool> result = cont.emplace(); | 
 |     EXPECT_TRUE(result.second); | 
 |     EXPECT_EQ(cont.begin(), result.first); | 
 |     EXPECT_EQ(1U, cont.size()); | 
 |     EXPECT_EQ(Emplaceable(), *cont.begin()); | 
 |  | 
 |     result = cont.emplace(2, 3.5); | 
 |     EXPECT_TRUE(result.second); | 
 |     EXPECT_EQ(std::next(cont.begin()), result.first); | 
 |     EXPECT_EQ(2U, cont.size()); | 
 |     EXPECT_EQ(Emplaceable(2, 3.5), *result.first); | 
 |  | 
 |     result = cont.emplace(2, 3.5); | 
 |     EXPECT_FALSE(result.second); | 
 |     EXPECT_EQ(std::next(cont.begin()), result.first); | 
 |     EXPECT_EQ(2U, cont.size()); | 
 |     EXPECT_EQ(Emplaceable(2, 3.5), *result.first); | 
 |   } | 
 |   { | 
 |     TypedTree<TypeParam> cont; | 
 |  | 
 |     std::pair<typename TypedTree<TypeParam>::iterator, bool> result = | 
 |         cont.emplace(2); | 
 |     EXPECT_TRUE(result.second); | 
 |     EXPECT_EQ(cont.begin(), result.first); | 
 |     EXPECT_EQ(1U, cont.size()); | 
 |     EXPECT_EQ(2, *result.first); | 
 |   } | 
 | } | 
 |  | 
 | // template <class... Args> | 
 | // iterator emplace_hint(const_iterator position_hint, Args&&... args) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, EmplacePosition) { | 
 |   { | 
 |     EmplaceableTree cont; | 
 |  | 
 |     auto result = cont.emplace_hint(cont.cend()); | 
 |     EXPECT_EQ(cont.begin(), result); | 
 |     EXPECT_EQ(1U, cont.size()); | 
 |     EXPECT_EQ(Emplaceable(), *cont.begin()); | 
 |  | 
 |     result = cont.emplace_hint(cont.cend(), 2, 3.5); | 
 |     EXPECT_EQ(std::next(cont.begin()), result); | 
 |     EXPECT_EQ(2U, cont.size()); | 
 |     EXPECT_EQ(Emplaceable(2, 3.5), *result); | 
 |  | 
 |     result = cont.emplace_hint(cont.cbegin(), 2, 3.5); | 
 |     EXPECT_EQ(std::next(cont.begin()), result); | 
 |     EXPECT_EQ(2U, cont.size()); | 
 |     EXPECT_EQ(Emplaceable(2, 3.5), *result); | 
 |   } | 
 |   { | 
 |     TypedTree<TypeParam> cont; | 
 |  | 
 |     auto result = cont.emplace_hint(cont.cend(), 2); | 
 |     EXPECT_EQ(cont.begin(), result); | 
 |     EXPECT_EQ(1U, cont.size()); | 
 |     EXPECT_EQ(2, *result); | 
 |   } | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Underlying type operations. | 
 |  | 
 | // underlying_type extract() && | 
 | TYPED_TEST_P(FlatTreeTest, Extract) { | 
 |   TypedTree<TypeParam> cont; | 
 |   cont.emplace(3); | 
 |   cont.emplace(1); | 
 |   cont.emplace(2); | 
 |   cont.emplace(4); | 
 |  | 
 |   TypeParam body = std::move(cont).extract(); | 
 |   EXPECT_THAT(cont, IsEmpty()); | 
 |   EXPECT_THAT(body, ElementsAre(1, 2, 3, 4)); | 
 | } | 
 |  | 
 | // replace(underlying_type&&) | 
 | TYPED_TEST_P(FlatTreeTest, Replace) { | 
 |   TypeParam body = {1, 2, 3, 4}; | 
 |   TypedTree<TypeParam> cont; | 
 |   cont.replace(std::move(body)); | 
 |  | 
 |   EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4)); | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Erase operations. | 
 |  | 
 | // iterator erase(const_iterator position_hint) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, ErasePosition) { | 
 |   { | 
 |     TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); | 
 |  | 
 |     auto it = cont.erase(std::next(cont.cbegin(), 3)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), it); | 
 |     EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8)); | 
 |  | 
 |     it = cont.erase(std::next(cont.cbegin(), 0)); | 
 |     EXPECT_EQ(cont.begin(), it); | 
 |     EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7, 8)); | 
 |  | 
 |     it = cont.erase(std::next(cont.cbegin(), 5)); | 
 |     EXPECT_EQ(cont.end(), it); | 
 |     EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7)); | 
 |  | 
 |     it = cont.erase(std::next(cont.cbegin(), 1)); | 
 |     EXPECT_EQ(std::next(cont.begin()), it); | 
 |     EXPECT_THAT(cont, ElementsAre(2, 5, 6, 7)); | 
 |  | 
 |     it = cont.erase(std::next(cont.cbegin(), 2)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), it); | 
 |     EXPECT_THAT(cont, ElementsAre(2, 5, 7)); | 
 |  | 
 |     it = cont.erase(std::next(cont.cbegin(), 2)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), it); | 
 |     EXPECT_THAT(cont, ElementsAre(2, 5)); | 
 |  | 
 |     it = cont.erase(std::next(cont.cbegin(), 0)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), it); | 
 |     EXPECT_THAT(cont, ElementsAre(5)); | 
 |  | 
 |     it = cont.erase(cont.cbegin()); | 
 |     EXPECT_EQ(cont.begin(), it); | 
 |     EXPECT_EQ(cont.end(), it); | 
 |   } | 
 |   //  This is LWG #2059. | 
 |   //  There is a potential ambiguity between erase with an iterator and erase | 
 |   //  with a key, if key has a templated constructor. | 
 |   { | 
 |     using T = TemplateConstructor; | 
 |  | 
 |     flat_tree<T, identity, std::less<>, std::vector<T>> cont; | 
 |     T v(0); | 
 |  | 
 |     auto it = cont.find(v); | 
 |     if (it != cont.end()) | 
 |       cont.erase(it); | 
 |   } | 
 | } | 
 |  | 
 | // iterator erase(const_iterator first, const_iterator last) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, EraseRange) { | 
 |   TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); | 
 |  | 
 |   auto it = | 
 |       cont.erase(std::next(cont.cbegin(), 5), std::next(cont.cbegin(), 5)); | 
 |   EXPECT_EQ(std::next(cont.begin(), 5), it); | 
 |   EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8)); | 
 |  | 
 |   it = cont.erase(std::next(cont.cbegin(), 3), std::next(cont.cbegin(), 4)); | 
 |   EXPECT_EQ(std::next(cont.begin(), 3), it); | 
 |   EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8)); | 
 |  | 
 |   it = cont.erase(std::next(cont.cbegin(), 2), std::next(cont.cbegin(), 5)); | 
 |   EXPECT_EQ(std::next(cont.begin(), 2), it); | 
 |   EXPECT_THAT(cont, ElementsAre(1, 2, 7, 8)); | 
 |  | 
 |   it = cont.erase(std::next(cont.cbegin(), 0), std::next(cont.cbegin(), 2)); | 
 |   EXPECT_EQ(std::next(cont.begin(), 0), it); | 
 |   EXPECT_THAT(cont, ElementsAre(7, 8)); | 
 |  | 
 |   it = cont.erase(cont.cbegin(), cont.cend()); | 
 |   EXPECT_EQ(cont.begin(), it); | 
 |   EXPECT_EQ(cont.end(), it); | 
 | } | 
 |  | 
 | // size_type erase(const key_type& key) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, EraseKey) { | 
 |   TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); | 
 |  | 
 |   EXPECT_EQ(0U, cont.erase(9)); | 
 |   EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8)); | 
 |  | 
 |   EXPECT_EQ(1U, cont.erase(4)); | 
 |   EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8)); | 
 |  | 
 |   EXPECT_EQ(1U, cont.erase(1)); | 
 |   EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7, 8)); | 
 |  | 
 |   EXPECT_EQ(1U, cont.erase(8)); | 
 |   EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7)); | 
 |  | 
 |   EXPECT_EQ(1U, cont.erase(3)); | 
 |   EXPECT_THAT(cont, ElementsAre(2, 5, 6, 7)); | 
 |  | 
 |   EXPECT_EQ(1U, cont.erase(6)); | 
 |   EXPECT_THAT(cont, ElementsAre(2, 5, 7)); | 
 |  | 
 |   EXPECT_EQ(1U, cont.erase(7)); | 
 |   EXPECT_THAT(cont, ElementsAre(2, 5)); | 
 |  | 
 |   EXPECT_EQ(1U, cont.erase(2)); | 
 |   EXPECT_THAT(cont, ElementsAre(5)); | 
 |  | 
 |   EXPECT_EQ(1U, cont.erase(5)); | 
 |   EXPECT_THAT(cont, ElementsAre()); | 
 | } | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, EraseEndDeath) { | 
 |   { | 
 |     TypedTree<TypeParam> tree; | 
 |     ASSERT_DEATH_IF_SUPPORTED(tree.erase(tree.cend()), ""); | 
 |   } | 
 |  | 
 |   { | 
 |     TypedTree<TypeParam> tree = {1, 2, 3, 4}; | 
 |     ASSERT_DEATH_IF_SUPPORTED(tree.erase(tree.find(5)), ""); | 
 |   } | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Comparators. | 
 |  | 
 | // key_compare key_comp() const | 
 |  | 
 | TEST(FlatTree, KeyComp) { | 
 |   ReversedTree cont({1, 2, 3, 4, 5}); | 
 |  | 
 |   EXPECT_TRUE(absl::c_is_sorted(cont, cont.key_comp())); | 
 |   int new_elements[] = {6, 7, 8, 9, 10}; | 
 |   std::copy(std::begin(new_elements), std::end(new_elements), | 
 |             std::inserter(cont, cont.end())); | 
 |   EXPECT_TRUE(absl::c_is_sorted(cont, cont.key_comp())); | 
 | } | 
 |  | 
 | // value_compare value_comp() const | 
 |  | 
 | TEST(FlatTree, ValueComp) { | 
 |   ReversedTree cont({1, 2, 3, 4, 5}); | 
 |  | 
 |   EXPECT_TRUE(absl::c_is_sorted(cont, cont.value_comp())); | 
 |   int new_elements[] = {6, 7, 8, 9, 10}; | 
 |   std::copy(std::begin(new_elements), std::end(new_elements), | 
 |             std::inserter(cont, cont.end())); | 
 |   EXPECT_TRUE(absl::c_is_sorted(cont, cont.value_comp())); | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // Search operations. | 
 |  | 
 | // size_type count(const key_type& key) const | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Count) { | 
 |   const TypedTree<TypeParam> cont({5, 6, 7, 8, 9, 10, 11, 12}); | 
 |  | 
 |   EXPECT_EQ(1U, cont.count(5)); | 
 |   EXPECT_EQ(1U, cont.count(6)); | 
 |   EXPECT_EQ(1U, cont.count(7)); | 
 |   EXPECT_EQ(1U, cont.count(8)); | 
 |   EXPECT_EQ(1U, cont.count(9)); | 
 |   EXPECT_EQ(1U, cont.count(10)); | 
 |   EXPECT_EQ(1U, cont.count(11)); | 
 |   EXPECT_EQ(1U, cont.count(12)); | 
 |   EXPECT_EQ(0U, cont.count(4)); | 
 | } | 
 |  | 
 | // iterator find(const key_type& key) | 
 | // const_iterator find(const key_type& key) const | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Find) { | 
 |   { | 
 |     TypedTree<TypeParam> cont({5, 6, 7, 8, 9, 10, 11, 12}); | 
 |  | 
 |     EXPECT_EQ(cont.begin(), cont.find(5)); | 
 |     EXPECT_EQ(std::next(cont.begin()), cont.find(6)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.find(7)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.find(8)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.find(9)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.find(10)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.find(11)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.find(12)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), cont.find(4)); | 
 |   } | 
 |   { | 
 |     const TypedTree<TypeParam> cont({5, 6, 7, 8, 9, 10, 11, 12}); | 
 |  | 
 |     EXPECT_EQ(cont.begin(), cont.find(5)); | 
 |     EXPECT_EQ(std::next(cont.begin()), cont.find(6)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.find(7)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.find(8)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.find(9)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.find(10)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.find(11)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.find(12)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), cont.find(4)); | 
 |   } | 
 | } | 
 |  | 
 | // bool contains(const key_type& key) const | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Contains) { | 
 |   const TypedTree<TypeParam> cont({5, 6, 7, 8, 9, 10, 11, 12}); | 
 |  | 
 |   EXPECT_TRUE(cont.contains(5)); | 
 |   EXPECT_TRUE(cont.contains(6)); | 
 |   EXPECT_TRUE(cont.contains(7)); | 
 |   EXPECT_TRUE(cont.contains(8)); | 
 |   EXPECT_TRUE(cont.contains(9)); | 
 |   EXPECT_TRUE(cont.contains(10)); | 
 |   EXPECT_TRUE(cont.contains(11)); | 
 |   EXPECT_TRUE(cont.contains(12)); | 
 |   EXPECT_FALSE(cont.contains(4)); | 
 | } | 
 |  | 
 | // pair<iterator, iterator> equal_range(const key_type& key) | 
 | // pair<const_iterator, const_iterator> equal_range(const key_type& key) const | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, EqualRange) { | 
 |   { | 
 |     TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); | 
 |  | 
 |     std::pair<typename TypedTree<TypeParam>::iterator, | 
 |               typename TypedTree<TypeParam>::iterator> | 
 |         result = cont.equal_range(5); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), result.second); | 
 |     result = cont.equal_range(7); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), result.second); | 
 |     result = cont.equal_range(9); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), result.second); | 
 |     result = cont.equal_range(11); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), result.second); | 
 |     result = cont.equal_range(13); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), result.second); | 
 |     result = cont.equal_range(15); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), result.second); | 
 |     result = cont.equal_range(17); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), result.second); | 
 |     result = cont.equal_range(19); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), result.second); | 
 |     result = cont.equal_range(4); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), result.second); | 
 |     result = cont.equal_range(6); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), result.second); | 
 |     result = cont.equal_range(8); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), result.second); | 
 |     result = cont.equal_range(10); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), result.second); | 
 |     result = cont.equal_range(12); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), result.second); | 
 |     result = cont.equal_range(14); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), result.second); | 
 |     result = cont.equal_range(16); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), result.second); | 
 |     result = cont.equal_range(18); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), result.second); | 
 |     result = cont.equal_range(20); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), result.second); | 
 |   } | 
 |   { | 
 |     const TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); | 
 |  | 
 |     std::pair<typename TypedTree<TypeParam>::const_iterator, | 
 |               typename TypedTree<TypeParam>::const_iterator> | 
 |         result = cont.equal_range(5); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), result.second); | 
 |     result = cont.equal_range(7); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), result.second); | 
 |     result = cont.equal_range(9); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), result.second); | 
 |     result = cont.equal_range(11); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), result.second); | 
 |     result = cont.equal_range(13); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), result.second); | 
 |     result = cont.equal_range(15); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), result.second); | 
 |     result = cont.equal_range(17); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), result.second); | 
 |     result = cont.equal_range(19); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), result.second); | 
 |     result = cont.equal_range(4); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), result.second); | 
 |     result = cont.equal_range(6); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), result.second); | 
 |     result = cont.equal_range(8); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), result.second); | 
 |     result = cont.equal_range(10); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), result.second); | 
 |     result = cont.equal_range(12); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), result.second); | 
 |     result = cont.equal_range(14); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), result.second); | 
 |     result = cont.equal_range(16); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), result.second); | 
 |     result = cont.equal_range(18); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), result.second); | 
 |     result = cont.equal_range(20); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), result.first); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), result.second); | 
 |   } | 
 | } | 
 |  | 
 | //       iterator lower_bound(const key_type& key); | 
 | // const_iterator lower_bound(const key_type& key) const; | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, LowerBound) { | 
 |   { | 
 |     TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); | 
 |  | 
 |     EXPECT_EQ(cont.begin(), cont.lower_bound(5)); | 
 |     EXPECT_EQ(std::next(cont.begin()), cont.lower_bound(7)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(9)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(11)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(13)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(15)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(17)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(19)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), cont.lower_bound(4)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), cont.lower_bound(6)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(8)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(10)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(12)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(14)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(16)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(18)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), cont.lower_bound(20)); | 
 |   } | 
 |   { | 
 |     const TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); | 
 |  | 
 |     EXPECT_EQ(cont.begin(), cont.lower_bound(5)); | 
 |     EXPECT_EQ(std::next(cont.begin()), cont.lower_bound(7)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(9)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(11)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(13)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(15)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(17)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(19)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), cont.lower_bound(4)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), cont.lower_bound(6)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(8)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(10)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(12)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(14)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(16)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(18)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), cont.lower_bound(20)); | 
 |   } | 
 | } | 
 |  | 
 | // iterator upper_bound(const key_type& key) | 
 | // const_iterator upper_bound(const key_type& key) const | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, UpperBound) { | 
 |   { | 
 |     TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); | 
 |  | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(5)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(7)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(9)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(11)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(13)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(15)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(17)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(19)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), cont.upper_bound(4)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(6)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(8)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(10)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(12)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(14)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(16)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(18)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(20)); | 
 |   } | 
 |   { | 
 |     const TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); | 
 |  | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(5)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(7)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(9)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(11)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(13)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(15)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(17)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(19)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 0), cont.upper_bound(4)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(6)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(8)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(10)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(12)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(14)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(16)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(18)); | 
 |     EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(20)); | 
 |   } | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 | // General operations. | 
 |  | 
 | // void swap(flat_tree& other) | 
 | // void swap(flat_tree& lhs, flat_tree& rhs) | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, Swap) { | 
 |   TypedTree<TypeParam> x({1, 2, 3}); | 
 |   TypedTree<TypeParam> y({4}); | 
 |   swap(x, y); | 
 |   EXPECT_THAT(x, ElementsAre(4)); | 
 |   EXPECT_THAT(y, ElementsAre(1, 2, 3)); | 
 |  | 
 |   y.swap(x); | 
 |   EXPECT_THAT(x, ElementsAre(1, 2, 3)); | 
 |   EXPECT_THAT(y, ElementsAre(4)); | 
 | } | 
 |  | 
 | // bool operator==(const flat_tree& lhs, const flat_tree& rhs) | 
 | // bool operator!=(const flat_tree& lhs, const flat_tree& rhs) | 
 | // bool operator<(const flat_tree& lhs, const flat_tree& rhs) | 
 | // bool operator>(const flat_tree& lhs, const flat_tree& rhs) | 
 | // bool operator<=(const flat_tree& lhs, const flat_tree& rhs) | 
 | // bool operator>=(const flat_tree& lhs, const flat_tree& rhs) | 
 |  | 
 | TEST(FlatTree, Comparison) { | 
 |   // Provided comparator does not participate in comparison. | 
 |   ReversedTree biggest({3}); | 
 |   ReversedTree smallest({1}); | 
 |   ReversedTree middle({1, 2}); | 
 |  | 
 |   EXPECT_EQ(biggest, biggest); | 
 |   EXPECT_NE(biggest, smallest); | 
 |   EXPECT_LT(smallest, middle); | 
 |   EXPECT_LE(smallest, middle); | 
 |   EXPECT_LE(middle, middle); | 
 |   EXPECT_GT(biggest, middle); | 
 |   EXPECT_GE(biggest, middle); | 
 |   EXPECT_GE(biggest, biggest); | 
 | } | 
 |  | 
 | TYPED_TEST_P(FlatTreeTest, SupportsEraseIf) { | 
 |   TypedTree<TypeParam> x; | 
 |   EXPECT_EQ(0u, EraseIf(x, [](int) { return false; })); | 
 |   EXPECT_THAT(x, ElementsAre()); | 
 |  | 
 |   x = {1, 2, 3}; | 
 |   EXPECT_EQ(1u, EraseIf(x, [](int elem) { return !(elem & 1); })); | 
 |   EXPECT_THAT(x, ElementsAre(1, 3)); | 
 |  | 
 |   x = {1, 2, 3, 4}; | 
 |   EXPECT_EQ(2u, EraseIf(x, [](int elem) { return elem & 1; })); | 
 |   EXPECT_THAT(x, ElementsAre(2, 4)); | 
 | } | 
 |  | 
 | REGISTER_TYPED_TEST_SUITE_P(FlatTreeTest, | 
 |                             DefaultConstructor, | 
 |                             CopyConstructor, | 
 |                             ContainerCopyConstructor, | 
 |                             InitializerListConstructor, | 
 |                             SortedUniqueContainerCopyConstructor, | 
 |                             SortedUniqueInitializerListConstructor, | 
 |                             CopyAssignable, | 
 |                             InitializerListAssignable, | 
 |                             Clear, | 
 |                             Size, | 
 |                             Empty, | 
 |                             Iterators, | 
 |                             InsertLValue, | 
 |                             InsertPositionLValue, | 
 |                             Emplace, | 
 |                             EmplacePosition, | 
 |                             Extract, | 
 |                             Replace, | 
 |                             ErasePosition, | 
 |                             EraseRange, | 
 |                             EraseKey, | 
 |                             EraseEndDeath, | 
 |                             Count, | 
 |                             Find, | 
 |                             Contains, | 
 |                             EqualRange, | 
 |                             LowerBound, | 
 |                             UpperBound, | 
 |                             Swap, | 
 |                             SupportsEraseIf); | 
 |  | 
 | using IntSequenceContainers = | 
 |     ::testing::Types<std::deque<int>, std::vector<int>>; | 
 | INSTANTIATE_TYPED_TEST_SUITE_P(My, FlatTreeTest, IntSequenceContainers); | 
 |  | 
 | }  // namespace | 
 | }  // namespace flat_containers_internal | 
 | }  // namespace webrtc |