Commit 20c087a7 by Abseil Team Committed by Copybara-Service

Add lifetimebound attribute to some Abseil containers

PiperOrigin-RevId: 529119690
Change-Id: If585274c409e2a344c8d60759da6f8f990023d29
parent 3e9f08d9
......@@ -200,18 +200,22 @@ class FixedArray {
//
// Returns a const T* pointer to elements of the `FixedArray`. This pointer
// can be used to access (but not modify) the contained elements.
const_pointer data() const { return AsValueType(storage_.begin()); }
const_pointer data() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return AsValueType(storage_.begin());
}
// Overload of FixedArray::data() to return a T* pointer to elements of the
// fixed array. This pointer can be used to access and modify the contained
// elements.
pointer data() { return AsValueType(storage_.begin()); }
pointer data() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return AsValueType(storage_.begin());
}
// FixedArray::operator[]
//
// Returns a reference the ith element of the fixed array.
// REQUIRES: 0 <= i < size()
reference operator[](size_type i) {
reference operator[](size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
......@@ -219,7 +223,7 @@ class FixedArray {
// Overload of FixedArray::operator()[] to return a const reference to the
// ith element of the fixed array.
// REQUIRES: 0 <= i < size()
const_reference operator[](size_type i) const {
const_reference operator[](size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
......@@ -228,7 +232,7 @@ class FixedArray {
//
// Bounds-checked access. Returns a reference to the ith element of the fixed
// array, or throws std::out_of_range
reference at(size_type i) {
reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
}
......@@ -237,7 +241,7 @@ class FixedArray {
// Overload of FixedArray::at() to return a const reference to the ith element
// of the fixed array.
const_reference at(size_type i) const {
const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
}
......@@ -247,14 +251,14 @@ class FixedArray {
// FixedArray::front()
//
// Returns a reference to the first element of the fixed array.
reference front() {
reference front() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[0];
}
// Overload of FixedArray::front() to return a reference to the first element
// of a fixed array of const values.
const_reference front() const {
const_reference front() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[0];
}
......@@ -262,14 +266,14 @@ class FixedArray {
// FixedArray::back()
//
// Returns a reference to the last element of the fixed array.
reference back() {
reference back() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[size() - 1];
}
// Overload of FixedArray::back() to return a reference to the last element
// of a fixed array of const values.
const_reference back() const {
const_reference back() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[size() - 1];
}
......@@ -277,62 +281,74 @@ class FixedArray {
// FixedArray::begin()
//
// Returns an iterator to the beginning of the fixed array.
iterator begin() { return data(); }
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }
// Overload of FixedArray::begin() to return a const iterator to the
// beginning of the fixed array.
const_iterator begin() const { return data(); }
const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }
// FixedArray::cbegin()
//
// Returns a const iterator to the beginning of the fixed array.
const_iterator cbegin() const { return begin(); }
const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return begin();
}
// FixedArray::end()
//
// Returns an iterator to the end of the fixed array.
iterator end() { return data() + size(); }
iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return data() + size(); }
// Overload of FixedArray::end() to return a const iterator to the end of the
// fixed array.
const_iterator end() const { return data() + size(); }
const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return data() + size();
}
// FixedArray::cend()
//
// Returns a const iterator to the end of the fixed array.
const_iterator cend() const { return end(); }
const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }
// FixedArray::rbegin()
//
// Returns a reverse iterator from the end of the fixed array.
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(end());
}
// Overload of FixedArray::rbegin() to return a const reverse iterator from
// the end of the fixed array.
const_reverse_iterator rbegin() const {
const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(end());
}
// FixedArray::crbegin()
//
// Returns a const reverse iterator from the end of the fixed array.
const_reverse_iterator crbegin() const { return rbegin(); }
const_reverse_iterator crbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rbegin();
}
// FixedArray::rend()
//
// Returns a reverse iterator from the beginning of the fixed array.
reverse_iterator rend() { return reverse_iterator(begin()); }
reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(begin());
}
// Overload of FixedArray::rend() for returning a const reverse iterator
// from the beginning of the fixed array.
const_reverse_iterator rend() const {
const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(begin());
}
// FixedArray::crend()
//
// Returns a reverse iterator from the beginning of the fixed array.
const_reverse_iterator crend() const { return rend(); }
const_reverse_iterator crend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rend();
}
// FixedArray::fill()
//
......
......@@ -341,7 +341,7 @@ class InlinedVector {
// can be used to access and modify the contained elements.
//
// NOTE: only elements within [`data()`, `data() + size()`) are valid.
pointer data() noexcept {
pointer data() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
: storage_.GetInlinedData();
}
......@@ -351,7 +351,7 @@ class InlinedVector {
// modify the contained elements.
//
// NOTE: only elements within [`data()`, `data() + size()`) are valid.
const_pointer data() const noexcept {
const_pointer data() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
: storage_.GetInlinedData();
}
......@@ -359,14 +359,14 @@ class InlinedVector {
// `InlinedVector::operator[](...)`
//
// Returns a `reference` to the `i`th element of the inlined vector.
reference operator[](size_type i) {
reference operator[](size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
// Overload of `InlinedVector::operator[](...)` that returns a
// `const_reference` to the `i`th element of the inlined vector.
const_reference operator[](size_type i) const {
const_reference operator[](size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
......@@ -377,7 +377,7 @@ class InlinedVector {
//
// NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,
// in both debug and non-debug builds, `std::out_of_range` will be thrown.
reference at(size_type i) {
reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange(
"`InlinedVector::at(size_type)` failed bounds check");
......@@ -390,7 +390,7 @@ class InlinedVector {
//
// NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,
// in both debug and non-debug builds, `std::out_of_range` will be thrown.
const_reference at(size_type i) const {
const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange(
"`InlinedVector::at(size_type) const` failed bounds check");
......@@ -401,14 +401,14 @@ class InlinedVector {
// `InlinedVector::front()`
//
// Returns a `reference` to the first element of the inlined vector.
reference front() {
reference front() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[0];
}
// Overload of `InlinedVector::front()` that returns a `const_reference` to
// the first element of the inlined vector.
const_reference front() const {
const_reference front() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[0];
}
......@@ -416,14 +416,14 @@ class InlinedVector {
// `InlinedVector::back()`
//
// Returns a `reference` to the last element of the inlined vector.
reference back() {
reference back() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[size() - 1];
}
// Overload of `InlinedVector::back()` that returns a `const_reference` to the
// last element of the inlined vector.
const_reference back() const {
const_reference back() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[size() - 1];
}
......@@ -431,63 +431,82 @@ class InlinedVector {
// `InlinedVector::begin()`
//
// Returns an `iterator` to the beginning of the inlined vector.
iterator begin() noexcept { return data(); }
iterator begin() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }
// Overload of `InlinedVector::begin()` that returns a `const_iterator` to
// the beginning of the inlined vector.
const_iterator begin() const noexcept { return data(); }
const_iterator begin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return data();
}
// `InlinedVector::end()`
//
// Returns an `iterator` to the end of the inlined vector.
iterator end() noexcept { return data() + size(); }
iterator end() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return data() + size();
}
// Overload of `InlinedVector::end()` that returns a `const_iterator` to the
// end of the inlined vector.
const_iterator end() const noexcept { return data() + size(); }
const_iterator end() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return data() + size();
}
// `InlinedVector::cbegin()`
//
// Returns a `const_iterator` to the beginning of the inlined vector.
const_iterator cbegin() const noexcept { return begin(); }
const_iterator cbegin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return begin();
}
// `InlinedVector::cend()`
//
// Returns a `const_iterator` to the end of the inlined vector.
const_iterator cend() const noexcept { return end(); }
const_iterator cend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return end();
}
// `InlinedVector::rbegin()`
//
// Returns a `reverse_iterator` from the end of the inlined vector.
reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
reverse_iterator rbegin() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(end());
}
// Overload of `InlinedVector::rbegin()` that returns a
// `const_reverse_iterator` from the end of the inlined vector.
const_reverse_iterator rbegin() const noexcept {
const_reverse_iterator rbegin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(end());
}
// `InlinedVector::rend()`
//
// Returns a `reverse_iterator` from the beginning of the inlined vector.
reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
reverse_iterator rend() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(begin());
}
// Overload of `InlinedVector::rend()` that returns a `const_reverse_iterator`
// from the beginning of the inlined vector.
const_reverse_iterator rend() const noexcept {
const_reverse_iterator rend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(begin());
}
// `InlinedVector::crbegin()`
//
// Returns a `const_reverse_iterator` from the end of the inlined vector.
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
const_reverse_iterator crbegin() const noexcept
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rbegin();
}
// `InlinedVector::crend()`
//
// Returns a `const_reverse_iterator` from the beginning of the inlined
// vector.
const_reverse_iterator crend() const noexcept { return rend(); }
const_reverse_iterator crend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rend();
}
// `InlinedVector::get_allocator()`
//
......@@ -597,20 +616,23 @@ class InlinedVector {
//
// Inserts a copy of `v` at `pos`, returning an `iterator` to the newly
// inserted element.
iterator insert(const_iterator pos, const_reference v) {
iterator insert(const_iterator pos,
const_reference v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return emplace(pos, v);
}
// Overload of `InlinedVector::insert(...)` that inserts `v` at `pos` using
// move semantics, returning an `iterator` to the newly inserted element.
iterator insert(const_iterator pos, value_type&& v) {
iterator insert(const_iterator pos,
value_type&& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return emplace(pos, std::move(v));
}
// Overload of `InlinedVector::insert(...)` that inserts `n` contiguous copies
// of `v` starting at `pos`, returning an `iterator` pointing to the first of
// the newly inserted elements.
iterator insert(const_iterator pos, size_type n, const_reference v) {
iterator insert(const_iterator pos, size_type n,
const_reference v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
......@@ -638,7 +660,8 @@ class InlinedVector {
// Overload of `InlinedVector::insert(...)` that inserts copies of the
// elements of `list` starting at `pos`, returning an `iterator` pointing to
// the first of the newly inserted elements.
iterator insert(const_iterator pos, std::initializer_list<value_type> list) {
iterator insert(const_iterator pos, std::initializer_list<value_type> list)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert(pos, list.begin(), list.end());
}
......@@ -650,7 +673,7 @@ class InlinedVector {
template <typename ForwardIterator,
EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
iterator insert(const_iterator pos, ForwardIterator first,
ForwardIterator last) {
ForwardIterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
......@@ -670,7 +693,8 @@ class InlinedVector {
// NOTE: this overload is for iterators that are "input" category.
template <typename InputIterator,
DisableIfAtLeastForwardIterator<InputIterator> = 0>
iterator insert(const_iterator pos, InputIterator first, InputIterator last) {
iterator insert(const_iterator pos, InputIterator first,
InputIterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
......@@ -687,7 +711,8 @@ class InlinedVector {
// Constructs and inserts an element using `args...` in the inlined vector at
// `pos`, returning an `iterator` pointing to the newly emplaced element.
template <typename... Args>
iterator emplace(const_iterator pos, Args&&... args) {
iterator emplace(const_iterator pos,
Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
......@@ -715,7 +740,7 @@ class InlinedVector {
// Constructs and inserts an element using `args...` in the inlined vector at
// `end()`, returning a `reference` to the newly emplaced element.
template <typename... Args>
reference emplace_back(Args&&... args) {
reference emplace_back(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return storage_.EmplaceBack(std::forward<Args>(args)...);
}
......@@ -746,7 +771,7 @@ class InlinedVector {
// erased element was located.
//
// NOTE: may return `end()`, which is not dereferenceable.
iterator erase(const_iterator pos) {
iterator erase(const_iterator pos) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos < end());
......@@ -758,7 +783,8 @@ class InlinedVector {
// erased element was located.
//
// NOTE: may return `end()`, which is not dereferenceable.
iterator erase(const_iterator from, const_iterator to) {
iterator erase(const_iterator from,
const_iterator to) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(from >= begin());
ABSL_HARDENING_ASSERT(from <= to);
ABSL_HARDENING_ASSERT(to <= end());
......
......@@ -1444,43 +1444,54 @@ class btree {
btree &operator=(const btree &other);
btree &operator=(btree &&other) noexcept;
iterator begin() { return iterator(leftmost()); }
const_iterator begin() const { return const_iterator(leftmost()); }
iterator end() { return iterator(rightmost(), rightmost()->finish()); }
const_iterator end() const {
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(leftmost());
}
const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_iterator(leftmost());
}
iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(rightmost(), rightmost()->finish());
}
const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_iterator(rightmost(), rightmost()->finish());
}
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {
reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(end());
}
const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(end());
}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {
reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(begin());
}
const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(begin());
}
// Finds the first element whose key is not less than `key`.
template <typename K>
iterator lower_bound(const K &key) {
iterator lower_bound(const K &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return internal_end(internal_lower_bound(key).value);
}
template <typename K>
const_iterator lower_bound(const K &key) const {
const_iterator lower_bound(const K &key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return internal_end(internal_lower_bound(key).value);
}
// Finds the first element whose key is not less than `key` and also returns
// whether that element is equal to `key`.
template <typename K>
std::pair<iterator, bool> lower_bound_equal(const K &key) const;
std::pair<iterator, bool> lower_bound_equal(const K &key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Finds the first element whose key is greater than `key`.
template <typename K>
iterator upper_bound(const K &key) {
iterator upper_bound(const K &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return internal_end(internal_upper_bound(key));
}
template <typename K>
const_iterator upper_bound(const K &key) const {
const_iterator upper_bound(const K &key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return internal_end(internal_upper_bound(key));
}
......@@ -1488,9 +1499,11 @@ class btree {
// the returned pair is equal to lower_bound(key). The second member of the
// pair is equal to upper_bound(key).
template <typename K>
std::pair<iterator, iterator> equal_range(const K &key);
std::pair<iterator, iterator> equal_range(const K &key)
ABSL_ATTRIBUTE_LIFETIME_BOUND;
template <typename K>
std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
std::pair<const_iterator, const_iterator> equal_range(const K &key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_cast<btree *>(this)->equal_range(key);
}
......@@ -1499,7 +1512,8 @@ class btree {
// Requirement: if `key` already exists in the btree, does not consume `args`.
// Requirement: `key` is never referenced after consuming `args`.
template <typename K, typename... Args>
std::pair<iterator, bool> insert_unique(const K &key, Args &&...args);
std::pair<iterator, bool> insert_unique(const K &key, Args &&...args)
ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Inserts with hint. Checks to see if the value should be placed immediately
// before `position` in the tree. If so, then the insertion will take
......@@ -1509,7 +1523,8 @@ class btree {
// Requirement: `key` is never referenced after consuming `args`.
template <typename K, typename... Args>
std::pair<iterator, bool> insert_hint_unique(iterator position, const K &key,
Args &&...args);
Args &&...args)
ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Insert a range of values into the btree.
// Note: the first overload avoids constructing a value_type if the key
......@@ -1526,11 +1541,12 @@ class btree {
// Inserts a value into the btree.
template <typename ValueType>
iterator insert_multi(const key_type &key, ValueType &&v);
iterator insert_multi(const key_type &key,
ValueType &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Inserts a value into the btree.
template <typename ValueType>
iterator insert_multi(ValueType &&v) {
iterator insert_multi(ValueType &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_multi(params_type::key(v), std::forward<ValueType>(v));
}
......@@ -1539,30 +1555,33 @@ class btree {
// amortized constant time. If not, the insertion will take amortized
// logarithmic time as if a call to insert_multi(v) were made.
template <typename ValueType>
iterator insert_hint_multi(iterator position, ValueType &&v);
iterator insert_hint_multi(iterator position,
ValueType &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Insert a range of values into the btree.
template <typename InputIterator>
void insert_iterator_multi(InputIterator b, InputIterator e);
void insert_iterator_multi(InputIterator b,
InputIterator e);
// Erase the specified iterator from the btree. The iterator must be valid
// (i.e. not equal to end()). Return an iterator pointing to the node after
// the one that was erased (or end() if none exists).
// Requirement: does not read the value at `*iter`.
iterator erase(iterator iter);
iterator erase(iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Erases range. Returns the number of keys erased and an iterator pointing
// to the element after the last erased element.
std::pair<size_type, iterator> erase_range(iterator begin, iterator end);
std::pair<size_type, iterator> erase_range(iterator begin, iterator end)
ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Finds an element with key equivalent to `key` or returns `end()` if `key`
// is not present.
template <typename K>
iterator find(const K &key) {
iterator find(const K &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return internal_end(internal_find(key));
}
template <typename K>
const_iterator find(const K &key) const {
const_iterator find(const K &key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return internal_end(internal_find(key));
}
......@@ -1572,7 +1591,7 @@ class btree {
// Swaps the contents of `this` and `other`.
void swap(btree &other);
const key_compare &key_comp() const noexcept {
const key_compare &key_comp() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rightmost_.template get<0>();
}
template <typename K1, typename K2>
......
......@@ -434,37 +434,43 @@ class btree_map_container : public btree_set_container<Tree> {
// Note: the nullptr template arguments and extra `const M&` overloads allow
// for supporting bitfield arguments.
template <typename K = key_type, class M>
std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k,
const M &obj) {
std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, const M &obj)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_impl(k, obj);
}
template <typename K = key_type, class M, K * = nullptr>
std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj) {
std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_impl(std::forward<K>(k), obj);
}
template <typename K = key_type, class M, M * = nullptr>
std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj) {
std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_impl(k, std::forward<M>(obj));
}
template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj) {
std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_impl(std::forward<K>(k), std::forward<M>(obj));
}
template <typename K = key_type, class M>
iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
const M &obj) {
const M &obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_hint_impl(hint, k, obj);
}
template <typename K = key_type, class M, K * = nullptr>
iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, const M &obj) {
iterator insert_or_assign(const_iterator hint, key_arg<K> &&k,
const M &obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_hint_impl(hint, std::forward<K>(k), obj);
}
template <typename K = key_type, class M, M * = nullptr>
iterator insert_or_assign(const_iterator hint, const key_arg<K> &k, M &&obj) {
iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
M &&obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_hint_impl(hint, k, std::forward<M>(obj));
}
template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, M &&obj) {
iterator insert_or_assign(const_iterator hint, key_arg<K> &&k,
M &&obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_hint_impl(hint, std::forward<K>(k),
std::forward<M>(obj));
}
......@@ -472,44 +478,48 @@ class btree_map_container : public btree_set_container<Tree> {
template <typename K = key_type, typename... Args,
typename absl::enable_if_t<
!std::is_convertible<K, const_iterator>::value, int> = 0>
std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&... args) {
std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&...args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace_impl(k, std::forward<Args>(args)...);
}
template <typename K = key_type, typename... Args,
typename absl::enable_if_t<
!std::is_convertible<K, const_iterator>::value, int> = 0>
std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&... args) {
std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&...args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
}
template <typename K = key_type, typename... Args>
iterator try_emplace(const_iterator hint, const key_arg<K> &k,
Args &&... args) {
Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
}
template <typename K = key_type, typename... Args>
iterator try_emplace(const_iterator hint, key_arg<K> &&k, Args &&... args) {
iterator try_emplace(const_iterator hint, key_arg<K> &&k,
Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace_hint_impl(hint, std::forward<K>(k),
std::forward<Args>(args)...);
}
template <typename K = key_type>
mapped_type &operator[](const key_arg<K> &k) {
mapped_type &operator[](const key_arg<K> &k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(k).first->second;
}
template <typename K = key_type>
mapped_type &operator[](key_arg<K> &&k) {
mapped_type &operator[](key_arg<K> &&k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(std::forward<K>(k)).first->second;
}
template <typename K = key_type>
mapped_type &at(const key_arg<K> &key) {
mapped_type &at(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = this->find(key);
if (it == this->end())
base_internal::ThrowStdOutOfRange("absl::btree_map::at");
return it->second;
}
template <typename K = key_type>
const mapped_type &at(const key_arg<K> &key) const {
const mapped_type &at(const key_arg<K> &key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = this->find(key);
if (it == this->end())
base_internal::ThrowStdOutOfRange("absl::btree_map::at");
......@@ -600,14 +610,18 @@ class btree_multiset_container : public btree_container<Tree> {
: btree_multiset_container(init.begin(), init.end(), alloc) {}
// Insertion routines.
iterator insert(const value_type &v) { return this->tree_.insert_multi(v); }
iterator insert(value_type &&v) {
iterator insert(const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_multi(v);
}
iterator insert(value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_multi(std::move(v));
}
iterator insert(const_iterator hint, const value_type &v) {
iterator insert(const_iterator hint,
const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_hint_multi(iterator(hint), v);
}
iterator insert(const_iterator hint, value_type &&v) {
iterator insert(const_iterator hint,
value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_hint_multi(iterator(hint), std::move(v));
}
template <typename InputIterator>
......@@ -618,21 +632,22 @@ class btree_multiset_container : public btree_container<Tree> {
this->tree_.insert_iterator_multi(init.begin(), init.end());
}
template <typename... Args>
iterator emplace(Args &&... args) {
iterator emplace(Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
// Use a node handle to manage a temp slot.
auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
std::forward<Args>(args)...);
return this->tree_.insert_multi(CommonAccess::GetSlot(node));
}
template <typename... Args>
iterator emplace_hint(const_iterator hint, Args &&... args) {
iterator emplace_hint(const_iterator hint,
Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
// Use a node handle to manage a temp slot.
auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
std::forward<Args>(args)...);
return this->tree_.insert_hint_multi(iterator(hint),
CommonAccess::GetSlot(node));
}
iterator insert(node_type &&node) {
iterator insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (!node) return this->end();
iterator res =
this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
......@@ -640,7 +655,8 @@ class btree_multiset_container : public btree_container<Tree> {
CommonAccess::Destroy(&node);
return res;
}
iterator insert(const_iterator hint, node_type &&node) {
iterator insert(const_iterator hint,
node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (!node) return this->end();
iterator res = this->tree_.insert_hint_multi(
iterator(hint),
......
......@@ -71,43 +71,51 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
// m.insert_or_assign(n, n);
template <class K = key_type, class V = mapped_type, K* = nullptr,
V* = nullptr>
std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, V&& v) {
std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, V&& v)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_impl(std::forward<K>(k), std::forward<V>(v));
}
template <class K = key_type, class V = mapped_type, K* = nullptr>
std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, const V& v) {
std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, const V& v)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_impl(std::forward<K>(k), v);
}
template <class K = key_type, class V = mapped_type, V* = nullptr>
std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, V&& v) {
std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, V&& v)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_impl(k, std::forward<V>(v));
}
template <class K = key_type, class V = mapped_type>
std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, const V& v) {
std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, const V& v)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign_impl(k, v);
}
template <class K = key_type, class V = mapped_type, K* = nullptr,
V* = nullptr>
iterator insert_or_assign(const_iterator, key_arg<K>&& k, V&& v) {
iterator insert_or_assign(const_iterator, key_arg<K>&& k,
V&& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign(std::forward<K>(k), std::forward<V>(v)).first;
}
template <class K = key_type, class V = mapped_type, K* = nullptr>
iterator insert_or_assign(const_iterator, key_arg<K>&& k, const V& v) {
iterator insert_or_assign(const_iterator, key_arg<K>&& k,
const V& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign(std::forward<K>(k), v).first;
}
template <class K = key_type, class V = mapped_type, V* = nullptr>
iterator insert_or_assign(const_iterator, const key_arg<K>& k, V&& v) {
iterator insert_or_assign(const_iterator, const key_arg<K>& k,
V&& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign(k, std::forward<V>(v)).first;
}
template <class K = key_type, class V = mapped_type>
iterator insert_or_assign(const_iterator, const key_arg<K>& k, const V& v) {
iterator insert_or_assign(const_iterator, const key_arg<K>& k,
const V& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert_or_assign(k, v).first;
}
......@@ -118,29 +126,33 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
typename std::enable_if<
!std::is_convertible<K, const_iterator>::value, int>::type = 0,
K* = nullptr>
std::pair<iterator, bool> try_emplace(key_arg<K>&& k, Args&&... args) {
std::pair<iterator, bool> try_emplace(key_arg<K>&& k, Args&&... args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
}
template <class K = key_type, class... Args,
typename std::enable_if<
!std::is_convertible<K, const_iterator>::value, int>::type = 0>
std::pair<iterator, bool> try_emplace(const key_arg<K>& k, Args&&... args) {
std::pair<iterator, bool> try_emplace(const key_arg<K>& k, Args&&... args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace_impl(k, std::forward<Args>(args)...);
}
template <class K = key_type, class... Args, K* = nullptr>
iterator try_emplace(const_iterator, key_arg<K>&& k, Args&&... args) {
iterator try_emplace(const_iterator, key_arg<K>&& k,
Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(std::forward<K>(k), std::forward<Args>(args)...).first;
}
template <class K = key_type, class... Args>
iterator try_emplace(const_iterator, const key_arg<K>& k, Args&&... args) {
iterator try_emplace(const_iterator, const key_arg<K>& k,
Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(k, std::forward<Args>(args)...).first;
}
template <class K = key_type, class P = Policy>
MappedReference<P> at(const key_arg<K>& key) {
MappedReference<P> at(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = this->find(key);
if (it == this->end()) {
base_internal::ThrowStdOutOfRange(
......@@ -150,7 +162,8 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
}
template <class K = key_type, class P = Policy>
MappedConstReference<P> at(const key_arg<K>& key) const {
MappedConstReference<P> at(const key_arg<K>& key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = this->find(key);
if (it == this->end()) {
base_internal::ThrowStdOutOfRange(
......@@ -160,18 +173,21 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
}
template <class K = key_type, class P = Policy, K* = nullptr>
MappedReference<P> operator[](key_arg<K>&& key) {
MappedReference<P> operator[](key_arg<K>&& key)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return Policy::value(&*try_emplace(std::forward<K>(key)).first);
}
template <class K = key_type, class P = Policy>
MappedReference<P> operator[](const key_arg<K>& key) {
MappedReference<P> operator[](const key_arg<K>& key)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return Policy::value(&*try_emplace(key).first);
}
private:
template <class K, class V>
std::pair<iterator, bool> insert_or_assign_impl(K&& k, V&& v) {
std::pair<iterator, bool> insert_or_assign_impl(K&& k, V&& v)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto res = this->find_or_prepare_insert(k);
if (res.second)
this->emplace_at(res.first, std::forward<K>(k), std::forward<V>(v));
......@@ -181,7 +197,8 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
}
template <class K = key_type, class... Args>
std::pair<iterator, bool> try_emplace_impl(K&& k, Args&&... args) {
std::pair<iterator, bool> try_emplace_impl(K&& k, Args&&... args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto res = this->find_or_prepare_insert(k);
if (res.second)
this->emplace_at(res.first, std::piecewise_construct,
......
......@@ -1828,19 +1828,25 @@ class raw_hash_set {
infoz().Unregister();
}
iterator begin() {
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = iterator_at(0);
it.skip_empty_or_deleted();
return it;
}
iterator end() { return iterator(common().generation_ptr()); }
iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(common().generation_ptr());
}
const_iterator begin() const {
const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_cast<raw_hash_set*>(this)->begin();
}
const_iterator end() const { return iterator(common().generation_ptr()); }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }
const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(common().generation_ptr());
}
const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return begin();
}
const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }
bool empty() const { return !size(); }
size_t size() const { return common().size_; }
......@@ -1887,7 +1893,7 @@ class raw_hash_set {
template <class T, RequiresInsertable<T> = 0, class T2 = T,
typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
T* = nullptr>
std::pair<iterator, bool> insert(T&& value) {
std::pair<iterator, bool> insert(T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return emplace(std::forward<T>(value));
}
......@@ -1905,7 +1911,8 @@ class raw_hash_set {
template <
class T, RequiresInsertable<const T&> = 0,
typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
std::pair<iterator, bool> insert(const T& value) {
std::pair<iterator, bool> insert(const T& value)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return emplace(value);
}
......@@ -1914,7 +1921,8 @@ class raw_hash_set {
//
// flat_hash_map<std::string, int> s;
// s.insert({"abc", 42});
std::pair<iterator, bool> insert(init_type&& value) {
std::pair<iterator, bool> insert(init_type&& value)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return emplace(std::move(value));
}
......@@ -1923,18 +1931,20 @@ class raw_hash_set {
template <class T, RequiresInsertable<T> = 0, class T2 = T,
typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
T* = nullptr>
iterator insert(const_iterator, T&& value) {
iterator insert(const_iterator, T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert(std::forward<T>(value)).first;
}
template <
class T, RequiresInsertable<const T&> = 0,
typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
iterator insert(const_iterator, const T& value) {
iterator insert(const_iterator,
const T& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert(value).first;
}
iterator insert(const_iterator, init_type&& value) {
iterator insert(const_iterator,
init_type&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert(std::move(value)).first;
}
......@@ -1952,7 +1962,7 @@ class raw_hash_set {
insert(ilist.begin(), ilist.end());
}
insert_return_type insert(node_type&& node) {
insert_return_type insert(node_type&& node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (!node) return {end(), false, node_type()};
const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));
auto res = PolicyTraits::apply(
......@@ -1966,7 +1976,8 @@ class raw_hash_set {
}
}
iterator insert(const_iterator, node_type&& node) {
iterator insert(const_iterator,
node_type&& node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto res = insert(std::move(node));
node = std::move(res.node);
return res.position;
......@@ -1983,7 +1994,8 @@ class raw_hash_set {
// m.emplace("abc", "xyz");
template <class... Args, typename std::enable_if<
IsDecomposable<Args...>::value, int>::type = 0>
std::pair<iterator, bool> emplace(Args&&... args) {
std::pair<iterator, bool> emplace(Args&&... args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return PolicyTraits::apply(EmplaceDecomposable{*this},
std::forward<Args>(args)...);
}
......@@ -1993,7 +2005,8 @@ class raw_hash_set {
// destroys.
template <class... Args, typename std::enable_if<
!IsDecomposable<Args...>::value, int>::type = 0>
std::pair<iterator, bool> emplace(Args&&... args) {
std::pair<iterator, bool> emplace(Args&&... args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
alignas(slot_type) unsigned char raw[sizeof(slot_type)];
slot_type* slot = reinterpret_cast<slot_type*>(&raw);
......@@ -2003,7 +2016,8 @@ class raw_hash_set {
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args) {
iterator emplace_hint(const_iterator,
Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return emplace(std::forward<Args>(args)...).first;
}
......@@ -2053,7 +2067,8 @@ class raw_hash_set {
};
template <class K = key_type, class F>
iterator lazy_emplace(const key_arg<K>& key, F&& f) {
iterator lazy_emplace(const key_arg<K>& key,
F&& f) ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto res = find_or_prepare_insert(key);
if (res.second) {
slot_type* slot = slot_array() + res.first;
......@@ -2103,7 +2118,8 @@ class raw_hash_set {
erase_meta_only(it);
}
iterator erase(const_iterator first, const_iterator last) {
iterator erase(const_iterator first,
const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
while (first != last) {
erase(first++);
}
......@@ -2232,7 +2248,8 @@ class raw_hash_set {
// 2. The type of the key argument doesn't have to be key_type. This is so
// called heterogeneous key support.
template <class K = key_type>
iterator find(const key_arg<K>& key, size_t hash) {
iterator find(const key_arg<K>& key,
size_t hash) ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto seq = probe(common(), hash);
slot_type* slot_ptr = slot_array();
const ctrl_t* ctrl = control();
......@@ -2250,17 +2267,19 @@ class raw_hash_set {
}
}
template <class K = key_type>
iterator find(const key_arg<K>& key) {
iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
prefetch_heap_block();
return find(key, hash_ref()(key));
}
template <class K = key_type>
const_iterator find(const key_arg<K>& key, size_t hash) const {
const_iterator find(const key_arg<K>& key,
size_t hash) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_cast<raw_hash_set*>(this)->find(key, hash);
}
template <class K = key_type>
const_iterator find(const key_arg<K>& key) const {
const_iterator find(const key_arg<K>& key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
prefetch_heap_block();
return find(key, hash_ref()(key));
}
......@@ -2271,14 +2290,15 @@ class raw_hash_set {
}
template <class K = key_type>
std::pair<iterator, iterator> equal_range(const key_arg<K>& key) {
std::pair<iterator, iterator> equal_range(const key_arg<K>& key)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = find(key);
if (it != end()) return {it, std::next(it)};
return {it, it};
}
template <class K = key_type>
std::pair<const_iterator, const_iterator> equal_range(
const key_arg<K>& key) const {
const key_arg<K>& key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = find(key);
if (it != end()) return {it, std::next(it)};
return {it, it};
......@@ -2606,10 +2626,10 @@ class raw_hash_set {
"constructed value does not match the lookup key");
}
iterator iterator_at(size_t i) {
iterator iterator_at(size_t i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return {control() + i, slot_array() + i, common().generation_ptr()};
}
const_iterator iterator_at(size_t i) const {
const_iterator iterator_at(size_t i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return {control() + i, slot_array() + i, common().generation_ptr()};
}
......
......@@ -53,6 +53,7 @@
#ifndef ABSL_TYPES_ANY_H_
#define ABSL_TYPES_ANY_H_
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/utility/utility.h"
......@@ -288,7 +289,7 @@ class any {
typename T, typename... Args, typename VT = absl::decay_t<T>,
absl::enable_if_t<std::is_copy_constructible<VT>::value &&
std::is_constructible<VT, Args...>::value>* = nullptr>
VT& emplace(Args&&... args) {
VT& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
reset(); // NOTE: reset() is required here even in the world of exceptions.
Obj<VT>* const object_ptr =
new Obj<VT>(in_place, std::forward<Args>(args)...);
......@@ -312,7 +313,8 @@ class any {
absl::enable_if_t<std::is_copy_constructible<VT>::value &&
std::is_constructible<VT, std::initializer_list<U>&,
Args...>::value>* = nullptr>
VT& emplace(std::initializer_list<U> ilist, Args&&... args) {
VT& emplace(std::initializer_list<U> ilist,
Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
reset(); // NOTE: reset() is required here even in the world of exceptions.
Obj<VT>* const object_ptr =
new Obj<VT>(in_place, ilist, std::forward<Args>(args)...);
......
......@@ -357,7 +357,7 @@ class optional : private optional_internal::optional_data<T>,
template <typename... Args,
typename = typename std::enable_if<
std::is_constructible<T, Args&&...>::value>::type>
T& emplace(Args&&... args) {
T& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
this->destruct();
this->construct(std::forward<Args>(args)...);
return reference();
......@@ -377,7 +377,8 @@ class optional : private optional_internal::optional_data<T>,
template <typename U, typename... Args,
typename = typename std::enable_if<std::is_constructible<
T, std::initializer_list<U>&, Args&&...>::value>::type>
T& emplace(std::initializer_list<U> il, Args&&... args) {
T& emplace(std::initializer_list<U> il,
Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
this->destruct();
this->construct(il, std::forward<Args>(args)...);
return reference();
......@@ -414,11 +415,11 @@ class optional : private optional_internal::optional_data<T>,
// `optional` is empty, behavior is undefined.
//
// If you need myOpt->foo in constexpr, use (*myOpt).foo instead.
const T* operator->() const {
const T* operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(this->engaged_);
return std::addressof(this->data_);
}
T* operator->() {
T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(this->engaged_);
return std::addressof(this->data_);
}
......@@ -427,17 +428,17 @@ class optional : private optional_internal::optional_data<T>,
//
// Accesses the underlying `T` value of an `optional`. If the `optional` is
// empty, behavior is undefined.
constexpr const T& operator*() const& {
constexpr const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
return ABSL_HARDENING_ASSERT(this->engaged_), reference();
}
T& operator*() & {
T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(this->engaged_);
return reference();
}
constexpr const T&& operator*() const && {
constexpr const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND {
return ABSL_HARDENING_ASSERT(this->engaged_), absl::move(reference());
}
T&& operator*() && {
T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(this->engaged_);
return std::move(reference());
}
......@@ -472,23 +473,24 @@ class optional : private optional_internal::optional_data<T>,
// and lvalue/rvalue-ness of the `optional` is preserved to the view of
// the `T` sub-object. Throws `absl::bad_optional_access` when the `optional`
// is empty.
constexpr const T& value() const & {
constexpr const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
return static_cast<bool>(*this)
? reference()
: (optional_internal::throw_bad_optional_access(), reference());
}
T& value() & {
T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
return static_cast<bool>(*this)
? reference()
: (optional_internal::throw_bad_optional_access(), reference());
}
T&& value() && { // NOLINT(build/c++11)
T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND { // NOLINT(build/c++11)
return std::move(
static_cast<bool>(*this)
? reference()
: (optional_internal::throw_bad_optional_access(), reference()));
}
constexpr const T&& value() const && { // NOLINT(build/c++11)
constexpr const T&& value()
const&& ABSL_ATTRIBUTE_LIFETIME_BOUND { // NOLINT(build/c++11)
return absl::move(
static_cast<bool>(*this)
? reference()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment