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