Commit 020619c4 by Abseil Team Committed by Andy Getz

Export of internal Abseil changes

--
336f161ad8cb2cc3e1a6bbcbbb8c5b692ee59789 by Derek Mauro <dmauro@google.com>:

Internal change

PiperOrigin-RevId: 398308807

--
80d512823d17561a45feca81f37713a91a175349 by Abseil Team <absl-team@google.com>:

Internal change.

PiperOrigin-RevId: 398257218

--
f1f9792000355eb1d0c11b17800048491662a218 by Abseil Team <absl-team@google.com>:

Fix documentation for btree_multi{map,set}::merge to match behavior for elements with equivalent keys.

PiperOrigin-RevId: 398071060

--
8a9a302aebf2419e83f0c7dc5a63c33d26b807a3 by James Y Knight <jyknight@google.com>:

Silence -Wunused-value warning newly emitted by ToT Clang.

The value is being intentionally ignored, as the purpose of the call is only to eliminate this overload via SFINAE when `GenT{}` is not constant evaluable.

PiperOrigin-RevId: 397861294
GitOrigin-RevId: 336f161ad8cb2cc3e1a6bbcbbb8c5b692ee59789
Change-Id: I946e1d22619f92ce6a424c8c13a20a50b39ed463
parent d4af654d
...@@ -693,9 +693,8 @@ class btree_multimap ...@@ -693,9 +693,8 @@ class btree_multimap
// btree_multimap::merge() // btree_multimap::merge()
// //
// Extracts elements from a given `source` btree_multimap into this // Extracts all elements from a given `source` btree_multimap into this
// `btree_multimap`. If the destination `btree_multimap` already contains an // `btree_multimap`.
// element with an equivalent key, that element is not extracted.
using Base::merge; using Base::merge;
// btree_multimap::swap(btree_multimap& other) // btree_multimap::swap(btree_multimap& other)
......
...@@ -604,9 +604,8 @@ class btree_multiset ...@@ -604,9 +604,8 @@ class btree_multiset
// btree_multiset::merge() // btree_multiset::merge()
// //
// Extracts elements from a given `source` btree_multiset into this // Extracts all elements from a given `source` btree_multiset into this
// `btree_multiset`. If the destination `btree_multiset` already contains an // `btree_multiset`.
// element with an equivalent key, that element is not extracted.
using Base::merge; using Base::merge;
// btree_multiset::swap(btree_multiset& other) // btree_multiset::swap(btree_multiset& other)
......
...@@ -207,8 +207,8 @@ class InlinedVector { ...@@ -207,8 +207,8 @@ class InlinedVector {
other.storage_.SetInlinedSize(0); other.storage_.SetInlinedSize(0);
} else if (other.storage_.GetIsAllocated()) { } else if (other.storage_.GetIsAllocated()) {
storage_.SetAllocatedData(other.storage_.GetAllocatedData(), storage_.SetAllocation({other.storage_.GetAllocatedData(),
other.storage_.GetAllocatedCapacity()); other.storage_.GetAllocatedCapacity()});
storage_.SetAllocatedSize(other.storage_.GetSize()); storage_.SetAllocatedSize(other.storage_.GetSize());
other.storage_.SetInlinedSize(0); other.storage_.SetInlinedSize(0);
...@@ -242,8 +242,8 @@ class InlinedVector { ...@@ -242,8 +242,8 @@ class InlinedVector {
other.storage_.SetInlinedSize(0); other.storage_.SetInlinedSize(0);
} else if ((storage_.GetAllocator() == other.storage_.GetAllocator()) && } else if ((storage_.GetAllocator() == other.storage_.GetAllocator()) &&
other.storage_.GetIsAllocated()) { other.storage_.GetIsAllocated()) {
storage_.SetAllocatedData(other.storage_.GetAllocatedData(), storage_.SetAllocation({other.storage_.GetAllocatedData(),
other.storage_.GetAllocatedCapacity()); other.storage_.GetAllocatedCapacity()});
storage_.SetAllocatedSize(other.storage_.GetSize()); storage_.SetAllocatedSize(other.storage_.GetSize());
other.storage_.SetInlinedSize(0); other.storage_.SetInlinedSize(0);
...@@ -735,15 +735,12 @@ class InlinedVector { ...@@ -735,15 +735,12 @@ class InlinedVector {
// `InlinedVector::shrink_to_fit()` // `InlinedVector::shrink_to_fit()`
// //
// Reduces memory usage by freeing unused memory. After being called, calls to // Attempts to reduce memory usage by moving elements to (or keeping elements
// `capacity()` will be equal to `max(N, size())`. // in) the smallest available buffer sufficient for containing `size()`
// elements.
// //
// If `size() <= N` and the inlined vector contains allocated memory, the // If `size()` is sufficiently small, the elements will be moved into (or kept
// elements will all be moved to the inlined space and the allocated memory // in) the inlined space.
// will be deallocated.
//
// If `size() > N` and `size() < capacity()`, the elements will be moved to a
// smaller allocation.
void shrink_to_fit() { void shrink_to_fit() {
if (storage_.GetIsAllocated()) { if (storage_.GetIsAllocated()) {
storage_.ShrinkToFit(); storage_.ShrinkToFit();
......
...@@ -21,8 +21,11 @@ ...@@ -21,8 +21,11 @@
#include <iterator> #include <iterator>
#include <limits> #include <limits>
#include <memory> #include <memory>
#include <new>
#include <type_traits>
#include <utility> #include <utility>
#include "absl/base/attributes.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/container/internal/compressed_tuple.h" #include "absl/container/internal/compressed_tuple.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
...@@ -102,6 +105,27 @@ void DestroyElements(NoTypeDeduction<A>& allocator, Pointer<A> destroy_first, ...@@ -102,6 +105,27 @@ void DestroyElements(NoTypeDeduction<A>& allocator, Pointer<A> destroy_first,
} }
} }
template <typename A>
struct Allocation {
Pointer<A> data;
SizeType<A> capacity;
};
template <typename A,
bool IsOverAligned =
(alignof(ValueType<A>) > ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT)>
struct MallocAdapter {
static Allocation<A> Allocate(A& allocator, SizeType<A> requested_capacity) {
return {AllocatorTraits<A>::allocate(allocator, requested_capacity),
requested_capacity};
}
static void Deallocate(A& allocator, Pointer<A> pointer,
SizeType<A> capacity) {
AllocatorTraits<A>::deallocate(allocator, pointer, capacity);
}
};
// If kUseMemcpy is true, memcpy(dst, src, n); else do nothing. // If kUseMemcpy is true, memcpy(dst, src, n); else do nothing.
// Useful to avoid compiler warnings when memcpy() is used for T values // Useful to avoid compiler warnings when memcpy() is used for T values
// that are not trivially copyable in non-reachable code. // that are not trivially copyable in non-reachable code.
...@@ -201,7 +225,7 @@ class AllocationTransaction { ...@@ -201,7 +225,7 @@ class AllocationTransaction {
~AllocationTransaction() { ~AllocationTransaction() {
if (DidAllocate()) { if (DidAllocate()) {
AllocatorTraits<A>::deallocate(GetAllocator(), GetData(), GetCapacity()); MallocAdapter<A>::Deallocate(GetAllocator(), GetData(), GetCapacity());
} }
} }
...@@ -213,18 +237,27 @@ class AllocationTransaction { ...@@ -213,18 +237,27 @@ class AllocationTransaction {
SizeType<A>& GetCapacity() { return capacity_; } SizeType<A>& GetCapacity() { return capacity_; }
bool DidAllocate() { return GetData() != nullptr; } bool DidAllocate() { return GetData() != nullptr; }
Pointer<A> Allocate(SizeType<A> capacity) {
GetData() = AllocatorTraits<A>::allocate(GetAllocator(), capacity); Pointer<A> Allocate(SizeType<A> requested_capacity) {
GetCapacity() = capacity; Allocation<A> result =
return GetData(); MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
GetData() = result.data;
GetCapacity() = result.capacity;
return result.data;
}
ABSL_MUST_USE_RESULT Allocation<A> Release() && {
Allocation<A> result = {GetData(), GetCapacity()};
Reset();
return result;
} }
private:
void Reset() { void Reset() {
GetData() = nullptr; GetData() = nullptr;
GetCapacity() = 0; GetCapacity() = 0;
} }
private:
container_internal::CompressedTuple<A, Pointer<A>> allocator_data_; container_internal::CompressedTuple<A, Pointer<A>> allocator_data_;
SizeType<A> capacity_; SizeType<A> capacity_;
}; };
...@@ -405,15 +438,9 @@ class Storage { ...@@ -405,15 +438,9 @@ class Storage {
GetSizeAndIsAllocated() -= count << static_cast<SizeType<A>>(1); GetSizeAndIsAllocated() -= count << static_cast<SizeType<A>>(1);
} }
void SetAllocatedData(Pointer<A> data, SizeType<A> capacity) { void SetAllocation(Allocation<A> allocation) {
data_.allocated.allocated_data = data; data_.allocated.allocated_data = allocation.data;
data_.allocated.allocated_capacity = capacity; data_.allocated.allocated_capacity = allocation.capacity;
}
void AcquireAllocatedData(AllocationTransaction<A>& allocation_tx) {
SetAllocatedData(allocation_tx.GetData(), allocation_tx.GetCapacity());
allocation_tx.Reset();
} }
void MemcpyFrom(const Storage& other_storage) { void MemcpyFrom(const Storage& other_storage) {
...@@ -425,8 +452,8 @@ class Storage { ...@@ -425,8 +452,8 @@ class Storage {
void DeallocateIfAllocated() { void DeallocateIfAllocated() {
if (GetIsAllocated()) { if (GetIsAllocated()) {
AllocatorTraits<A>::deallocate(GetAllocator(), GetAllocatedData(), MallocAdapter<A>::Deallocate(GetAllocator(), GetAllocatedData(),
GetAllocatedCapacity()); GetAllocatedCapacity());
} }
} }
...@@ -476,9 +503,11 @@ void Storage<T, N, A>::InitFrom(const Storage& other) { ...@@ -476,9 +503,11 @@ void Storage<T, N, A>::InitFrom(const Storage& other) {
// Because this is only called from the `InlinedVector` constructors, it's // Because this is only called from the `InlinedVector` constructors, it's
// safe to take on the allocation with size `0`. If `ConstructElements(...)` // safe to take on the allocation with size `0`. If `ConstructElements(...)`
// throws, deallocation will be automatically handled by `~Storage()`. // throws, deallocation will be automatically handled by `~Storage()`.
SizeType<A> new_capacity = ComputeCapacity(GetInlinedCapacity(), n); SizeType<A> requested_capacity = ComputeCapacity(GetInlinedCapacity(), n);
dst = AllocatorTraits<A>::allocate(GetAllocator(), new_capacity); Allocation<A> allocation =
SetAllocatedData(dst, new_capacity); MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
SetAllocation(allocation);
dst = allocation.data;
src = other.GetAllocatedData(); src = other.GetAllocatedData();
} }
if (IsMemcpyOk<A>::value) { if (IsMemcpyOk<A>::value) {
...@@ -503,9 +532,12 @@ auto Storage<T, N, A>::Initialize(ValueAdapter values, SizeType<A> new_size) ...@@ -503,9 +532,12 @@ auto Storage<T, N, A>::Initialize(ValueAdapter values, SizeType<A> new_size)
// Because this is only called from the `InlinedVector` constructors, it's // Because this is only called from the `InlinedVector` constructors, it's
// safe to take on the allocation with size `0`. If `ConstructElements(...)` // safe to take on the allocation with size `0`. If `ConstructElements(...)`
// throws, deallocation will be automatically handled by `~Storage()`. // throws, deallocation will be automatically handled by `~Storage()`.
SizeType<A> new_capacity = ComputeCapacity(GetInlinedCapacity(), new_size); SizeType<A> requested_capacity =
construct_data = AllocatorTraits<A>::allocate(GetAllocator(), new_capacity); ComputeCapacity(GetInlinedCapacity(), new_size);
SetAllocatedData(construct_data, new_capacity); Allocation<A> allocation =
MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
construct_data = allocation.data;
SetAllocation(allocation);
SetIsAllocated(); SetIsAllocated();
} else { } else {
construct_data = GetInlinedData(); construct_data = GetInlinedData();
...@@ -532,8 +564,9 @@ auto Storage<T, N, A>::Assign(ValueAdapter values, SizeType<A> new_size) ...@@ -532,8 +564,9 @@ auto Storage<T, N, A>::Assign(ValueAdapter values, SizeType<A> new_size)
absl::Span<ValueType<A>> destroy_loop; absl::Span<ValueType<A>> destroy_loop;
if (new_size > storage_view.capacity) { if (new_size > storage_view.capacity) {
SizeType<A> new_capacity = ComputeCapacity(storage_view.capacity, new_size); SizeType<A> requested_capacity =
construct_loop = {allocation_tx.Allocate(new_capacity), new_size}; ComputeCapacity(storage_view.capacity, new_size);
construct_loop = {allocation_tx.Allocate(requested_capacity), new_size};
destroy_loop = {storage_view.data, storage_view.size}; destroy_loop = {storage_view.data, storage_view.size};
} else if (new_size > storage_view.size) { } else if (new_size > storage_view.size) {
assign_loop = {storage_view.data, storage_view.size}; assign_loop = {storage_view.data, storage_view.size};
...@@ -553,7 +586,7 @@ auto Storage<T, N, A>::Assign(ValueAdapter values, SizeType<A> new_size) ...@@ -553,7 +586,7 @@ auto Storage<T, N, A>::Assign(ValueAdapter values, SizeType<A> new_size)
if (allocation_tx.DidAllocate()) { if (allocation_tx.DidAllocate()) {
DeallocateIfAllocated(); DeallocateIfAllocated();
AcquireAllocatedData(allocation_tx); SetAllocation(std::move(allocation_tx).Release());
SetIsAllocated(); SetIsAllocated();
} }
...@@ -583,8 +616,9 @@ auto Storage<T, N, A>::Resize(ValueAdapter values, SizeType<A> new_size) ...@@ -583,8 +616,9 @@ auto Storage<T, N, A>::Resize(ValueAdapter values, SizeType<A> new_size)
// Use transactional wrappers for the first two steps so we can roll // Use transactional wrappers for the first two steps so we can roll
// back if necessary due to exceptions. // back if necessary due to exceptions.
AllocationTransaction<A> allocation_tx(alloc); AllocationTransaction<A> allocation_tx(alloc);
SizeType<A> new_capacity = ComputeCapacity(storage_view.capacity, new_size); SizeType<A> requested_capacity =
Pointer<A> new_data = allocation_tx.Allocate(new_capacity); ComputeCapacity(storage_view.capacity, new_size);
Pointer<A> new_data = allocation_tx.Allocate(requested_capacity);
ConstructionTransaction<A> construction_tx(alloc); ConstructionTransaction<A> construction_tx(alloc);
construction_tx.Construct(new_data + size, values, new_size - size); construction_tx.Construct(new_data + size, values, new_size - size);
...@@ -596,7 +630,7 @@ auto Storage<T, N, A>::Resize(ValueAdapter values, SizeType<A> new_size) ...@@ -596,7 +630,7 @@ auto Storage<T, N, A>::Resize(ValueAdapter values, SizeType<A> new_size)
DestroyElements<A>(alloc, base, size); DestroyElements<A>(alloc, base, size);
construction_tx.Commit(); construction_tx.Commit();
DeallocateIfAllocated(); DeallocateIfAllocated();
AcquireAllocatedData(allocation_tx); SetAllocation(std::move(allocation_tx).Release());
SetIsAllocated(); SetIsAllocated();
} }
SetSize(new_size); SetSize(new_size);
...@@ -621,8 +655,9 @@ auto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values, ...@@ -621,8 +655,9 @@ auto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values,
IteratorValueAdapter<A, MoveIterator<A>> move_values( IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(storage_view.data)); MoveIterator<A>(storage_view.data));
SizeType<A> new_capacity = ComputeCapacity(storage_view.capacity, new_size); SizeType<A> requested_capacity =
Pointer<A> new_data = allocation_tx.Allocate(new_capacity); ComputeCapacity(storage_view.capacity, new_size);
Pointer<A> new_data = allocation_tx.Allocate(requested_capacity);
construction_tx.Construct(new_data + insert_index, values, insert_count); construction_tx.Construct(new_data + insert_index, values, insert_count);
...@@ -636,7 +671,7 @@ auto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values, ...@@ -636,7 +671,7 @@ auto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values,
construction_tx.Commit(); construction_tx.Commit();
move_construction_tx.Commit(); move_construction_tx.Commit();
DeallocateIfAllocated(); DeallocateIfAllocated();
AcquireAllocatedData(allocation_tx); SetAllocation(std::move(allocation_tx).Release());
SetAllocatedSize(new_size); SetAllocatedSize(new_size);
return Iterator<A>(new_data + insert_index); return Iterator<A>(new_data + insert_index);
...@@ -717,8 +752,8 @@ auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> Reference<A> { ...@@ -717,8 +752,8 @@ auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> Reference<A> {
AllocationTransaction<A> allocation_tx(GetAllocator()); AllocationTransaction<A> allocation_tx(GetAllocator());
IteratorValueAdapter<A, MoveIterator<A>> move_values( IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(storage_view.data)); MoveIterator<A>(storage_view.data));
SizeType<A> new_capacity = NextCapacity(storage_view.capacity); SizeType<A> requested_capacity = NextCapacity(storage_view.capacity);
Pointer<A> construct_data = allocation_tx.Allocate(new_capacity); Pointer<A> construct_data = allocation_tx.Allocate(requested_capacity);
Pointer<A> last_ptr = construct_data + storage_view.size; Pointer<A> last_ptr = construct_data + storage_view.size;
// Construct new element. // Construct new element.
...@@ -737,7 +772,7 @@ auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> Reference<A> { ...@@ -737,7 +772,7 @@ auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> Reference<A> {
DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size); DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size);
DeallocateIfAllocated(); DeallocateIfAllocated();
AcquireAllocatedData(allocation_tx); SetAllocation(std::move(allocation_tx).Release());
SetIsAllocated(); SetIsAllocated();
AddSize(1); AddSize(1);
return *last_ptr; return *last_ptr;
...@@ -778,9 +813,9 @@ auto Storage<T, N, A>::Reserve(SizeType<A> requested_capacity) -> void { ...@@ -778,9 +813,9 @@ auto Storage<T, N, A>::Reserve(SizeType<A> requested_capacity) -> void {
IteratorValueAdapter<A, MoveIterator<A>> move_values( IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(storage_view.data)); MoveIterator<A>(storage_view.data));
SizeType<A> new_capacity = SizeType<A> new_requested_capacity =
ComputeCapacity(storage_view.capacity, requested_capacity); ComputeCapacity(storage_view.capacity, requested_capacity);
Pointer<A> new_data = allocation_tx.Allocate(new_capacity); Pointer<A> new_data = allocation_tx.Allocate(new_requested_capacity);
ConstructElements<A>(GetAllocator(), new_data, move_values, ConstructElements<A>(GetAllocator(), new_data, move_values,
storage_view.size); storage_view.size);
...@@ -788,7 +823,7 @@ auto Storage<T, N, A>::Reserve(SizeType<A> requested_capacity) -> void { ...@@ -788,7 +823,7 @@ auto Storage<T, N, A>::Reserve(SizeType<A> requested_capacity) -> void {
DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size); DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size);
DeallocateIfAllocated(); DeallocateIfAllocated();
AcquireAllocatedData(allocation_tx); SetAllocation(std::move(allocation_tx).Release());
SetIsAllocated(); SetIsAllocated();
} }
...@@ -809,8 +844,12 @@ auto Storage<T, N, A>::ShrinkToFit() -> void { ...@@ -809,8 +844,12 @@ auto Storage<T, N, A>::ShrinkToFit() -> void {
Pointer<A> construct_data; Pointer<A> construct_data;
if (storage_view.size > GetInlinedCapacity()) { if (storage_view.size > GetInlinedCapacity()) {
SizeType<A> new_capacity = storage_view.size; SizeType<A> requested_capacity = storage_view.size;
construct_data = allocation_tx.Allocate(new_capacity); construct_data = allocation_tx.Allocate(requested_capacity);
if (allocation_tx.GetCapacity() >= storage_view.capacity) {
// Already using the smallest available heap allocation.
return;
}
} else { } else {
construct_data = GetInlinedData(); construct_data = GetInlinedData();
} }
...@@ -820,17 +859,17 @@ auto Storage<T, N, A>::ShrinkToFit() -> void { ...@@ -820,17 +859,17 @@ auto Storage<T, N, A>::ShrinkToFit() -> void {
storage_view.size); storage_view.size);
} }
ABSL_INTERNAL_CATCH_ANY { ABSL_INTERNAL_CATCH_ANY {
SetAllocatedData(storage_view.data, storage_view.capacity); SetAllocation({storage_view.data, storage_view.capacity});
ABSL_INTERNAL_RETHROW; ABSL_INTERNAL_RETHROW;
} }
DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size); DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size);
AllocatorTraits<A>::deallocate(GetAllocator(), storage_view.data, MallocAdapter<A>::Deallocate(GetAllocator(), storage_view.data,
storage_view.capacity); storage_view.capacity);
if (allocation_tx.DidAllocate()) { if (allocation_tx.DidAllocate()) {
AcquireAllocatedData(allocation_tx); SetAllocation(std::move(allocation_tx).Release());
} else { } else {
UnsetIsAllocated(); UnsetIsAllocated();
} }
...@@ -881,16 +920,16 @@ auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void { ...@@ -881,16 +920,16 @@ auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void {
inlined_ptr->GetSize()); inlined_ptr->GetSize());
} }
ABSL_INTERNAL_CATCH_ANY { ABSL_INTERNAL_CATCH_ANY {
allocated_ptr->SetAllocatedData(allocated_storage_view.data, allocated_ptr->SetAllocation(
allocated_storage_view.capacity); {allocated_storage_view.data, allocated_storage_view.capacity});
ABSL_INTERNAL_RETHROW; ABSL_INTERNAL_RETHROW;
} }
DestroyElements<A>(inlined_ptr->GetAllocator(), DestroyElements<A>(inlined_ptr->GetAllocator(),
inlined_ptr->GetInlinedData(), inlined_ptr->GetSize()); inlined_ptr->GetInlinedData(), inlined_ptr->GetSize());
inlined_ptr->SetAllocatedData(allocated_storage_view.data, inlined_ptr->SetAllocation(
allocated_storage_view.capacity); {allocated_storage_view.data, allocated_storage_view.capacity});
} }
swap(GetSizeAndIsAllocated(), other_storage_ptr->GetSizeAndIsAllocated()); swap(GetSizeAndIsAllocated(), other_storage_ptr->GetSizeAndIsAllocated());
......
...@@ -290,7 +290,7 @@ constexpr T InitDefaultValue(EmptyBraces) { ...@@ -290,7 +290,7 @@ constexpr T InitDefaultValue(EmptyBraces) {
template <typename ValueT, typename GenT, template <typename ValueT, typename GenT,
typename std::enable_if<std::is_integral<ValueT>::value, int>::type = typename std::enable_if<std::is_integral<ValueT>::value, int>::type =
(GenT{}, 0)> ((void)GenT{}, 0)>
constexpr FlagDefaultArg DefaultArg(int) { constexpr FlagDefaultArg DefaultArg(int) {
return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord}; return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord};
} }
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#ifndef ABSL_META_TYPE_TRAITS_H_ #ifndef ABSL_META_TYPE_TRAITS_H_
#define ABSL_META_TYPE_TRAITS_H_ #define ABSL_META_TYPE_TRAITS_H_
#include <stddef.h> #include <cstddef>
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
...@@ -47,6 +47,14 @@ ...@@ -47,6 +47,14 @@
#define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1 #define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
#endif #endif
// Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17
// feature.
#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT __STDCPP_DEFAULT_NEW_ALIGNMENT__
#else // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT alignof(std::max_align_t)
#endif // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
......
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