Export of internal Abseil changes
-- 0b924fe4e9871200792617329d32beb8356daa9b by Derek Mauro <dmauro@google.com>: Use less threads in the GetTID() test to avoid test timeouts PiperOrigin-RevId: 292566826 -- 0b519c4fd48d61b7c4ea94ed6a6be6e981b9c51a by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 292563778 -- 3204f6e07bcc2b5e9098d45f1a20998f25ab808e by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 292550551 -- 09fbbe73833478d3f26f3e33c8291b991fd3be51 by Derek Mauro <dmauro@google.com>: Add a debug bounds-check to absl::string_view::operator[] string_view accesses that are out-of-bounds are undefined behavior: https://en.cppreference.com/w/cpp/string/basic_string_view/operator_at This change causes code to abort in debug mode, indicating a bug and possibly a security issue like a buffer overflow. Code broken by this change should be investigated. PiperOrigin-RevId: 292544735 -- bf2c19cb45682628f963d4067c0cd6deed7e656d by Derek Mauro <dmauro@google.com>: Add debug assertions to absl::string_view::front and absl::string_view::back Calling front() or back() on an empty string_view is undefined behavior. This assertion is to help catch broken code. https://en.cppreference.com/w/cpp/string/basic_string_view/front https://en.cppreference.com/w/cpp/string/basic_string_view/back PiperOrigin-RevId: 292453255 -- 47f573679b322f8c0fd2cb037cc87e7bc822ac6b by Xiaoyi Zhang <zhangxy@google.com>: Release functional/CMakeList.txt. PiperOrigin-RevId: 292417025 GitOrigin-RevId: 0b924fe4e9871200792617329d32beb8356daa9b Change-Id: Ie6980fb1ac351d72a2ce4468f25bd31db396f88a
This commit is contained in:
		
							parent
							
								
									c512f118dd
								
							
						
					
					
						commit
						0f86336b69
					
				
					 8 changed files with 151 additions and 78 deletions
				
			
		|  | @ -19,6 +19,7 @@ add_subdirectory(algorithm) | ||||||
| add_subdirectory(container) | add_subdirectory(container) | ||||||
| add_subdirectory(debugging) | add_subdirectory(debugging) | ||||||
| add_subdirectory(flags) | add_subdirectory(flags) | ||||||
|  | add_subdirectory(functional) | ||||||
| add_subdirectory(hash) | add_subdirectory(hash) | ||||||
| add_subdirectory(memory) | add_subdirectory(memory) | ||||||
| add_subdirectory(meta) | add_subdirectory(meta) | ||||||
|  |  | ||||||
|  | @ -59,8 +59,8 @@ TEST(SysinfoTest, GetTID) { | ||||||
| #endif | #endif | ||||||
|   // Test that TIDs are unique to each thread.
 |   // Test that TIDs are unique to each thread.
 | ||||||
|   // Uses a few loops to exercise implementations that reallocate IDs.
 |   // Uses a few loops to exercise implementations that reallocate IDs.
 | ||||||
|   for (int i = 0; i < 32; ++i) { |   for (int i = 0; i < 10; ++i) { | ||||||
|     constexpr int kNumThreads = 64; |     constexpr int kNumThreads = 10; | ||||||
|     Barrier all_threads_done(kNumThreads); |     Barrier all_threads_done(kNumThreads); | ||||||
|     std::vector<std::thread> threads; |     std::vector<std::thread> threads; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -180,9 +180,7 @@ class base_checker { | ||||||
|   const_iterator find(const key_type &key) const { |   const_iterator find(const key_type &key) const { | ||||||
|     return iter_check(tree_.find(key), checker_.find(key)); |     return iter_check(tree_.find(key), checker_.find(key)); | ||||||
|   } |   } | ||||||
|   bool contains(const key_type &key) const { |   bool contains(const key_type &key) const { return find(key) != end(); } | ||||||
|     return find(key) != end(); |  | ||||||
|   } |  | ||||||
|   size_type count(const key_type &key) const { |   size_type count(const key_type &key) const { | ||||||
|     size_type res = checker_.count(key); |     size_type res = checker_.count(key); | ||||||
|     EXPECT_EQ(res, tree_.count(key)); |     EXPECT_EQ(res, tree_.count(key)); | ||||||
|  | @ -240,8 +238,10 @@ class base_checker { | ||||||
|         ++checker_end; |         ++checker_end; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     checker_.erase(checker_begin, checker_end); |     const auto checker_ret = checker_.erase(checker_begin, checker_end); | ||||||
|     tree_.erase(begin, end); |     const auto tree_ret = tree_.erase(begin, end); | ||||||
|  |     EXPECT_EQ(std::distance(checker_.begin(), checker_ret), | ||||||
|  |               std::distance(tree_.begin(), tree_ret)); | ||||||
|     EXPECT_EQ(tree_.size(), checker_.size()); |     EXPECT_EQ(tree_.size(), checker_.size()); | ||||||
|     EXPECT_EQ(tree_.size(), size - count); |     EXPECT_EQ(tree_.size(), size - count); | ||||||
|   } |   } | ||||||
|  | @ -326,7 +326,7 @@ class unique_checker : public base_checker<TreeType, CheckerType> { | ||||||
|   unique_checker(const unique_checker &x) : super_type(x) {} |   unique_checker(const unique_checker &x) : super_type(x) {} | ||||||
|   template <class InputIterator> |   template <class InputIterator> | ||||||
|   unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {} |   unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {} | ||||||
|   unique_checker& operator=(const unique_checker&) = default; |   unique_checker &operator=(const unique_checker &) = default; | ||||||
| 
 | 
 | ||||||
|   // Insertion routines.
 |   // Insertion routines.
 | ||||||
|   std::pair<iterator, bool> insert(const value_type &x) { |   std::pair<iterator, bool> insert(const value_type &x) { | ||||||
|  | @ -374,7 +374,7 @@ class multi_checker : public base_checker<TreeType, CheckerType> { | ||||||
|   multi_checker(const multi_checker &x) : super_type(x) {} |   multi_checker(const multi_checker &x) : super_type(x) {} | ||||||
|   template <class InputIterator> |   template <class InputIterator> | ||||||
|   multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {} |   multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {} | ||||||
|   multi_checker& operator=(const multi_checker&) = default; |   multi_checker &operator=(const multi_checker &) = default; | ||||||
| 
 | 
 | ||||||
|   // Insertion routines.
 |   // Insertion routines.
 | ||||||
|   iterator insert(const value_type &x) { |   iterator insert(const value_type &x) { | ||||||
|  | @ -868,7 +868,7 @@ struct CompareIntToString { | ||||||
| 
 | 
 | ||||||
| struct NonTransparentCompare { | struct NonTransparentCompare { | ||||||
|   template <typename T, typename U> |   template <typename T, typename U> | ||||||
|   bool operator()(const T& t, const U& u) const { |   bool operator()(const T &t, const U &u) const { | ||||||
|     // Treating all comparators as transparent can cause inefficiencies (see
 |     // Treating all comparators as transparent can cause inefficiencies (see
 | ||||||
|     // N3657 C++ proposal). Test that for comparators without 'is_transparent'
 |     // N3657 C++ proposal). Test that for comparators without 'is_transparent'
 | ||||||
|     // alias (like this one), we do not attempt heterogeneous lookup.
 |     // alias (like this one), we do not attempt heterogeneous lookup.
 | ||||||
|  | @ -1005,21 +1005,15 @@ class StringLike { | ||||||
|  public: |  public: | ||||||
|   StringLike() = default; |   StringLike() = default; | ||||||
| 
 | 
 | ||||||
|   StringLike(const char* s) : s_(s) {  // NOLINT
 |   StringLike(const char *s) : s_(s) {  // NOLINT
 | ||||||
|     ++constructor_calls_; |     ++constructor_calls_; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   bool operator<(const StringLike& a) const { |   bool operator<(const StringLike &a) const { return s_ < a.s_; } | ||||||
|     return s_ < a.s_; |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   static void clear_constructor_call_count() { |   static void clear_constructor_call_count() { constructor_calls_ = 0; } | ||||||
|     constructor_calls_ = 0; |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   static int constructor_calls() { |   static int constructor_calls() { return constructor_calls_; } | ||||||
|     return constructor_calls_; |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|   static int constructor_calls_; |   static int constructor_calls_; | ||||||
|  | @ -1476,7 +1470,7 @@ struct NoDefaultCtor { | ||||||
|   int num; |   int num; | ||||||
|   explicit NoDefaultCtor(int i) : num(i) {} |   explicit NoDefaultCtor(int i) : num(i) {} | ||||||
| 
 | 
 | ||||||
|   friend bool operator<(const NoDefaultCtor& a, const NoDefaultCtor& b) { |   friend bool operator<(const NoDefaultCtor &a, const NoDefaultCtor &b) { | ||||||
|     return a.num < b.num; |     return a.num < b.num; | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -882,18 +882,14 @@ struct btree_iterator { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Accessors for the key/value the iterator is pointing at.
 |   // Accessors for the key/value the iterator is pointing at.
 | ||||||
|   reference operator*() const { |   reference operator*() const { return node->value(position); } | ||||||
|     return node->value(position); |   pointer operator->() const { return &node->value(position); } | ||||||
|   } |  | ||||||
|   pointer operator->() const { |  | ||||||
|     return &node->value(position); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   btree_iterator& operator++() { |   btree_iterator &operator++() { | ||||||
|     increment(); |     increment(); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|   btree_iterator& operator--() { |   btree_iterator &operator--() { | ||||||
|     decrement(); |     decrement(); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|  | @ -961,7 +957,7 @@ class btree { | ||||||
| 
 | 
 | ||||||
|   static node_type *EmptyNode() { |   static node_type *EmptyNode() { | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
|     static EmptyNodeType* empty_node = new EmptyNodeType; |     static EmptyNodeType *empty_node = new EmptyNodeType; | ||||||
|     // This assert fails on some other construction methods.
 |     // This assert fails on some other construction methods.
 | ||||||
|     assert(empty_node->parent == empty_node); |     assert(empty_node->parent == empty_node); | ||||||
|     return empty_node; |     return empty_node; | ||||||
|  | @ -980,12 +976,9 @@ class btree { | ||||||
|   struct node_stats { |   struct node_stats { | ||||||
|     using size_type = typename Params::size_type; |     using size_type = typename Params::size_type; | ||||||
| 
 | 
 | ||||||
|     node_stats(size_type l, size_type i) |     node_stats(size_type l, size_type i) : leaf_nodes(l), internal_nodes(i) {} | ||||||
|         : leaf_nodes(l), |  | ||||||
|           internal_nodes(i) { |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     node_stats& operator+=(const node_stats &x) { |     node_stats &operator+=(const node_stats &x) { | ||||||
|       leaf_nodes += x.leaf_nodes; |       leaf_nodes += x.leaf_nodes; | ||||||
|       internal_nodes += x.internal_nodes; |       internal_nodes += x.internal_nodes; | ||||||
|       return *this; |       return *this; | ||||||
|  | @ -1054,25 +1047,17 @@ class btree { | ||||||
|   btree &operator=(const btree &x); |   btree &operator=(const btree &x); | ||||||
|   btree &operator=(btree &&x) noexcept; |   btree &operator=(btree &&x) noexcept; | ||||||
| 
 | 
 | ||||||
|   iterator begin() { |   iterator begin() { return iterator(leftmost(), 0); } | ||||||
|     return iterator(leftmost(), 0); |   const_iterator begin() const { return const_iterator(leftmost(), 0); } | ||||||
|   } |  | ||||||
|   const_iterator begin() const { |  | ||||||
|     return const_iterator(leftmost(), 0); |  | ||||||
|   } |  | ||||||
|   iterator end() { return iterator(rightmost_, rightmost_->count()); } |   iterator end() { return iterator(rightmost_, rightmost_->count()); } | ||||||
|   const_iterator end() const { |   const_iterator end() const { | ||||||
|     return const_iterator(rightmost_, rightmost_->count()); |     return const_iterator(rightmost_, rightmost_->count()); | ||||||
|   } |   } | ||||||
|   reverse_iterator rbegin() { |   reverse_iterator rbegin() { return reverse_iterator(end()); } | ||||||
|     return reverse_iterator(end()); |  | ||||||
|   } |  | ||||||
|   const_reverse_iterator rbegin() const { |   const_reverse_iterator rbegin() const { | ||||||
|     return const_reverse_iterator(end()); |     return const_reverse_iterator(end()); | ||||||
|   } |   } | ||||||
|   reverse_iterator rend() { |   reverse_iterator rend() { return reverse_iterator(begin()); } | ||||||
|     return reverse_iterator(begin()); |  | ||||||
|   } |  | ||||||
|   const_reverse_iterator rend() const { |   const_reverse_iterator rend() const { | ||||||
|     return const_reverse_iterator(begin()); |     return const_reverse_iterator(begin()); | ||||||
|   } |   } | ||||||
|  | @ -1160,7 +1145,7 @@ class btree { | ||||||
| 
 | 
 | ||||||
|   // Erases range. Returns the number of keys erased and an iterator pointing
 |   // Erases range. Returns the number of keys erased and an iterator pointing
 | ||||||
|   // to the element after the last erased element.
 |   // to the element after the last erased element.
 | ||||||
|   std::pair<size_type, iterator> erase(iterator begin, iterator end); |   std::pair<size_type, iterator> erase_range(iterator begin, iterator end); | ||||||
| 
 | 
 | ||||||
|   // Erases the specified key from the btree. Returns 1 if an element was
 |   // Erases the specified key from the btree. Returns 1 if an element was
 | ||||||
|   // erased and 0 otherwise.
 |   // erased and 0 otherwise.
 | ||||||
|  | @ -1242,9 +1227,7 @@ class btree { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // The number of internal, leaf and total nodes used by the btree.
 |   // The number of internal, leaf and total nodes used by the btree.
 | ||||||
|   size_type leaf_nodes() const { |   size_type leaf_nodes() const { return internal_stats(root()).leaf_nodes; } | ||||||
|     return internal_stats(root()).leaf_nodes; |  | ||||||
|   } |  | ||||||
|   size_type internal_nodes() const { |   size_type internal_nodes() const { | ||||||
|     return internal_stats(root()).internal_nodes; |     return internal_stats(root()).internal_nodes; | ||||||
|   } |   } | ||||||
|  | @ -1257,11 +1240,9 @@ class btree { | ||||||
|   size_type bytes_used() const { |   size_type bytes_used() const { | ||||||
|     node_stats stats = internal_stats(root()); |     node_stats stats = internal_stats(root()); | ||||||
|     if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) { |     if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) { | ||||||
|       return sizeof(*this) + |       return sizeof(*this) + node_type::LeafSize(root()->max_count()); | ||||||
|              node_type::LeafSize(root()->max_count()); |  | ||||||
|     } else { |     } else { | ||||||
|       return sizeof(*this) + |       return sizeof(*this) + stats.leaf_nodes * node_type::LeafSize() + | ||||||
|              stats.leaf_nodes * node_type::LeafSize() + |  | ||||||
|              stats.internal_nodes * node_type::InternalSize(); |              stats.internal_nodes * node_type::InternalSize(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | @ -1294,9 +1275,7 @@ class btree { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // The allocator used by the btree.
 |   // The allocator used by the btree.
 | ||||||
|   allocator_type get_allocator() const { |   allocator_type get_allocator() const { return allocator(); } | ||||||
|     return allocator(); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|   // Internal accessor routines.
 |   // Internal accessor routines.
 | ||||||
|  | @ -1326,11 +1305,11 @@ class btree { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Node creation/deletion routines.
 |   // Node creation/deletion routines.
 | ||||||
|   node_type* new_internal_node(node_type *parent) { |   node_type *new_internal_node(node_type *parent) { | ||||||
|     node_type *p = allocate(node_type::InternalSize()); |     node_type *p = allocate(node_type::InternalSize()); | ||||||
|     return node_type::init_internal(p, parent); |     return node_type::init_internal(p, parent); | ||||||
|   } |   } | ||||||
|   node_type* new_leaf_node(node_type *parent) { |   node_type *new_leaf_node(node_type *parent) { | ||||||
|     node_type *p = allocate(node_type::LeafSize()); |     node_type *p = allocate(node_type::LeafSize()); | ||||||
|     return node_type::init_leaf(p, parent, kNodeValues); |     return node_type::init_leaf(p, parent, kNodeValues); | ||||||
|   } |   } | ||||||
|  | @ -1431,8 +1410,8 @@ class btree { | ||||||
|   void internal_clear(node_type *node); |   void internal_clear(node_type *node); | ||||||
| 
 | 
 | ||||||
|   // Verifies the tree structure of node.
 |   // Verifies the tree structure of node.
 | ||||||
|   int internal_verify(const node_type *node, |   int internal_verify(const node_type *node, const key_type *lo, | ||||||
|                       const key_type *lo, const key_type *hi) const; |                       const key_type *hi) const; | ||||||
| 
 | 
 | ||||||
|   node_stats internal_stats(const node_type *node) const { |   node_stats internal_stats(const node_type *node) const { | ||||||
|     // The root can be a static empty node.
 |     // The root can be a static empty node.
 | ||||||
|  | @ -2098,7 +2077,7 @@ auto btree<P>::rebalance_after_delete(iterator iter) -> iterator { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename P> | template <typename P> | ||||||
| auto btree<P>::erase(iterator begin, iterator end) | auto btree<P>::erase_range(iterator begin, iterator end) | ||||||
|     -> std::pair<size_type, iterator> { |     -> std::pair<size_type, iterator> { | ||||||
|   difference_type count = std::distance(begin, end); |   difference_type count = std::distance(begin, end); | ||||||
|   assert(count >= 0); |   assert(count >= 0); | ||||||
|  | @ -2198,7 +2177,7 @@ auto btree<P>::erase_multi(const K &key) -> size_type { | ||||||
|   } |   } | ||||||
|   // Delete all of the keys between begin and upper_bound(key).
 |   // Delete all of the keys between begin and upper_bound(key).
 | ||||||
|   const iterator end = internal_end(internal_upper_bound(key)); |   const iterator end = internal_end(internal_upper_bound(key)); | ||||||
|   return erase(begin, end).first; |   return erase_range(begin, end).first; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename P> | template <typename P> | ||||||
|  | @ -2379,8 +2358,7 @@ bool btree<P>::try_merge_or_rebalance(iterator *iter) { | ||||||
|     // empty. This is a small optimization for the common pattern of deleting
 |     // empty. This is a small optimization for the common pattern of deleting
 | ||||||
|     // from the front of the tree.
 |     // from the front of the tree.
 | ||||||
|     if ((right->count() > kMinNodeValues) && |     if ((right->count() > kMinNodeValues) && | ||||||
|         ((iter->node->count() == 0) || |         ((iter->node->count() == 0) || (iter->position > 0))) { | ||||||
|          (iter->position > 0))) { |  | ||||||
|       int to_move = (right->count() - iter->node->count()) / 2; |       int to_move = (right->count() - iter->node->count()) / 2; | ||||||
|       to_move = (std::min)(to_move, right->count() - 1); |       to_move = (std::min)(to_move, right->count() - 1); | ||||||
|       iter->node->rebalance_right_to_left(to_move, right, mutable_allocator()); |       iter->node->rebalance_right_to_left(to_move, right, mutable_allocator()); | ||||||
|  | @ -2578,8 +2556,8 @@ void btree<P>::internal_clear(node_type *node) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename P> | template <typename P> | ||||||
| int btree<P>::internal_verify( | int btree<P>::internal_verify(const node_type *node, const key_type *lo, | ||||||
|     const node_type *node, const key_type *lo, const key_type *hi) const { |                               const key_type *hi) const { | ||||||
|   assert(node->count() > 0); |   assert(node->count() > 0); | ||||||
|   assert(node->count() <= node->max_count()); |   assert(node->count() <= node->max_count()); | ||||||
|   if (lo) { |   if (lo) { | ||||||
|  | @ -2597,9 +2575,8 @@ int btree<P>::internal_verify( | ||||||
|       assert(node->child(i) != nullptr); |       assert(node->child(i) != nullptr); | ||||||
|       assert(node->child(i)->parent() == node); |       assert(node->child(i)->parent() == node); | ||||||
|       assert(node->child(i)->position() == i); |       assert(node->child(i)->position() == i); | ||||||
|       count += internal_verify( |       count += | ||||||
|           node->child(i), |           internal_verify(node->child(i), (i == 0) ? lo : &node->key(i - 1), | ||||||
|           (i == 0) ? lo : &node->key(i - 1), |  | ||||||
|                           (i == node->count()) ? hi : &node->key(i)); |                           (i == node->count()) ? hi : &node->key(i)); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -136,7 +136,7 @@ class btree_container { | ||||||
|   iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); } |   iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); } | ||||||
|   iterator erase(iterator iter) { return tree_.erase(iter); } |   iterator erase(iterator iter) { return tree_.erase(iter); } | ||||||
|   iterator erase(const_iterator first, const_iterator last) { |   iterator erase(const_iterator first, const_iterator last) { | ||||||
|     return tree_.erase(iterator(first), iterator(last)).second; |     return tree_.erase_range(iterator(first), iterator(last)).second; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Extract routines.
 |   // Extract routines.
 | ||||||
|  | @ -465,7 +465,7 @@ class btree_map_container : public btree_set_container<Tree> { | ||||||
|     // and then using `k` unsequenced. This is safe because the move is into a
 |     // and then using `k` unsequenced. This is safe because the move is into a
 | ||||||
|     // forwarding reference and insert_unique guarantees that `key` is never
 |     // forwarding reference and insert_unique guarantees that `key` is never
 | ||||||
|     // referenced after consuming `args`.
 |     // referenced after consuming `args`.
 | ||||||
|     const key_type& key_ref = k; |     const key_type &key_ref = k; | ||||||
|     return this->tree_.insert_unique( |     return this->tree_.insert_unique( | ||||||
|         key_ref, std::piecewise_construct, std::forward_as_tuple(std::move(k)), |         key_ref, std::piecewise_construct, std::forward_as_tuple(std::move(k)), | ||||||
|         std::forward_as_tuple(std::forward<Args>(args)...)); |         std::forward_as_tuple(std::forward<Args>(args)...)); | ||||||
|  | @ -485,7 +485,7 @@ class btree_map_container : public btree_set_container<Tree> { | ||||||
|     // and then using `k` unsequenced. This is safe because the move is into a
 |     // and then using `k` unsequenced. This is safe because the move is into a
 | ||||||
|     // forwarding reference and insert_hint_unique guarantees that `key` is
 |     // forwarding reference and insert_hint_unique guarantees that `key` is
 | ||||||
|     // never referenced after consuming `args`.
 |     // never referenced after consuming `args`.
 | ||||||
|     const key_type& key_ref = k; |     const key_type &key_ref = k; | ||||||
|     return this->tree_ |     return this->tree_ | ||||||
|         .insert_hint_unique(iterator(hint), key_ref, std::piecewise_construct, |         .insert_hint_unique(iterator(hint), key_ref, std::piecewise_construct, | ||||||
|                             std::forward_as_tuple(std::move(k)), |                             std::forward_as_tuple(std::move(k)), | ||||||
|  |  | ||||||
							
								
								
									
										72
									
								
								absl/functional/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								absl/functional/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | ||||||
|  | # | ||||||
|  | # Copyright 2019 The Abseil Authors. | ||||||
|  | # | ||||||
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | # you may not use this file except in compliance with the License. | ||||||
|  | # You may obtain a copy of the License at | ||||||
|  | # | ||||||
|  | #      https://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | # | ||||||
|  | # Unless required by applicable law or agreed to in writing, software | ||||||
|  | # distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | # See the License for the specific language governing permissions and | ||||||
|  | # limitations under the License. | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | absl_cc_library( | ||||||
|  |   NAME | ||||||
|  |     bind_front | ||||||
|  |   SRCS | ||||||
|  |     "internal/front_binder.h" | ||||||
|  |   HDRS | ||||||
|  |     "bind_front.h" | ||||||
|  |   COPTS | ||||||
|  |     ${ABSL_DEFAULT_COPTS} | ||||||
|  |   DEPS | ||||||
|  |     absl::base_internal | ||||||
|  |     absl::compressed_tuple | ||||||
|  |   PUBLIC | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | absl_cc_test( | ||||||
|  |   NAME | ||||||
|  |     bind_front_test | ||||||
|  |   SRCS | ||||||
|  |     "bind_front_test.cc" | ||||||
|  |   COPTS | ||||||
|  |     ${ABSL_DEFAULT_COPTS} | ||||||
|  |   DEPS | ||||||
|  |     absl::bind_front | ||||||
|  |     absl::memory | ||||||
|  |     gmock_main | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | absl_cc_library( | ||||||
|  |   NAME | ||||||
|  |     function_ref | ||||||
|  |   SRCS | ||||||
|  |     "internal/function_ref.h" | ||||||
|  |   HDRS | ||||||
|  |     "function_ref.h" | ||||||
|  |   COPTS | ||||||
|  |     ${ABSL_DEFAULT_COPTS} | ||||||
|  |   DEPS | ||||||
|  |     absl::base_internal | ||||||
|  |     absl::meta | ||||||
|  |   PUBLIC | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | absl_cc_test( | ||||||
|  |   NAME | ||||||
|  |     function_ref_test | ||||||
|  |   SRCS | ||||||
|  |     "function_ref_test.cc" | ||||||
|  |   COPTS | ||||||
|  |     ${ABSL_TEST_COPTS} | ||||||
|  |   DEPS | ||||||
|  |     absl::function_ref | ||||||
|  |     absl::memory | ||||||
|  |     absl::test_instance_tracker | ||||||
|  |     gmock_main | ||||||
|  | ) | ||||||
|  | @ -282,7 +282,9 @@ class string_view { | ||||||
|   //
 |   //
 | ||||||
|   // Returns the ith element of the `string_view` using the array operator.
 |   // Returns the ith element of the `string_view` using the array operator.
 | ||||||
|   // Note that this operator does not perform any bounds checking.
 |   // Note that this operator does not perform any bounds checking.
 | ||||||
|   constexpr const_reference operator[](size_type i) const { return ptr_[i]; } |   constexpr const_reference operator[](size_type i) const { | ||||||
|  |     return ABSL_ASSERT(i < size()), ptr_[i]; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   // string_view::at()
 |   // string_view::at()
 | ||||||
|   //
 |   //
 | ||||||
|  | @ -300,12 +302,16 @@ class string_view { | ||||||
|   // string_view::front()
 |   // string_view::front()
 | ||||||
|   //
 |   //
 | ||||||
|   // Returns the first element of a `string_view`.
 |   // Returns the first element of a `string_view`.
 | ||||||
|   constexpr const_reference front() const { return ptr_[0]; } |   constexpr const_reference front() const { | ||||||
|  |     return ABSL_ASSERT(!empty()), ptr_[0]; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   // string_view::back()
 |   // string_view::back()
 | ||||||
|   //
 |   //
 | ||||||
|   // Returns the last element of a `string_view`.
 |   // Returns the last element of a `string_view`.
 | ||||||
|   constexpr const_reference back() const { return ptr_[size() - 1]; } |   constexpr const_reference back() const { | ||||||
|  |     return ABSL_ASSERT(!empty()), ptr_[size() - 1]; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   // string_view::data()
 |   // string_view::data()
 | ||||||
|   //
 |   //
 | ||||||
|  |  | ||||||
|  | @ -818,6 +818,18 @@ TEST(StringViewTest, FrontBackSingleChar) { | ||||||
|   EXPECT_EQ(&c, &csp.back()); |   EXPECT_EQ(&c, &csp.back()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | TEST(StringViewTest, FrontBackEmpty) { | ||||||
|  | #ifndef ABSL_USES_STD_STRING_VIEW | ||||||
|  | #ifndef NDEBUG | ||||||
|  |   // Abseil's string_view implementation has debug assertions that check that
 | ||||||
|  |   // front() and back() are not called on an empty string_view.
 | ||||||
|  |   absl::string_view sv; | ||||||
|  |   ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.front(), ""); | ||||||
|  |   ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.back(), ""); | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // `std::string_view::string_view(const char*)` calls
 | // `std::string_view::string_view(const char*)` calls
 | ||||||
| // `std::char_traits<char>::length(const char*)` to get the string length. In
 | // `std::char_traits<char>::length(const char*)` to get the string length. In
 | ||||||
| // libc++, it doesn't allow `nullptr` in the constexpr context, with the error
 | // libc++, it doesn't allow `nullptr` in the constexpr context, with the error
 | ||||||
|  | @ -1108,6 +1120,17 @@ TEST(StringViewTest, Noexcept) { | ||||||
|   EXPECT_TRUE(noexcept(sp.find_last_not_of('f'))); |   EXPECT_TRUE(noexcept(sp.find_last_not_of('f'))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | TEST(StringViewTest, BoundsCheck) { | ||||||
|  | #ifndef ABSL_USES_STD_STRING_VIEW | ||||||
|  | #ifndef NDEBUG | ||||||
|  |   // Abseil's string_view implementation has bounds-checking in debug mode.
 | ||||||
|  |   absl::string_view h = "hello"; | ||||||
|  |   ABSL_EXPECT_DEATH_IF_SUPPORTED(h[5], ""); | ||||||
|  |   ABSL_EXPECT_DEATH_IF_SUPPORTED(h[-1], ""); | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
| TEST(ComparisonOpsTest, StringCompareNotAmbiguous) { | TEST(ComparisonOpsTest, StringCompareNotAmbiguous) { | ||||||
|   EXPECT_EQ("hello", std::string("hello")); |   EXPECT_EQ("hello", std::string("hello")); | ||||||
|   EXPECT_LT("hello", std::string("world")); |   EXPECT_LT("hello", std::string("world")); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue