Victor Boivie | fd954fc | 2021-06-29 09:21:11 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | // This implementation is borrowed from Chromium. |
| 12 | |
| 13 | #include "rtc_base/containers/flat_tree.h" |
| 14 | |
| 15 | // Following tests are ported and extended tests from libcpp for std::set. |
| 16 | // They can be found here: |
| 17 | // https://github.com/llvm/llvm-project/tree/main/libcxx/test/std/containers/associative/set |
| 18 | // |
| 19 | // Not ported tests: |
| 20 | // * No tests with PrivateConstructor and std::less<> changed to std::less<T> |
| 21 | // These tests have to do with C++14 std::less<> |
| 22 | // http://en.cppreference.com/w/cpp/utility/functional/less_void |
| 23 | // and add support for templated versions of lookup functions. |
| 24 | // Because we use same implementation, we figured that it's OK just to check |
| 25 | // compilation and this is what we do in flat_set_unittest/flat_map_unittest. |
| 26 | // * No tests for max_size() |
| 27 | // Has to do with allocator support. |
| 28 | // * No tests with DefaultOnly. |
| 29 | // Standard containers allocate each element in the separate node on the heap |
| 30 | // and then manipulate these nodes. Flat containers store their elements in |
| 31 | // contiguous memory and move them around, type is required to be movable. |
| 32 | // * No tests for N3644. |
| 33 | // This proposal suggests that all default constructed iterators compare |
| 34 | // equal. Currently we use std::vector iterators and they don't implement |
| 35 | // this. |
| 36 | // * No tests with min_allocator and no tests counting allocations. |
| 37 | // Flat sets currently don't support allocators. |
| 38 | |
| 39 | #include <array> |
| 40 | #include <deque> |
| 41 | #include <forward_list> |
| 42 | #include <functional> |
| 43 | #include <iterator> |
| 44 | #include <list> |
| 45 | #include <string> |
| 46 | #include <vector> |
| 47 | |
| 48 | #include "rtc_base/containers/identity.h" |
| 49 | #include "rtc_base/containers/move_only_int.h" |
| 50 | #include "test/gmock.h" |
| 51 | #include "test/gtest.h" |
| 52 | |
| 53 | namespace webrtc { |
| 54 | namespace flat_containers_internal { |
| 55 | namespace { |
| 56 | |
| 57 | template <class It> |
| 58 | class InputIterator { |
| 59 | public: |
| 60 | using iterator_category = std::input_iterator_tag; |
| 61 | using value_type = typename std::iterator_traits<It>::value_type; |
| 62 | using difference_type = typename std::iterator_traits<It>::difference_type; |
| 63 | using pointer = It; |
| 64 | using reference = typename std::iterator_traits<It>::reference; |
| 65 | |
| 66 | InputIterator() : it_() {} |
| 67 | explicit InputIterator(It it) : it_(it) {} |
| 68 | |
| 69 | reference operator*() const { return *it_; } |
| 70 | pointer operator->() const { return it_; } |
| 71 | |
| 72 | InputIterator& operator++() { |
| 73 | ++it_; |
| 74 | return *this; |
| 75 | } |
| 76 | InputIterator operator++(int) { |
| 77 | InputIterator tmp(*this); |
| 78 | ++(*this); |
| 79 | return tmp; |
| 80 | } |
| 81 | |
| 82 | friend bool operator==(const InputIterator& lhs, const InputIterator& rhs) { |
| 83 | return lhs.it_ == rhs.it_; |
| 84 | } |
| 85 | friend bool operator!=(const InputIterator& lhs, const InputIterator& rhs) { |
| 86 | return !(lhs == rhs); |
| 87 | } |
| 88 | |
| 89 | private: |
| 90 | It it_; |
| 91 | }; |
| 92 | |
| 93 | template <typename It> |
| 94 | InputIterator<It> MakeInputIterator(It it) { |
| 95 | return InputIterator<It>(it); |
| 96 | } |
| 97 | |
| 98 | class Emplaceable { |
| 99 | public: |
| 100 | Emplaceable() : Emplaceable(0, 0.0) {} |
| 101 | Emplaceable(int i, double d) : int_(i), double_(d) {} |
| 102 | Emplaceable(Emplaceable&& other) : int_(other.int_), double_(other.double_) { |
| 103 | other.int_ = 0; |
| 104 | other.double_ = 0.0; |
| 105 | } |
| 106 | Emplaceable(const Emplaceable&) = delete; |
| 107 | Emplaceable& operator=(const Emplaceable&) = delete; |
| 108 | |
| 109 | Emplaceable& operator=(Emplaceable&& other) { |
| 110 | int_ = other.int_; |
| 111 | other.int_ = 0; |
| 112 | double_ = other.double_; |
| 113 | other.double_ = 0.0; |
| 114 | return *this; |
| 115 | } |
| 116 | |
| 117 | friend bool operator==(const Emplaceable& lhs, const Emplaceable& rhs) { |
| 118 | return std::tie(lhs.int_, lhs.double_) == std::tie(rhs.int_, rhs.double_); |
| 119 | } |
| 120 | |
| 121 | friend bool operator<(const Emplaceable& lhs, const Emplaceable& rhs) { |
| 122 | return std::tie(lhs.int_, lhs.double_) < std::tie(rhs.int_, rhs.double_); |
| 123 | } |
| 124 | |
| 125 | private: |
| 126 | int int_; |
| 127 | double double_; |
| 128 | }; |
| 129 | |
| 130 | struct TemplateConstructor { |
| 131 | template <typename T> |
| 132 | explicit TemplateConstructor(const T&) {} |
| 133 | |
| 134 | friend bool operator<(const TemplateConstructor&, |
| 135 | const TemplateConstructor&) { |
| 136 | return false; |
| 137 | } |
| 138 | }; |
| 139 | |
| 140 | class NonDefaultConstructibleCompare { |
| 141 | public: |
| 142 | explicit NonDefaultConstructibleCompare(int) {} |
| 143 | |
| 144 | template <typename T> |
| 145 | bool operator()(const T& lhs, const T& rhs) const { |
| 146 | return std::less<T>()(lhs, rhs); |
| 147 | } |
| 148 | }; |
| 149 | |
| 150 | template <class PairType> |
| 151 | struct LessByFirst { |
| 152 | bool operator()(const PairType& lhs, const PairType& rhs) const { |
| 153 | return lhs.first < rhs.first; |
| 154 | } |
| 155 | }; |
| 156 | |
| 157 | // Common test trees. |
| 158 | template <typename ContainerT> |
| 159 | using TypedTree = flat_tree<typename ContainerT::value_type, |
| 160 | identity, |
| 161 | std::less<>, |
| 162 | ContainerT>; |
| 163 | using IntTree = TypedTree<std::vector<int>>; |
| 164 | using IntPair = std::pair<int, int>; |
| 165 | using IntPairTree = |
| 166 | flat_tree<IntPair, identity, LessByFirst<IntPair>, std::vector<IntPair>>; |
| 167 | using MoveOnlyTree = |
| 168 | flat_tree<MoveOnlyInt, identity, std::less<>, std::vector<MoveOnlyInt>>; |
| 169 | using EmplaceableTree = |
| 170 | flat_tree<Emplaceable, identity, std::less<>, std::vector<Emplaceable>>; |
| 171 | using ReversedTree = |
| 172 | flat_tree<int, identity, std::greater<int>, std::vector<int>>; |
| 173 | |
| 174 | using TreeWithStrangeCompare = |
| 175 | flat_tree<int, identity, NonDefaultConstructibleCompare, std::vector<int>>; |
| 176 | |
| 177 | using ::testing::ElementsAre; |
| 178 | using ::testing::IsEmpty; |
| 179 | |
| 180 | template <typename T> |
| 181 | class FlatTreeTest : public testing::Test {}; |
| 182 | TYPED_TEST_SUITE_P(FlatTreeTest); |
| 183 | |
| 184 | TEST(FlatTree, IsMultipass) { |
| 185 | static_assert(!is_multipass<std::istream_iterator<int>>(), |
| 186 | "InputIterator is not multipass"); |
| 187 | static_assert(!is_multipass<std::ostream_iterator<int>>(), |
| 188 | "OutputIterator is not multipass"); |
| 189 | |
| 190 | static_assert(is_multipass<std::forward_list<int>::iterator>(), |
| 191 | "ForwardIterator is multipass"); |
| 192 | static_assert(is_multipass<std::list<int>::iterator>(), |
| 193 | "BidirectionalIterator is multipass"); |
| 194 | static_assert(is_multipass<std::vector<int>::iterator>(), |
| 195 | "RandomAccessIterator is multipass"); |
| 196 | } |
| 197 | |
| 198 | // Tests that the compiler generated move operators propagrate noexcept |
| 199 | // specifiers. |
| 200 | TEST(FlatTree, NoExcept) { |
| 201 | struct MoveThrows { |
| 202 | MoveThrows(MoveThrows&&) noexcept(false) {} |
| 203 | MoveThrows& operator=(MoveThrows&&) noexcept(false) { return *this; } |
| 204 | }; |
| 205 | |
| 206 | using MoveThrowsTree = |
| 207 | flat_tree<MoveThrows, identity, std::less<>, std::array<MoveThrows, 1>>; |
| 208 | |
| 209 | static_assert(std::is_nothrow_move_constructible<IntTree>::value, |
| 210 | "Error: IntTree is not nothrow move constructible"); |
| 211 | static_assert(std::is_nothrow_move_assignable<IntTree>::value, |
| 212 | "Error: IntTree is not nothrow move assignable"); |
| 213 | |
| 214 | static_assert(!std::is_nothrow_move_constructible<MoveThrowsTree>::value, |
| 215 | "Error: MoveThrowsTree is nothrow move constructible"); |
| 216 | static_assert(!std::is_nothrow_move_assignable<MoveThrowsTree>::value, |
| 217 | "Error: MoveThrowsTree is nothrow move assignable"); |
| 218 | } |
| 219 | |
| 220 | // ---------------------------------------------------------------------------- |
| 221 | // Class. |
| 222 | |
| 223 | // Check that flat_tree and its iterators can be instantiated with an |
| 224 | // incomplete type. |
| 225 | |
| 226 | TEST(FlatTree, IncompleteType) { |
| 227 | struct A { |
| 228 | using Tree = flat_tree<A, identity, std::less<A>, std::vector<A>>; |
| 229 | int data; |
| 230 | Tree set_with_incomplete_type; |
| 231 | Tree::iterator it; |
| 232 | Tree::const_iterator cit; |
| 233 | |
| 234 | // We do not declare operator< because clang complains that it's unused. |
| 235 | }; |
| 236 | |
| 237 | A a; |
| 238 | } |
| 239 | |
| 240 | TEST(FlatTree, Stability) { |
| 241 | using Pair = std::pair<int, int>; |
| 242 | |
| 243 | using Tree = flat_tree<Pair, identity, LessByFirst<Pair>, std::vector<Pair>>; |
| 244 | |
| 245 | // Constructors are stable. |
| 246 | Tree cont({{0, 0}, {1, 0}, {0, 1}, {2, 0}, {0, 2}, {1, 1}}); |
| 247 | |
| 248 | auto AllOfSecondsAreZero = [&cont] { |
| 249 | return absl::c_all_of(cont, |
| 250 | [](const Pair& elem) { return elem.second == 0; }); |
| 251 | }; |
| 252 | |
| 253 | EXPECT_TRUE(AllOfSecondsAreZero()) << "constructor should be stable"; |
| 254 | |
| 255 | // Should not replace existing. |
| 256 | cont.insert(Pair(0, 2)); |
| 257 | cont.insert(Pair(1, 2)); |
| 258 | cont.insert(Pair(2, 2)); |
| 259 | |
| 260 | EXPECT_TRUE(AllOfSecondsAreZero()) << "insert should be stable"; |
| 261 | |
| 262 | cont.insert(Pair(3, 0)); |
| 263 | cont.insert(Pair(3, 2)); |
| 264 | |
| 265 | EXPECT_TRUE(AllOfSecondsAreZero()) << "insert should be stable"; |
| 266 | } |
| 267 | |
| 268 | // ---------------------------------------------------------------------------- |
| 269 | // Types. |
| 270 | |
| 271 | // key_type |
| 272 | // key_compare |
| 273 | // value_type |
| 274 | // value_compare |
| 275 | // pointer |
| 276 | // const_pointer |
| 277 | // reference |
| 278 | // const_reference |
| 279 | // size_type |
| 280 | // difference_type |
| 281 | // iterator |
| 282 | // const_iterator |
| 283 | // reverse_iterator |
| 284 | // const_reverse_iterator |
| 285 | |
| 286 | TEST(FlatTree, Types) { |
| 287 | // These are guaranteed to be portable. |
| 288 | static_assert((std::is_same<int, IntTree::key_type>::value), ""); |
| 289 | static_assert((std::is_same<int, IntTree::value_type>::value), ""); |
| 290 | static_assert((std::is_same<std::less<>, IntTree::key_compare>::value), ""); |
| 291 | static_assert((std::is_same<int&, IntTree::reference>::value), ""); |
| 292 | static_assert((std::is_same<const int&, IntTree::const_reference>::value), |
| 293 | ""); |
| 294 | static_assert((std::is_same<int*, IntTree::pointer>::value), ""); |
| 295 | static_assert((std::is_same<const int*, IntTree::const_pointer>::value), ""); |
| 296 | } |
| 297 | |
| 298 | // ---------------------------------------------------------------------------- |
| 299 | // Lifetime. |
| 300 | |
| 301 | // flat_tree() |
| 302 | // flat_tree(const Compare& comp) |
| 303 | |
| 304 | TYPED_TEST_P(FlatTreeTest, DefaultConstructor) { |
| 305 | { |
| 306 | TypedTree<TypeParam> cont; |
| 307 | EXPECT_THAT(cont, ElementsAre()); |
| 308 | } |
| 309 | |
| 310 | { |
| 311 | TreeWithStrangeCompare cont(NonDefaultConstructibleCompare(0)); |
| 312 | EXPECT_THAT(cont, ElementsAre()); |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | // flat_tree(const flat_tree& x) |
| 317 | |
| 318 | TYPED_TEST_P(FlatTreeTest, CopyConstructor) { |
| 319 | TypedTree<TypeParam> original({1, 2, 3, 4}); |
| 320 | TypedTree<TypeParam> copied(original); |
| 321 | |
| 322 | EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4)); |
| 323 | |
| 324 | EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4)); |
| 325 | EXPECT_THAT(original, ElementsAre(1, 2, 3, 4)); |
| 326 | EXPECT_EQ(original, copied); |
| 327 | } |
| 328 | |
| 329 | // flat_tree(flat_tree&& x) |
| 330 | |
| 331 | TEST(FlatTree, MoveConstructor) { |
| 332 | int input_range[] = {1, 2, 3, 4}; |
| 333 | |
| 334 | MoveOnlyTree original(std::begin(input_range), std::end(input_range)); |
| 335 | MoveOnlyTree moved(std::move(original)); |
| 336 | |
| 337 | EXPECT_EQ(1U, moved.count(MoveOnlyInt(1))); |
| 338 | EXPECT_EQ(1U, moved.count(MoveOnlyInt(2))); |
| 339 | EXPECT_EQ(1U, moved.count(MoveOnlyInt(3))); |
| 340 | EXPECT_EQ(1U, moved.count(MoveOnlyInt(4))); |
| 341 | } |
| 342 | |
| 343 | // flat_tree(InputIterator first, |
| 344 | // InputIterator last, |
| 345 | // const Compare& comp = Compare()) |
| 346 | |
| 347 | TEST(FlatTree, RangeConstructor) { |
| 348 | { |
| 349 | IntPair input_vals[] = {{1, 1}, {1, 2}, {2, 1}, {2, 2}, {1, 3}, |
| 350 | {2, 3}, {3, 1}, {3, 2}, {3, 3}}; |
| 351 | |
| 352 | IntPairTree first_of(MakeInputIterator(std::begin(input_vals)), |
| 353 | MakeInputIterator(std::end(input_vals))); |
| 354 | EXPECT_THAT(first_of, |
| 355 | ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1))); |
| 356 | } |
| 357 | { |
| 358 | TreeWithStrangeCompare::value_type input_vals[] = {1, 1, 1, 2, 2, |
| 359 | 2, 3, 3, 3}; |
| 360 | |
| 361 | TreeWithStrangeCompare cont(MakeInputIterator(std::begin(input_vals)), |
| 362 | MakeInputIterator(std::end(input_vals)), |
| 363 | NonDefaultConstructibleCompare(0)); |
| 364 | EXPECT_THAT(cont, ElementsAre(1, 2, 3)); |
| 365 | } |
| 366 | } |
| 367 | |
| 368 | // flat_tree(const container_type&) |
| 369 | |
| 370 | TYPED_TEST_P(FlatTreeTest, ContainerCopyConstructor) { |
| 371 | TypeParam items = {1, 2, 3, 4}; |
| 372 | TypedTree<TypeParam> tree(items); |
| 373 | |
| 374 | EXPECT_THAT(tree, ElementsAre(1, 2, 3, 4)); |
| 375 | EXPECT_THAT(items, ElementsAre(1, 2, 3, 4)); |
| 376 | } |
| 377 | |
| 378 | // flat_tree(container_type&&) |
| 379 | |
| 380 | TEST(FlatTree, ContainerMoveConstructor) { |
| 381 | using Pair = std::pair<int, MoveOnlyInt>; |
| 382 | |
| 383 | // Construct an unsorted vector with a duplicate item in it. Sorted by the |
| 384 | // first item, the second allows us to test for stability. Using a move |
| 385 | // only type to ensure the vector is not copied. |
| 386 | std::vector<Pair> storage; |
| 387 | storage.push_back(Pair(2, MoveOnlyInt(0))); |
| 388 | storage.push_back(Pair(1, MoveOnlyInt(0))); |
| 389 | storage.push_back(Pair(2, MoveOnlyInt(1))); |
| 390 | |
| 391 | using Tree = flat_tree<Pair, identity, LessByFirst<Pair>, std::vector<Pair>>; |
| 392 | Tree tree(std::move(storage)); |
| 393 | |
| 394 | // The list should be two items long, with only the first "2" saved. |
| 395 | ASSERT_EQ(2u, tree.size()); |
| 396 | const Pair& zeroth = *tree.begin(); |
| 397 | ASSERT_EQ(1, zeroth.first); |
| 398 | ASSERT_EQ(0, zeroth.second.data()); |
| 399 | |
| 400 | const Pair& first = *(tree.begin() + 1); |
| 401 | ASSERT_EQ(2, first.first); |
| 402 | ASSERT_EQ(0, first.second.data()); |
| 403 | } |
| 404 | |
| 405 | // flat_tree(std::initializer_list<value_type> ilist, |
| 406 | // const Compare& comp = Compare()) |
| 407 | |
| 408 | TYPED_TEST_P(FlatTreeTest, InitializerListConstructor) { |
| 409 | { |
| 410 | TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 10, 8}); |
| 411 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); |
| 412 | } |
| 413 | { |
| 414 | TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 10, 8}); |
| 415 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); |
| 416 | } |
| 417 | { |
| 418 | TreeWithStrangeCompare cont({1, 2, 3, 4, 5, 6, 10, 8}, |
| 419 | NonDefaultConstructibleCompare(0)); |
| 420 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); |
| 421 | } |
| 422 | { |
| 423 | IntPairTree first_of({{1, 1}, {2, 1}, {1, 2}}); |
| 424 | EXPECT_THAT(first_of, ElementsAre(IntPair(1, 1), IntPair(2, 1))); |
| 425 | } |
| 426 | } |
| 427 | |
| 428 | // flat_tree(sorted_unique_t, |
| 429 | // InputIterator first, |
| 430 | // InputIterator last, |
| 431 | // const Compare& comp = Compare()) |
| 432 | |
| 433 | TEST(FlatTree, SortedUniqueRangeConstructor) { |
| 434 | { |
| 435 | IntPair input_vals[] = {{1, 1}, {2, 1}, {3, 1}}; |
| 436 | |
| 437 | IntPairTree first_of(sorted_unique, |
| 438 | MakeInputIterator(std::begin(input_vals)), |
| 439 | MakeInputIterator(std::end(input_vals))); |
| 440 | EXPECT_THAT(first_of, |
| 441 | ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1))); |
| 442 | } |
| 443 | { |
| 444 | TreeWithStrangeCompare::value_type input_vals[] = {1, 2, 3}; |
| 445 | |
| 446 | TreeWithStrangeCompare cont(sorted_unique, |
| 447 | MakeInputIterator(std::begin(input_vals)), |
| 448 | MakeInputIterator(std::end(input_vals)), |
| 449 | NonDefaultConstructibleCompare(0)); |
| 450 | EXPECT_THAT(cont, ElementsAre(1, 2, 3)); |
| 451 | } |
| 452 | } |
| 453 | |
| 454 | // flat_tree(sorted_unique_t, const container_type&) |
| 455 | |
| 456 | TYPED_TEST_P(FlatTreeTest, SortedUniqueContainerCopyConstructor) { |
| 457 | TypeParam items = {1, 2, 3, 4}; |
| 458 | TypedTree<TypeParam> tree(sorted_unique, items); |
| 459 | |
| 460 | EXPECT_THAT(tree, ElementsAre(1, 2, 3, 4)); |
| 461 | EXPECT_THAT(items, ElementsAre(1, 2, 3, 4)); |
| 462 | } |
| 463 | |
| 464 | // flat_tree(sorted_unique_t, std::vector<value_type>&&) |
| 465 | |
| 466 | TEST(FlatTree, SortedUniqueVectorMoveConstructor) { |
| 467 | using Pair = std::pair<int, MoveOnlyInt>; |
| 468 | |
| 469 | std::vector<Pair> storage; |
| 470 | storage.push_back(Pair(1, MoveOnlyInt(0))); |
| 471 | storage.push_back(Pair(2, MoveOnlyInt(0))); |
| 472 | |
| 473 | using Tree = flat_tree<Pair, identity, LessByFirst<Pair>, std::vector<Pair>>; |
| 474 | Tree tree(sorted_unique, std::move(storage)); |
| 475 | |
| 476 | ASSERT_EQ(2u, tree.size()); |
| 477 | const Pair& zeroth = *tree.begin(); |
| 478 | ASSERT_EQ(1, zeroth.first); |
| 479 | ASSERT_EQ(0, zeroth.second.data()); |
| 480 | |
| 481 | const Pair& first = *(tree.begin() + 1); |
| 482 | ASSERT_EQ(2, first.first); |
| 483 | ASSERT_EQ(0, first.second.data()); |
| 484 | } |
| 485 | |
| 486 | // flat_tree(sorted_unique_t, |
| 487 | // std::initializer_list<value_type> ilist, |
| 488 | // const Compare& comp = Compare()) |
| 489 | |
| 490 | TYPED_TEST_P(FlatTreeTest, SortedUniqueInitializerListConstructor) { |
| 491 | { |
| 492 | TypedTree<TypeParam> cont(sorted_unique, {1, 2, 3, 4, 5, 6, 8, 10}); |
| 493 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); |
| 494 | } |
| 495 | { |
| 496 | TypedTree<TypeParam> cont(sorted_unique, {1, 2, 3, 4, 5, 6, 8, 10}); |
| 497 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); |
| 498 | } |
| 499 | { |
| 500 | TreeWithStrangeCompare cont(sorted_unique, {1, 2, 3, 4, 5, 6, 8, 10}, |
| 501 | NonDefaultConstructibleCompare(0)); |
| 502 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); |
| 503 | } |
| 504 | { |
| 505 | IntPairTree first_of(sorted_unique, {{1, 1}, {2, 1}}); |
| 506 | EXPECT_THAT(first_of, ElementsAre(IntPair(1, 1), IntPair(2, 1))); |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | // ---------------------------------------------------------------------------- |
| 511 | // Assignments. |
| 512 | |
| 513 | // flat_tree& operator=(const flat_tree&) |
| 514 | |
| 515 | TYPED_TEST_P(FlatTreeTest, CopyAssignable) { |
| 516 | TypedTree<TypeParam> original({1, 2, 3, 4}); |
| 517 | TypedTree<TypeParam> copied; |
| 518 | copied = original; |
| 519 | |
| 520 | EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4)); |
| 521 | EXPECT_THAT(original, ElementsAre(1, 2, 3, 4)); |
| 522 | EXPECT_EQ(original, copied); |
| 523 | } |
| 524 | |
| 525 | // flat_tree& operator=(flat_tree&&) |
| 526 | |
| 527 | TEST(FlatTree, MoveAssignable) { |
| 528 | int input_range[] = {1, 2, 3, 4}; |
| 529 | |
| 530 | MoveOnlyTree original(std::begin(input_range), std::end(input_range)); |
| 531 | MoveOnlyTree moved; |
| 532 | moved = std::move(original); |
| 533 | |
| 534 | EXPECT_EQ(1U, moved.count(MoveOnlyInt(1))); |
| 535 | EXPECT_EQ(1U, moved.count(MoveOnlyInt(2))); |
| 536 | EXPECT_EQ(1U, moved.count(MoveOnlyInt(3))); |
| 537 | EXPECT_EQ(1U, moved.count(MoveOnlyInt(4))); |
| 538 | } |
| 539 | |
| 540 | // flat_tree& operator=(std::initializer_list<value_type> ilist) |
| 541 | |
| 542 | TYPED_TEST_P(FlatTreeTest, InitializerListAssignable) { |
| 543 | TypedTree<TypeParam> cont({0}); |
| 544 | cont = {1, 2, 3, 4, 5, 6, 10, 8}; |
| 545 | |
| 546 | EXPECT_EQ(0U, cont.count(0)); |
| 547 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10)); |
| 548 | } |
| 549 | |
| 550 | // -------------------------------------------------------------------------- |
| 551 | // Memory management. |
| 552 | |
| 553 | // void reserve(size_type new_capacity) |
| 554 | |
| 555 | TEST(FlatTreeTest, Reserve) { |
| 556 | IntTree cont({1, 2, 3}); |
| 557 | |
| 558 | cont.reserve(5); |
| 559 | EXPECT_LE(5U, cont.capacity()); |
| 560 | } |
| 561 | |
| 562 | // size_type capacity() const |
| 563 | |
| 564 | TEST(FlatTreeTest, Capacity) { |
| 565 | IntTree cont({1, 2, 3}); |
| 566 | |
| 567 | EXPECT_LE(cont.size(), cont.capacity()); |
| 568 | cont.reserve(5); |
| 569 | EXPECT_LE(cont.size(), cont.capacity()); |
| 570 | } |
| 571 | |
| 572 | // void shrink_to_fit() |
| 573 | |
| 574 | TEST(FlatTreeTest, ShrinkToFit) { |
| 575 | IntTree cont({1, 2, 3}); |
| 576 | |
| 577 | IntTree::size_type capacity_before = cont.capacity(); |
| 578 | cont.shrink_to_fit(); |
| 579 | EXPECT_GE(capacity_before, cont.capacity()); |
| 580 | } |
| 581 | |
| 582 | // ---------------------------------------------------------------------------- |
| 583 | // Size management. |
| 584 | |
| 585 | // void clear() |
| 586 | |
| 587 | TYPED_TEST_P(FlatTreeTest, Clear) { |
| 588 | TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); |
| 589 | cont.clear(); |
| 590 | EXPECT_THAT(cont, ElementsAre()); |
| 591 | } |
| 592 | |
| 593 | // size_type size() const |
| 594 | |
| 595 | TYPED_TEST_P(FlatTreeTest, Size) { |
| 596 | TypedTree<TypeParam> cont; |
| 597 | |
| 598 | EXPECT_EQ(0U, cont.size()); |
| 599 | cont.insert(2); |
| 600 | EXPECT_EQ(1U, cont.size()); |
| 601 | cont.insert(1); |
| 602 | EXPECT_EQ(2U, cont.size()); |
| 603 | cont.insert(3); |
| 604 | EXPECT_EQ(3U, cont.size()); |
| 605 | cont.erase(cont.begin()); |
| 606 | EXPECT_EQ(2U, cont.size()); |
| 607 | cont.erase(cont.begin()); |
| 608 | EXPECT_EQ(1U, cont.size()); |
| 609 | cont.erase(cont.begin()); |
| 610 | EXPECT_EQ(0U, cont.size()); |
| 611 | } |
| 612 | |
| 613 | // bool empty() const |
| 614 | |
| 615 | TYPED_TEST_P(FlatTreeTest, Empty) { |
| 616 | TypedTree<TypeParam> cont; |
| 617 | |
| 618 | EXPECT_TRUE(cont.empty()); |
| 619 | cont.insert(1); |
| 620 | EXPECT_FALSE(cont.empty()); |
| 621 | cont.clear(); |
| 622 | EXPECT_TRUE(cont.empty()); |
| 623 | } |
| 624 | |
| 625 | // ---------------------------------------------------------------------------- |
| 626 | // Iterators. |
| 627 | |
| 628 | // iterator begin() |
| 629 | // const_iterator begin() const |
| 630 | // iterator end() |
| 631 | // const_iterator end() const |
| 632 | // |
| 633 | // reverse_iterator rbegin() |
| 634 | // const_reverse_iterator rbegin() const |
| 635 | // reverse_iterator rend() |
| 636 | // const_reverse_iterator rend() const |
| 637 | // |
| 638 | // const_iterator cbegin() const |
| 639 | // const_iterator cend() const |
| 640 | // const_reverse_iterator crbegin() const |
| 641 | // const_reverse_iterator crend() const |
| 642 | |
| 643 | TYPED_TEST_P(FlatTreeTest, Iterators) { |
| 644 | TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); |
| 645 | |
| 646 | auto size = |
| 647 | static_cast<typename TypedTree<TypeParam>::difference_type>(cont.size()); |
| 648 | |
| 649 | EXPECT_EQ(size, std::distance(cont.begin(), cont.end())); |
| 650 | EXPECT_EQ(size, std::distance(cont.cbegin(), cont.cend())); |
| 651 | EXPECT_EQ(size, std::distance(cont.rbegin(), cont.rend())); |
| 652 | EXPECT_EQ(size, std::distance(cont.crbegin(), cont.crend())); |
| 653 | |
| 654 | { |
| 655 | auto it = cont.begin(); |
| 656 | auto c_it = cont.cbegin(); |
| 657 | EXPECT_EQ(it, c_it); |
| 658 | for (int j = 1; it != cont.end(); ++it, ++c_it, ++j) { |
| 659 | EXPECT_EQ(j, *it); |
| 660 | EXPECT_EQ(j, *c_it); |
| 661 | } |
| 662 | } |
| 663 | { |
| 664 | auto rit = cont.rbegin(); |
| 665 | auto c_rit = cont.crbegin(); |
| 666 | EXPECT_EQ(rit, c_rit); |
| 667 | for (int j = static_cast<int>(size); rit != cont.rend(); |
| 668 | ++rit, ++c_rit, --j) { |
| 669 | EXPECT_EQ(j, *rit); |
| 670 | EXPECT_EQ(j, *c_rit); |
| 671 | } |
| 672 | } |
| 673 | } |
| 674 | |
| 675 | // ---------------------------------------------------------------------------- |
| 676 | // Insert operations. |
| 677 | |
| 678 | // pair<iterator, bool> insert(const value_type& val) |
| 679 | |
| 680 | TYPED_TEST_P(FlatTreeTest, InsertLValue) { |
| 681 | TypedTree<TypeParam> cont; |
| 682 | |
| 683 | int value = 2; |
| 684 | std::pair<typename TypedTree<TypeParam>::iterator, bool> result = |
| 685 | cont.insert(value); |
| 686 | EXPECT_TRUE(result.second); |
| 687 | EXPECT_EQ(cont.begin(), result.first); |
| 688 | EXPECT_EQ(1U, cont.size()); |
| 689 | EXPECT_EQ(2, *result.first); |
| 690 | |
| 691 | value = 1; |
| 692 | result = cont.insert(value); |
| 693 | EXPECT_TRUE(result.second); |
| 694 | EXPECT_EQ(cont.begin(), result.first); |
| 695 | EXPECT_EQ(2U, cont.size()); |
| 696 | EXPECT_EQ(1, *result.first); |
| 697 | |
| 698 | value = 3; |
| 699 | result = cont.insert(value); |
| 700 | EXPECT_TRUE(result.second); |
| 701 | EXPECT_EQ(std::prev(cont.end()), result.first); |
| 702 | EXPECT_EQ(3U, cont.size()); |
| 703 | EXPECT_EQ(3, *result.first); |
| 704 | |
| 705 | value = 3; |
| 706 | result = cont.insert(value); |
| 707 | EXPECT_FALSE(result.second); |
| 708 | EXPECT_EQ(std::prev(cont.end()), result.first); |
| 709 | EXPECT_EQ(3U, cont.size()); |
| 710 | EXPECT_EQ(3, *result.first); |
| 711 | } |
| 712 | |
| 713 | // pair<iterator, bool> insert(value_type&& val) |
| 714 | |
| 715 | TEST(FlatTree, InsertRValue) { |
| 716 | MoveOnlyTree cont; |
| 717 | |
| 718 | std::pair<MoveOnlyTree::iterator, bool> result = cont.insert(MoveOnlyInt(2)); |
| 719 | EXPECT_TRUE(result.second); |
| 720 | EXPECT_EQ(cont.begin(), result.first); |
| 721 | EXPECT_EQ(1U, cont.size()); |
| 722 | EXPECT_EQ(2, result.first->data()); |
| 723 | |
| 724 | result = cont.insert(MoveOnlyInt(1)); |
| 725 | EXPECT_TRUE(result.second); |
| 726 | EXPECT_EQ(cont.begin(), result.first); |
| 727 | EXPECT_EQ(2U, cont.size()); |
| 728 | EXPECT_EQ(1, result.first->data()); |
| 729 | |
| 730 | result = cont.insert(MoveOnlyInt(3)); |
| 731 | EXPECT_TRUE(result.second); |
| 732 | EXPECT_EQ(std::prev(cont.end()), result.first); |
| 733 | EXPECT_EQ(3U, cont.size()); |
| 734 | EXPECT_EQ(3, result.first->data()); |
| 735 | |
| 736 | result = cont.insert(MoveOnlyInt(3)); |
| 737 | EXPECT_FALSE(result.second); |
| 738 | EXPECT_EQ(std::prev(cont.end()), result.first); |
| 739 | EXPECT_EQ(3U, cont.size()); |
| 740 | EXPECT_EQ(3, result.first->data()); |
| 741 | } |
| 742 | |
| 743 | // iterator insert(const_iterator position_hint, const value_type& val) |
| 744 | |
| 745 | TYPED_TEST_P(FlatTreeTest, InsertPositionLValue) { |
| 746 | TypedTree<TypeParam> cont; |
| 747 | |
| 748 | auto result = cont.insert(cont.cend(), 2); |
| 749 | EXPECT_EQ(cont.begin(), result); |
| 750 | EXPECT_EQ(1U, cont.size()); |
| 751 | EXPECT_EQ(2, *result); |
| 752 | |
| 753 | result = cont.insert(cont.cend(), 1); |
| 754 | EXPECT_EQ(cont.begin(), result); |
| 755 | EXPECT_EQ(2U, cont.size()); |
| 756 | EXPECT_EQ(1, *result); |
| 757 | |
| 758 | result = cont.insert(cont.cend(), 3); |
| 759 | EXPECT_EQ(std::prev(cont.end()), result); |
| 760 | EXPECT_EQ(3U, cont.size()); |
| 761 | EXPECT_EQ(3, *result); |
| 762 | |
| 763 | result = cont.insert(cont.cend(), 3); |
| 764 | EXPECT_EQ(std::prev(cont.end()), result); |
| 765 | EXPECT_EQ(3U, cont.size()); |
| 766 | EXPECT_EQ(3, *result); |
| 767 | } |
| 768 | |
| 769 | // iterator insert(const_iterator position_hint, value_type&& val) |
| 770 | |
| 771 | TEST(FlatTree, InsertPositionRValue) { |
| 772 | MoveOnlyTree cont; |
| 773 | |
| 774 | auto result = cont.insert(cont.cend(), MoveOnlyInt(2)); |
| 775 | EXPECT_EQ(cont.begin(), result); |
| 776 | EXPECT_EQ(1U, cont.size()); |
| 777 | EXPECT_EQ(2, result->data()); |
| 778 | |
| 779 | result = cont.insert(cont.cend(), MoveOnlyInt(1)); |
| 780 | EXPECT_EQ(cont.begin(), result); |
| 781 | EXPECT_EQ(2U, cont.size()); |
| 782 | EXPECT_EQ(1, result->data()); |
| 783 | |
| 784 | result = cont.insert(cont.cend(), MoveOnlyInt(3)); |
| 785 | EXPECT_EQ(std::prev(cont.end()), result); |
| 786 | EXPECT_EQ(3U, cont.size()); |
| 787 | EXPECT_EQ(3, result->data()); |
| 788 | |
| 789 | result = cont.insert(cont.cend(), MoveOnlyInt(3)); |
| 790 | EXPECT_EQ(std::prev(cont.end()), result); |
| 791 | EXPECT_EQ(3U, cont.size()); |
| 792 | EXPECT_EQ(3, result->data()); |
| 793 | } |
| 794 | |
| 795 | // template <class InputIterator> |
| 796 | // void insert(InputIterator first, InputIterator last); |
| 797 | |
| 798 | TEST(FlatTree, InsertIterIter) { |
| 799 | struct GetKeyFromIntIntPair { |
| 800 | const int& operator()(const std::pair<int, int>& p) const { |
| 801 | return p.first; |
| 802 | } |
| 803 | }; |
| 804 | |
| 805 | using IntIntMap = flat_tree<int, GetKeyFromIntIntPair, std::less<int>, |
| 806 | std::vector<IntPair>>; |
| 807 | |
| 808 | { |
| 809 | IntIntMap cont; |
| 810 | IntPair int_pairs[] = {{3, 1}, {1, 1}, {4, 1}, {2, 1}}; |
| 811 | cont.insert(std::begin(int_pairs), std::end(int_pairs)); |
| 812 | EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), |
| 813 | IntPair(4, 1))); |
| 814 | } |
| 815 | |
| 816 | { |
| 817 | IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); |
| 818 | std::vector<IntPair> int_pairs; |
| 819 | cont.insert(std::begin(int_pairs), std::end(int_pairs)); |
| 820 | EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), |
| 821 | IntPair(4, 1))); |
| 822 | } |
| 823 | |
| 824 | { |
| 825 | IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); |
| 826 | IntPair int_pairs[] = {{1, 1}}; |
| 827 | cont.insert(std::begin(int_pairs), std::end(int_pairs)); |
| 828 | EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), |
| 829 | IntPair(4, 1))); |
| 830 | } |
| 831 | |
| 832 | { |
| 833 | IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); |
| 834 | IntPair int_pairs[] = {{5, 1}}; |
| 835 | cont.insert(std::begin(int_pairs), std::end(int_pairs)); |
| 836 | EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), |
| 837 | IntPair(4, 1), IntPair(5, 1))); |
| 838 | } |
| 839 | |
| 840 | { |
| 841 | IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); |
| 842 | IntPair int_pairs[] = {{3, 2}, {1, 2}, {4, 2}, {2, 2}}; |
| 843 | cont.insert(std::begin(int_pairs), std::end(int_pairs)); |
| 844 | EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), |
| 845 | IntPair(4, 1))); |
| 846 | } |
| 847 | |
| 848 | { |
| 849 | IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}}); |
| 850 | IntPair int_pairs[] = {{3, 2}, {1, 2}, {4, 2}, {2, 2}, {7, 2}, {6, 2}, |
| 851 | {8, 2}, {5, 2}, {5, 3}, {6, 3}, {7, 3}, {8, 3}}; |
| 852 | cont.insert(std::begin(int_pairs), std::end(int_pairs)); |
| 853 | EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1), |
| 854 | IntPair(4, 1), IntPair(5, 2), IntPair(6, 2), |
| 855 | IntPair(7, 2), IntPair(8, 2))); |
| 856 | } |
| 857 | } |
| 858 | |
| 859 | // template <class... Args> |
| 860 | // pair<iterator, bool> emplace(Args&&... args) |
| 861 | |
| 862 | TYPED_TEST_P(FlatTreeTest, Emplace) { |
| 863 | { |
| 864 | EmplaceableTree cont; |
| 865 | |
| 866 | std::pair<EmplaceableTree::iterator, bool> result = cont.emplace(); |
| 867 | EXPECT_TRUE(result.second); |
| 868 | EXPECT_EQ(cont.begin(), result.first); |
| 869 | EXPECT_EQ(1U, cont.size()); |
| 870 | EXPECT_EQ(Emplaceable(), *cont.begin()); |
| 871 | |
| 872 | result = cont.emplace(2, 3.5); |
| 873 | EXPECT_TRUE(result.second); |
| 874 | EXPECT_EQ(std::next(cont.begin()), result.first); |
| 875 | EXPECT_EQ(2U, cont.size()); |
| 876 | EXPECT_EQ(Emplaceable(2, 3.5), *result.first); |
| 877 | |
| 878 | result = cont.emplace(2, 3.5); |
| 879 | EXPECT_FALSE(result.second); |
| 880 | EXPECT_EQ(std::next(cont.begin()), result.first); |
| 881 | EXPECT_EQ(2U, cont.size()); |
| 882 | EXPECT_EQ(Emplaceable(2, 3.5), *result.first); |
| 883 | } |
| 884 | { |
| 885 | TypedTree<TypeParam> cont; |
| 886 | |
| 887 | std::pair<typename TypedTree<TypeParam>::iterator, bool> result = |
| 888 | cont.emplace(2); |
| 889 | EXPECT_TRUE(result.second); |
| 890 | EXPECT_EQ(cont.begin(), result.first); |
| 891 | EXPECT_EQ(1U, cont.size()); |
| 892 | EXPECT_EQ(2, *result.first); |
| 893 | } |
| 894 | } |
| 895 | |
| 896 | // template <class... Args> |
| 897 | // iterator emplace_hint(const_iterator position_hint, Args&&... args) |
| 898 | |
| 899 | TYPED_TEST_P(FlatTreeTest, EmplacePosition) { |
| 900 | { |
| 901 | EmplaceableTree cont; |
| 902 | |
| 903 | auto result = cont.emplace_hint(cont.cend()); |
| 904 | EXPECT_EQ(cont.begin(), result); |
| 905 | EXPECT_EQ(1U, cont.size()); |
| 906 | EXPECT_EQ(Emplaceable(), *cont.begin()); |
| 907 | |
| 908 | result = cont.emplace_hint(cont.cend(), 2, 3.5); |
| 909 | EXPECT_EQ(std::next(cont.begin()), result); |
| 910 | EXPECT_EQ(2U, cont.size()); |
| 911 | EXPECT_EQ(Emplaceable(2, 3.5), *result); |
| 912 | |
| 913 | result = cont.emplace_hint(cont.cbegin(), 2, 3.5); |
| 914 | EXPECT_EQ(std::next(cont.begin()), result); |
| 915 | EXPECT_EQ(2U, cont.size()); |
| 916 | EXPECT_EQ(Emplaceable(2, 3.5), *result); |
| 917 | } |
| 918 | { |
| 919 | TypedTree<TypeParam> cont; |
| 920 | |
| 921 | auto result = cont.emplace_hint(cont.cend(), 2); |
| 922 | EXPECT_EQ(cont.begin(), result); |
| 923 | EXPECT_EQ(1U, cont.size()); |
| 924 | EXPECT_EQ(2, *result); |
| 925 | } |
| 926 | } |
| 927 | |
| 928 | // ---------------------------------------------------------------------------- |
| 929 | // Underlying type operations. |
| 930 | |
| 931 | // underlying_type extract() && |
| 932 | TYPED_TEST_P(FlatTreeTest, Extract) { |
| 933 | TypedTree<TypeParam> cont; |
| 934 | cont.emplace(3); |
| 935 | cont.emplace(1); |
| 936 | cont.emplace(2); |
| 937 | cont.emplace(4); |
| 938 | |
| 939 | TypeParam body = std::move(cont).extract(); |
| 940 | EXPECT_THAT(cont, IsEmpty()); |
| 941 | EXPECT_THAT(body, ElementsAre(1, 2, 3, 4)); |
| 942 | } |
| 943 | |
| 944 | // replace(underlying_type&&) |
| 945 | TYPED_TEST_P(FlatTreeTest, Replace) { |
| 946 | TypeParam body = {1, 2, 3, 4}; |
| 947 | TypedTree<TypeParam> cont; |
| 948 | cont.replace(std::move(body)); |
| 949 | |
| 950 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4)); |
| 951 | } |
| 952 | |
| 953 | // ---------------------------------------------------------------------------- |
| 954 | // Erase operations. |
| 955 | |
| 956 | // iterator erase(const_iterator position_hint) |
| 957 | |
| 958 | TYPED_TEST_P(FlatTreeTest, ErasePosition) { |
| 959 | { |
| 960 | TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); |
| 961 | |
| 962 | auto it = cont.erase(std::next(cont.cbegin(), 3)); |
| 963 | EXPECT_EQ(std::next(cont.begin(), 3), it); |
| 964 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8)); |
| 965 | |
| 966 | it = cont.erase(std::next(cont.cbegin(), 0)); |
| 967 | EXPECT_EQ(cont.begin(), it); |
| 968 | EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7, 8)); |
| 969 | |
| 970 | it = cont.erase(std::next(cont.cbegin(), 5)); |
| 971 | EXPECT_EQ(cont.end(), it); |
| 972 | EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7)); |
| 973 | |
| 974 | it = cont.erase(std::next(cont.cbegin(), 1)); |
| 975 | EXPECT_EQ(std::next(cont.begin()), it); |
| 976 | EXPECT_THAT(cont, ElementsAre(2, 5, 6, 7)); |
| 977 | |
| 978 | it = cont.erase(std::next(cont.cbegin(), 2)); |
| 979 | EXPECT_EQ(std::next(cont.begin(), 2), it); |
| 980 | EXPECT_THAT(cont, ElementsAre(2, 5, 7)); |
| 981 | |
| 982 | it = cont.erase(std::next(cont.cbegin(), 2)); |
| 983 | EXPECT_EQ(std::next(cont.begin(), 2), it); |
| 984 | EXPECT_THAT(cont, ElementsAre(2, 5)); |
| 985 | |
| 986 | it = cont.erase(std::next(cont.cbegin(), 0)); |
| 987 | EXPECT_EQ(std::next(cont.begin(), 0), it); |
| 988 | EXPECT_THAT(cont, ElementsAre(5)); |
| 989 | |
| 990 | it = cont.erase(cont.cbegin()); |
| 991 | EXPECT_EQ(cont.begin(), it); |
| 992 | EXPECT_EQ(cont.end(), it); |
| 993 | } |
| 994 | // This is LWG #2059. |
| 995 | // There is a potential ambiguity between erase with an iterator and erase |
| 996 | // with a key, if key has a templated constructor. |
| 997 | { |
| 998 | using T = TemplateConstructor; |
| 999 | |
| 1000 | flat_tree<T, identity, std::less<>, std::vector<T>> cont; |
| 1001 | T v(0); |
| 1002 | |
| 1003 | auto it = cont.find(v); |
| 1004 | if (it != cont.end()) |
| 1005 | cont.erase(it); |
| 1006 | } |
| 1007 | } |
| 1008 | |
| 1009 | // iterator erase(const_iterator first, const_iterator last) |
| 1010 | |
| 1011 | TYPED_TEST_P(FlatTreeTest, EraseRange) { |
| 1012 | TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); |
| 1013 | |
| 1014 | auto it = |
| 1015 | cont.erase(std::next(cont.cbegin(), 5), std::next(cont.cbegin(), 5)); |
| 1016 | EXPECT_EQ(std::next(cont.begin(), 5), it); |
| 1017 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8)); |
| 1018 | |
| 1019 | it = cont.erase(std::next(cont.cbegin(), 3), std::next(cont.cbegin(), 4)); |
| 1020 | EXPECT_EQ(std::next(cont.begin(), 3), it); |
| 1021 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8)); |
| 1022 | |
| 1023 | it = cont.erase(std::next(cont.cbegin(), 2), std::next(cont.cbegin(), 5)); |
| 1024 | EXPECT_EQ(std::next(cont.begin(), 2), it); |
| 1025 | EXPECT_THAT(cont, ElementsAre(1, 2, 7, 8)); |
| 1026 | |
| 1027 | it = cont.erase(std::next(cont.cbegin(), 0), std::next(cont.cbegin(), 2)); |
| 1028 | EXPECT_EQ(std::next(cont.begin(), 0), it); |
| 1029 | EXPECT_THAT(cont, ElementsAre(7, 8)); |
| 1030 | |
| 1031 | it = cont.erase(cont.cbegin(), cont.cend()); |
| 1032 | EXPECT_EQ(cont.begin(), it); |
| 1033 | EXPECT_EQ(cont.end(), it); |
| 1034 | } |
| 1035 | |
| 1036 | // size_type erase(const key_type& key) |
| 1037 | |
| 1038 | TYPED_TEST_P(FlatTreeTest, EraseKey) { |
| 1039 | TypedTree<TypeParam> cont({1, 2, 3, 4, 5, 6, 7, 8}); |
| 1040 | |
| 1041 | EXPECT_EQ(0U, cont.erase(9)); |
| 1042 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8)); |
| 1043 | |
| 1044 | EXPECT_EQ(1U, cont.erase(4)); |
| 1045 | EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8)); |
| 1046 | |
| 1047 | EXPECT_EQ(1U, cont.erase(1)); |
| 1048 | EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7, 8)); |
| 1049 | |
| 1050 | EXPECT_EQ(1U, cont.erase(8)); |
| 1051 | EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7)); |
| 1052 | |
| 1053 | EXPECT_EQ(1U, cont.erase(3)); |
| 1054 | EXPECT_THAT(cont, ElementsAre(2, 5, 6, 7)); |
| 1055 | |
| 1056 | EXPECT_EQ(1U, cont.erase(6)); |
| 1057 | EXPECT_THAT(cont, ElementsAre(2, 5, 7)); |
| 1058 | |
| 1059 | EXPECT_EQ(1U, cont.erase(7)); |
| 1060 | EXPECT_THAT(cont, ElementsAre(2, 5)); |
| 1061 | |
| 1062 | EXPECT_EQ(1U, cont.erase(2)); |
| 1063 | EXPECT_THAT(cont, ElementsAre(5)); |
| 1064 | |
| 1065 | EXPECT_EQ(1U, cont.erase(5)); |
| 1066 | EXPECT_THAT(cont, ElementsAre()); |
| 1067 | } |
| 1068 | |
| 1069 | TYPED_TEST_P(FlatTreeTest, EraseEndDeath) { |
| 1070 | { |
| 1071 | TypedTree<TypeParam> tree; |
| 1072 | ASSERT_DEATH_IF_SUPPORTED(tree.erase(tree.cend()), ""); |
| 1073 | } |
| 1074 | |
| 1075 | { |
| 1076 | TypedTree<TypeParam> tree = {1, 2, 3, 4}; |
| 1077 | ASSERT_DEATH_IF_SUPPORTED(tree.erase(tree.find(5)), ""); |
| 1078 | } |
| 1079 | } |
| 1080 | |
| 1081 | // ---------------------------------------------------------------------------- |
| 1082 | // Comparators. |
| 1083 | |
| 1084 | // key_compare key_comp() const |
| 1085 | |
| 1086 | TEST(FlatTree, KeyComp) { |
| 1087 | ReversedTree cont({1, 2, 3, 4, 5}); |
| 1088 | |
| 1089 | EXPECT_TRUE(absl::c_is_sorted(cont, cont.key_comp())); |
| 1090 | int new_elements[] = {6, 7, 8, 9, 10}; |
| 1091 | std::copy(std::begin(new_elements), std::end(new_elements), |
| 1092 | std::inserter(cont, cont.end())); |
| 1093 | EXPECT_TRUE(absl::c_is_sorted(cont, cont.key_comp())); |
| 1094 | } |
| 1095 | |
| 1096 | // value_compare value_comp() const |
| 1097 | |
| 1098 | TEST(FlatTree, ValueComp) { |
| 1099 | ReversedTree cont({1, 2, 3, 4, 5}); |
| 1100 | |
| 1101 | EXPECT_TRUE(absl::c_is_sorted(cont, cont.value_comp())); |
| 1102 | int new_elements[] = {6, 7, 8, 9, 10}; |
| 1103 | std::copy(std::begin(new_elements), std::end(new_elements), |
| 1104 | std::inserter(cont, cont.end())); |
| 1105 | EXPECT_TRUE(absl::c_is_sorted(cont, cont.value_comp())); |
| 1106 | } |
| 1107 | |
| 1108 | // ---------------------------------------------------------------------------- |
| 1109 | // Search operations. |
| 1110 | |
| 1111 | // size_type count(const key_type& key) const |
| 1112 | |
| 1113 | TYPED_TEST_P(FlatTreeTest, Count) { |
| 1114 | const TypedTree<TypeParam> cont({5, 6, 7, 8, 9, 10, 11, 12}); |
| 1115 | |
| 1116 | EXPECT_EQ(1U, cont.count(5)); |
| 1117 | EXPECT_EQ(1U, cont.count(6)); |
| 1118 | EXPECT_EQ(1U, cont.count(7)); |
| 1119 | EXPECT_EQ(1U, cont.count(8)); |
| 1120 | EXPECT_EQ(1U, cont.count(9)); |
| 1121 | EXPECT_EQ(1U, cont.count(10)); |
| 1122 | EXPECT_EQ(1U, cont.count(11)); |
| 1123 | EXPECT_EQ(1U, cont.count(12)); |
| 1124 | EXPECT_EQ(0U, cont.count(4)); |
| 1125 | } |
| 1126 | |
| 1127 | // iterator find(const key_type& key) |
| 1128 | // const_iterator find(const key_type& key) const |
| 1129 | |
| 1130 | TYPED_TEST_P(FlatTreeTest, Find) { |
| 1131 | { |
| 1132 | TypedTree<TypeParam> cont({5, 6, 7, 8, 9, 10, 11, 12}); |
| 1133 | |
| 1134 | EXPECT_EQ(cont.begin(), cont.find(5)); |
| 1135 | EXPECT_EQ(std::next(cont.begin()), cont.find(6)); |
| 1136 | EXPECT_EQ(std::next(cont.begin(), 2), cont.find(7)); |
| 1137 | EXPECT_EQ(std::next(cont.begin(), 3), cont.find(8)); |
| 1138 | EXPECT_EQ(std::next(cont.begin(), 4), cont.find(9)); |
| 1139 | EXPECT_EQ(std::next(cont.begin(), 5), cont.find(10)); |
| 1140 | EXPECT_EQ(std::next(cont.begin(), 6), cont.find(11)); |
| 1141 | EXPECT_EQ(std::next(cont.begin(), 7), cont.find(12)); |
| 1142 | EXPECT_EQ(std::next(cont.begin(), 8), cont.find(4)); |
| 1143 | } |
| 1144 | { |
| 1145 | const TypedTree<TypeParam> cont({5, 6, 7, 8, 9, 10, 11, 12}); |
| 1146 | |
| 1147 | EXPECT_EQ(cont.begin(), cont.find(5)); |
| 1148 | EXPECT_EQ(std::next(cont.begin()), cont.find(6)); |
| 1149 | EXPECT_EQ(std::next(cont.begin(), 2), cont.find(7)); |
| 1150 | EXPECT_EQ(std::next(cont.begin(), 3), cont.find(8)); |
| 1151 | EXPECT_EQ(std::next(cont.begin(), 4), cont.find(9)); |
| 1152 | EXPECT_EQ(std::next(cont.begin(), 5), cont.find(10)); |
| 1153 | EXPECT_EQ(std::next(cont.begin(), 6), cont.find(11)); |
| 1154 | EXPECT_EQ(std::next(cont.begin(), 7), cont.find(12)); |
| 1155 | EXPECT_EQ(std::next(cont.begin(), 8), cont.find(4)); |
| 1156 | } |
| 1157 | } |
| 1158 | |
| 1159 | // bool contains(const key_type& key) const |
| 1160 | |
| 1161 | TYPED_TEST_P(FlatTreeTest, Contains) { |
| 1162 | const TypedTree<TypeParam> cont({5, 6, 7, 8, 9, 10, 11, 12}); |
| 1163 | |
| 1164 | EXPECT_TRUE(cont.contains(5)); |
| 1165 | EXPECT_TRUE(cont.contains(6)); |
| 1166 | EXPECT_TRUE(cont.contains(7)); |
| 1167 | EXPECT_TRUE(cont.contains(8)); |
| 1168 | EXPECT_TRUE(cont.contains(9)); |
| 1169 | EXPECT_TRUE(cont.contains(10)); |
| 1170 | EXPECT_TRUE(cont.contains(11)); |
| 1171 | EXPECT_TRUE(cont.contains(12)); |
| 1172 | EXPECT_FALSE(cont.contains(4)); |
| 1173 | } |
| 1174 | |
| 1175 | // pair<iterator, iterator> equal_range(const key_type& key) |
| 1176 | // pair<const_iterator, const_iterator> equal_range(const key_type& key) const |
| 1177 | |
| 1178 | TYPED_TEST_P(FlatTreeTest, EqualRange) { |
| 1179 | { |
| 1180 | TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); |
| 1181 | |
| 1182 | std::pair<typename TypedTree<TypeParam>::iterator, |
| 1183 | typename TypedTree<TypeParam>::iterator> |
| 1184 | result = cont.equal_range(5); |
| 1185 | EXPECT_EQ(std::next(cont.begin(), 0), result.first); |
| 1186 | EXPECT_EQ(std::next(cont.begin(), 1), result.second); |
| 1187 | result = cont.equal_range(7); |
| 1188 | EXPECT_EQ(std::next(cont.begin(), 1), result.first); |
| 1189 | EXPECT_EQ(std::next(cont.begin(), 2), result.second); |
| 1190 | result = cont.equal_range(9); |
| 1191 | EXPECT_EQ(std::next(cont.begin(), 2), result.first); |
| 1192 | EXPECT_EQ(std::next(cont.begin(), 3), result.second); |
| 1193 | result = cont.equal_range(11); |
| 1194 | EXPECT_EQ(std::next(cont.begin(), 3), result.first); |
| 1195 | EXPECT_EQ(std::next(cont.begin(), 4), result.second); |
| 1196 | result = cont.equal_range(13); |
| 1197 | EXPECT_EQ(std::next(cont.begin(), 4), result.first); |
| 1198 | EXPECT_EQ(std::next(cont.begin(), 5), result.second); |
| 1199 | result = cont.equal_range(15); |
| 1200 | EXPECT_EQ(std::next(cont.begin(), 5), result.first); |
| 1201 | EXPECT_EQ(std::next(cont.begin(), 6), result.second); |
| 1202 | result = cont.equal_range(17); |
| 1203 | EXPECT_EQ(std::next(cont.begin(), 6), result.first); |
| 1204 | EXPECT_EQ(std::next(cont.begin(), 7), result.second); |
| 1205 | result = cont.equal_range(19); |
| 1206 | EXPECT_EQ(std::next(cont.begin(), 7), result.first); |
| 1207 | EXPECT_EQ(std::next(cont.begin(), 8), result.second); |
| 1208 | result = cont.equal_range(4); |
| 1209 | EXPECT_EQ(std::next(cont.begin(), 0), result.first); |
| 1210 | EXPECT_EQ(std::next(cont.begin(), 0), result.second); |
| 1211 | result = cont.equal_range(6); |
| 1212 | EXPECT_EQ(std::next(cont.begin(), 1), result.first); |
| 1213 | EXPECT_EQ(std::next(cont.begin(), 1), result.second); |
| 1214 | result = cont.equal_range(8); |
| 1215 | EXPECT_EQ(std::next(cont.begin(), 2), result.first); |
| 1216 | EXPECT_EQ(std::next(cont.begin(), 2), result.second); |
| 1217 | result = cont.equal_range(10); |
| 1218 | EXPECT_EQ(std::next(cont.begin(), 3), result.first); |
| 1219 | EXPECT_EQ(std::next(cont.begin(), 3), result.second); |
| 1220 | result = cont.equal_range(12); |
| 1221 | EXPECT_EQ(std::next(cont.begin(), 4), result.first); |
| 1222 | EXPECT_EQ(std::next(cont.begin(), 4), result.second); |
| 1223 | result = cont.equal_range(14); |
| 1224 | EXPECT_EQ(std::next(cont.begin(), 5), result.first); |
| 1225 | EXPECT_EQ(std::next(cont.begin(), 5), result.second); |
| 1226 | result = cont.equal_range(16); |
| 1227 | EXPECT_EQ(std::next(cont.begin(), 6), result.first); |
| 1228 | EXPECT_EQ(std::next(cont.begin(), 6), result.second); |
| 1229 | result = cont.equal_range(18); |
| 1230 | EXPECT_EQ(std::next(cont.begin(), 7), result.first); |
| 1231 | EXPECT_EQ(std::next(cont.begin(), 7), result.second); |
| 1232 | result = cont.equal_range(20); |
| 1233 | EXPECT_EQ(std::next(cont.begin(), 8), result.first); |
| 1234 | EXPECT_EQ(std::next(cont.begin(), 8), result.second); |
| 1235 | } |
| 1236 | { |
| 1237 | const TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); |
| 1238 | |
| 1239 | std::pair<typename TypedTree<TypeParam>::const_iterator, |
| 1240 | typename TypedTree<TypeParam>::const_iterator> |
| 1241 | result = cont.equal_range(5); |
| 1242 | EXPECT_EQ(std::next(cont.begin(), 0), result.first); |
| 1243 | EXPECT_EQ(std::next(cont.begin(), 1), result.second); |
| 1244 | result = cont.equal_range(7); |
| 1245 | EXPECT_EQ(std::next(cont.begin(), 1), result.first); |
| 1246 | EXPECT_EQ(std::next(cont.begin(), 2), result.second); |
| 1247 | result = cont.equal_range(9); |
| 1248 | EXPECT_EQ(std::next(cont.begin(), 2), result.first); |
| 1249 | EXPECT_EQ(std::next(cont.begin(), 3), result.second); |
| 1250 | result = cont.equal_range(11); |
| 1251 | EXPECT_EQ(std::next(cont.begin(), 3), result.first); |
| 1252 | EXPECT_EQ(std::next(cont.begin(), 4), result.second); |
| 1253 | result = cont.equal_range(13); |
| 1254 | EXPECT_EQ(std::next(cont.begin(), 4), result.first); |
| 1255 | EXPECT_EQ(std::next(cont.begin(), 5), result.second); |
| 1256 | result = cont.equal_range(15); |
| 1257 | EXPECT_EQ(std::next(cont.begin(), 5), result.first); |
| 1258 | EXPECT_EQ(std::next(cont.begin(), 6), result.second); |
| 1259 | result = cont.equal_range(17); |
| 1260 | EXPECT_EQ(std::next(cont.begin(), 6), result.first); |
| 1261 | EXPECT_EQ(std::next(cont.begin(), 7), result.second); |
| 1262 | result = cont.equal_range(19); |
| 1263 | EXPECT_EQ(std::next(cont.begin(), 7), result.first); |
| 1264 | EXPECT_EQ(std::next(cont.begin(), 8), result.second); |
| 1265 | result = cont.equal_range(4); |
| 1266 | EXPECT_EQ(std::next(cont.begin(), 0), result.first); |
| 1267 | EXPECT_EQ(std::next(cont.begin(), 0), result.second); |
| 1268 | result = cont.equal_range(6); |
| 1269 | EXPECT_EQ(std::next(cont.begin(), 1), result.first); |
| 1270 | EXPECT_EQ(std::next(cont.begin(), 1), result.second); |
| 1271 | result = cont.equal_range(8); |
| 1272 | EXPECT_EQ(std::next(cont.begin(), 2), result.first); |
| 1273 | EXPECT_EQ(std::next(cont.begin(), 2), result.second); |
| 1274 | result = cont.equal_range(10); |
| 1275 | EXPECT_EQ(std::next(cont.begin(), 3), result.first); |
| 1276 | EXPECT_EQ(std::next(cont.begin(), 3), result.second); |
| 1277 | result = cont.equal_range(12); |
| 1278 | EXPECT_EQ(std::next(cont.begin(), 4), result.first); |
| 1279 | EXPECT_EQ(std::next(cont.begin(), 4), result.second); |
| 1280 | result = cont.equal_range(14); |
| 1281 | EXPECT_EQ(std::next(cont.begin(), 5), result.first); |
| 1282 | EXPECT_EQ(std::next(cont.begin(), 5), result.second); |
| 1283 | result = cont.equal_range(16); |
| 1284 | EXPECT_EQ(std::next(cont.begin(), 6), result.first); |
| 1285 | EXPECT_EQ(std::next(cont.begin(), 6), result.second); |
| 1286 | result = cont.equal_range(18); |
| 1287 | EXPECT_EQ(std::next(cont.begin(), 7), result.first); |
| 1288 | EXPECT_EQ(std::next(cont.begin(), 7), result.second); |
| 1289 | result = cont.equal_range(20); |
| 1290 | EXPECT_EQ(std::next(cont.begin(), 8), result.first); |
| 1291 | EXPECT_EQ(std::next(cont.begin(), 8), result.second); |
| 1292 | } |
| 1293 | } |
| 1294 | |
| 1295 | // iterator lower_bound(const key_type& key); |
| 1296 | // const_iterator lower_bound(const key_type& key) const; |
| 1297 | |
| 1298 | TYPED_TEST_P(FlatTreeTest, LowerBound) { |
| 1299 | { |
| 1300 | TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); |
| 1301 | |
| 1302 | EXPECT_EQ(cont.begin(), cont.lower_bound(5)); |
| 1303 | EXPECT_EQ(std::next(cont.begin()), cont.lower_bound(7)); |
| 1304 | EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(9)); |
| 1305 | EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(11)); |
| 1306 | EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(13)); |
| 1307 | EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(15)); |
| 1308 | EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(17)); |
| 1309 | EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(19)); |
| 1310 | EXPECT_EQ(std::next(cont.begin(), 0), cont.lower_bound(4)); |
| 1311 | EXPECT_EQ(std::next(cont.begin(), 1), cont.lower_bound(6)); |
| 1312 | EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(8)); |
| 1313 | EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(10)); |
| 1314 | EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(12)); |
| 1315 | EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(14)); |
| 1316 | EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(16)); |
| 1317 | EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(18)); |
| 1318 | EXPECT_EQ(std::next(cont.begin(), 8), cont.lower_bound(20)); |
| 1319 | } |
| 1320 | { |
| 1321 | const TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); |
| 1322 | |
| 1323 | EXPECT_EQ(cont.begin(), cont.lower_bound(5)); |
| 1324 | EXPECT_EQ(std::next(cont.begin()), cont.lower_bound(7)); |
| 1325 | EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(9)); |
| 1326 | EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(11)); |
| 1327 | EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(13)); |
| 1328 | EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(15)); |
| 1329 | EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(17)); |
| 1330 | EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(19)); |
| 1331 | EXPECT_EQ(std::next(cont.begin(), 0), cont.lower_bound(4)); |
| 1332 | EXPECT_EQ(std::next(cont.begin(), 1), cont.lower_bound(6)); |
| 1333 | EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(8)); |
| 1334 | EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(10)); |
| 1335 | EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(12)); |
| 1336 | EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(14)); |
| 1337 | EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(16)); |
| 1338 | EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(18)); |
| 1339 | EXPECT_EQ(std::next(cont.begin(), 8), cont.lower_bound(20)); |
| 1340 | } |
| 1341 | } |
| 1342 | |
| 1343 | // iterator upper_bound(const key_type& key) |
| 1344 | // const_iterator upper_bound(const key_type& key) const |
| 1345 | |
| 1346 | TYPED_TEST_P(FlatTreeTest, UpperBound) { |
| 1347 | { |
| 1348 | TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); |
| 1349 | |
| 1350 | EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(5)); |
| 1351 | EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(7)); |
| 1352 | EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(9)); |
| 1353 | EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(11)); |
| 1354 | EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(13)); |
| 1355 | EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(15)); |
| 1356 | EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(17)); |
| 1357 | EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(19)); |
| 1358 | EXPECT_EQ(std::next(cont.begin(), 0), cont.upper_bound(4)); |
| 1359 | EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(6)); |
| 1360 | EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(8)); |
| 1361 | EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(10)); |
| 1362 | EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(12)); |
| 1363 | EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(14)); |
| 1364 | EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(16)); |
| 1365 | EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(18)); |
| 1366 | EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(20)); |
| 1367 | } |
| 1368 | { |
| 1369 | const TypedTree<TypeParam> cont({5, 7, 9, 11, 13, 15, 17, 19}); |
| 1370 | |
| 1371 | EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(5)); |
| 1372 | EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(7)); |
| 1373 | EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(9)); |
| 1374 | EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(11)); |
| 1375 | EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(13)); |
| 1376 | EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(15)); |
| 1377 | EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(17)); |
| 1378 | EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(19)); |
| 1379 | EXPECT_EQ(std::next(cont.begin(), 0), cont.upper_bound(4)); |
| 1380 | EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(6)); |
| 1381 | EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(8)); |
| 1382 | EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(10)); |
| 1383 | EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(12)); |
| 1384 | EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(14)); |
| 1385 | EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(16)); |
| 1386 | EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(18)); |
| 1387 | EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(20)); |
| 1388 | } |
| 1389 | } |
| 1390 | |
| 1391 | // ---------------------------------------------------------------------------- |
| 1392 | // General operations. |
| 1393 | |
| 1394 | // void swap(flat_tree& other) |
| 1395 | // void swap(flat_tree& lhs, flat_tree& rhs) |
| 1396 | |
| 1397 | TYPED_TEST_P(FlatTreeTest, Swap) { |
| 1398 | TypedTree<TypeParam> x({1, 2, 3}); |
| 1399 | TypedTree<TypeParam> y({4}); |
| 1400 | swap(x, y); |
| 1401 | EXPECT_THAT(x, ElementsAre(4)); |
| 1402 | EXPECT_THAT(y, ElementsAre(1, 2, 3)); |
| 1403 | |
| 1404 | y.swap(x); |
| 1405 | EXPECT_THAT(x, ElementsAre(1, 2, 3)); |
| 1406 | EXPECT_THAT(y, ElementsAre(4)); |
| 1407 | } |
| 1408 | |
| 1409 | // bool operator==(const flat_tree& lhs, const flat_tree& rhs) |
| 1410 | // bool operator!=(const flat_tree& lhs, const flat_tree& rhs) |
| 1411 | // bool operator<(const flat_tree& lhs, const flat_tree& rhs) |
| 1412 | // bool operator>(const flat_tree& lhs, const flat_tree& rhs) |
| 1413 | // bool operator<=(const flat_tree& lhs, const flat_tree& rhs) |
| 1414 | // bool operator>=(const flat_tree& lhs, const flat_tree& rhs) |
| 1415 | |
| 1416 | TEST(FlatTree, Comparison) { |
| 1417 | // Provided comparator does not participate in comparison. |
| 1418 | ReversedTree biggest({3}); |
| 1419 | ReversedTree smallest({1}); |
| 1420 | ReversedTree middle({1, 2}); |
| 1421 | |
| 1422 | EXPECT_EQ(biggest, biggest); |
| 1423 | EXPECT_NE(biggest, smallest); |
| 1424 | EXPECT_LT(smallest, middle); |
| 1425 | EXPECT_LE(smallest, middle); |
| 1426 | EXPECT_LE(middle, middle); |
| 1427 | EXPECT_GT(biggest, middle); |
| 1428 | EXPECT_GE(biggest, middle); |
| 1429 | EXPECT_GE(biggest, biggest); |
| 1430 | } |
| 1431 | |
| 1432 | TYPED_TEST_P(FlatTreeTest, SupportsEraseIf) { |
| 1433 | TypedTree<TypeParam> x; |
| 1434 | EXPECT_EQ(0u, EraseIf(x, [](int) { return false; })); |
| 1435 | EXPECT_THAT(x, ElementsAre()); |
| 1436 | |
| 1437 | x = {1, 2, 3}; |
| 1438 | EXPECT_EQ(1u, EraseIf(x, [](int elem) { return !(elem & 1); })); |
| 1439 | EXPECT_THAT(x, ElementsAre(1, 3)); |
| 1440 | |
| 1441 | x = {1, 2, 3, 4}; |
| 1442 | EXPECT_EQ(2u, EraseIf(x, [](int elem) { return elem & 1; })); |
| 1443 | EXPECT_THAT(x, ElementsAre(2, 4)); |
| 1444 | } |
| 1445 | |
| 1446 | REGISTER_TYPED_TEST_SUITE_P(FlatTreeTest, |
| 1447 | DefaultConstructor, |
| 1448 | CopyConstructor, |
| 1449 | ContainerCopyConstructor, |
| 1450 | InitializerListConstructor, |
| 1451 | SortedUniqueContainerCopyConstructor, |
| 1452 | SortedUniqueInitializerListConstructor, |
| 1453 | CopyAssignable, |
| 1454 | InitializerListAssignable, |
| 1455 | Clear, |
| 1456 | Size, |
| 1457 | Empty, |
| 1458 | Iterators, |
| 1459 | InsertLValue, |
| 1460 | InsertPositionLValue, |
| 1461 | Emplace, |
| 1462 | EmplacePosition, |
| 1463 | Extract, |
| 1464 | Replace, |
| 1465 | ErasePosition, |
| 1466 | EraseRange, |
| 1467 | EraseKey, |
| 1468 | EraseEndDeath, |
| 1469 | Count, |
| 1470 | Find, |
| 1471 | Contains, |
| 1472 | EqualRange, |
| 1473 | LowerBound, |
| 1474 | UpperBound, |
| 1475 | Swap, |
| 1476 | SupportsEraseIf); |
| 1477 | |
| 1478 | using IntSequenceContainers = |
| 1479 | ::testing::Types<std::deque<int>, std::vector<int>>; |
| 1480 | INSTANTIATE_TYPED_TEST_SUITE_P(My, FlatTreeTest, IntSequenceContainers); |
| 1481 | |
| 1482 | } // namespace |
| 1483 | } // namespace flat_containers_internal |
| 1484 | } // namespace webrtc |