1#if !defined(phmap_base_h_guard_)
2#define phmap_base_h_guard_
40#include <initializer_list>
51#include "phmap_config.h"
53#ifdef PHMAP_HAVE_SHARED_MUTEX
54 #include <shared_mutex>
59 #pragma warning(disable : 4514)
60 #pragma warning(disable : 4582)
61 #pragma warning(disable : 4625)
62 #pragma warning(disable : 4626)
63 #pragma warning(disable : 4710)
64 #pragma warning(disable : 4711)
65 #pragma warning(disable : 4820)
70template <
class T>
using Allocator =
typename std::allocator<T>;
72template<
class T1,
class T2>
using Pair =
typename std::pair<T1, T2>;
77 inline bool operator()(
const T& a,
const T& b)
const
79 return std::equal_to<T>()(a, b);
86 inline bool operator()(
const T& a,
const T& b)
const
88 return std::less<T>()(a, b);
92namespace type_traits_internal {
94template <
typename... Ts>
103template <
size_t Len,
typename T = std::aligned_storage<Len>>
106template <
size_t Len,
size_t Align>
108 std::aligned_storage<Len, Align>> {
109 static constexpr size_t value = Align;
123template <
class Enabler,
template <
class...>
class Op,
class... Args>
125 using type = std::false_type;
128template <
template <
class...>
class Op,
class... Args>
130 using type = std::true_type;
133template <
template <
class...>
class Op,
class... Args>
136template <
class Enabler,
class To,
template <
class...>
class Op,
class... Args>
138 using type = std::false_type;
141template <
class To,
template <
class...>
class Op,
class... Args>
143 typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
145 using type = std::true_type;
148template <
class To,
template <
class...>
class Op,
class... Args>
153using IsCopyAssignableImpl =
154 decltype(std::declval<T&>() = std::declval<const T&>());
157using IsMoveAssignableImpl =
decltype(std::declval<T&>() = std::declval<T&&>());
163 type_traits_internal::IsCopyAssignableImpl, T> {
168 type_traits_internal::IsMoveAssignableImpl, T> {
185template <
typename... Ts>
199template <
typename... Ts>
202template <
typename T,
typename... Ts>
204 : std::conditional<T::value, conjunction<Ts...>, T>::type {};
223template <
typename... Ts>
226template <
typename T,
typename... Ts>
228 std::conditional<T::value, T, disjunction<Ts...>>::type {};
237struct negation : std::integral_constant<bool, !T::value> {};
241 : std::integral_constant<bool, __has_trivial_destructor(T) &&
242 std::is_destructible<T>::value> {};
246 : std::integral_constant<bool, __has_trivial_constructor(T) &&
247 std::is_default_constructible<T>::value &&
248 is_trivially_destructible<T>::value> {};
252 : std::integral_constant<bool, __has_trivial_copy(T) &&
253 std::is_copy_constructible<T>::value &&
254 is_trivially_destructible<T>::value> {};
258 : std::integral_constant<
259 bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
260 phmap::is_copy_assignable<T>::value> {};
267using remove_cv_t =
typename std::remove_cv<T>::type;
270using remove_const_t =
typename std::remove_const<T>::type;
273using remove_volatile_t =
typename std::remove_volatile<T>::type;
276using add_cv_t =
typename std::add_cv<T>::type;
279using add_const_t =
typename std::add_const<T>::type;
282using add_volatile_t =
typename std::add_volatile<T>::type;
285using remove_reference_t =
typename std::remove_reference<T>::type;
288using add_lvalue_reference_t =
typename std::add_lvalue_reference<T>::type;
291using add_rvalue_reference_t =
typename std::add_rvalue_reference<T>::type;
294using remove_pointer_t =
typename std::remove_pointer<T>::type;
297using add_pointer_t =
typename std::add_pointer<T>::type;
300using make_signed_t =
typename std::make_signed<T>::type;
303using make_unsigned_t =
typename std::make_unsigned<T>::type;
306using remove_extent_t =
typename std::remove_extent<T>::type;
309using remove_all_extents_t =
typename std::remove_all_extents<T>::type;
311template <
size_t Len,
size_t Align = type_traits_internal::
312 default_alignment_of_aligned_storage<Len>::value>
313using aligned_storage_t =
typename std::aligned_storage<Len, Align>::type;
316using decay_t =
typename std::decay<T>::type;
318template <
bool B,
typename T =
void>
319using enable_if_t =
typename std::enable_if<B, T>::type;
321template <
bool B,
typename T,
typename F>
322using conditional_t =
typename std::conditional<B, T, F>::type;
325template <
typename... T>
326using common_type_t =
typename std::common_type<T...>::type;
329using underlying_type_t =
typename std::underlying_type<T>::type;
331template<
class F,
class... ArgTypes>
333 using invoke_result_t =
typename std::invoke_result_t<F, ArgTypes...>;
335 using invoke_result_t =
typename std::result_of<F(ArgTypes...)>::type;
338namespace type_traits_internal {
345#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
346 _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
347 #define PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
349 #define PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
352#if !PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
353 template <
typename Key,
typename =
size_t>
354 struct IsHashable : std::true_type {};
356 template <
typename Key,
typename =
void>
359 template <
typename Key>
361 phmap::enable_if_t<std::is_convertible<
362 decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
363 std::size_t>::value>> : std::true_type {};
369 static void Sink(...) {}
373 static auto GetReturnType(
int)
374 ->
decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
376 static NAT GetReturnType(...);
379 static std::nullptr_t DoIt() {
381 "std::hash<Key> does not provide a call operator");
383 std::is_default_constructible<std::hash<Key>>::value,
384 "std::hash<Key> must be default constructible when it is enabled");
386 std::is_copy_constructible<std::hash<Key>>::value,
387 "std::hash<Key> must be copy constructible when it is enabled");
389 "std::hash<Key> must be copy assignable when it is enabled");
392 using ReturnType =
decltype(GetReturnType<Key>(0));
393 static_assert(std::is_same<ReturnType, NAT>::value ||
394 std::is_same<ReturnType, size_t>::value,
395 "std::hash<Key> must return size_t");
399 template <
class... Ts>
400 friend void AssertHashEnabled();
403template <
class... Ts>
404inline void AssertHashEnabled
408 Helper::Sink(Helper::DoIt<Ts>()...);
423template <
class Policy,
class =
void>
424struct hash_policy_traits
433 template <
class Key,
class... Args>
434 Key operator()(Key&& k,
const Args&...)
const {
435 return std::forward<Key>(k);
439 template <
class P = Policy,
class =
void>
440 struct ConstantIteratorsImpl : std::false_type {};
443 struct ConstantIteratorsImpl<P, phmap::void_t<typename P::constant_iterators>>
444 : P::constant_iterators {};
448 using slot_type =
typename Policy::slot_type;
451 using key_type =
typename Policy::key_type;
456 using init_type =
typename Policy::init_type;
458 using reference =
decltype(Policy::element(std::declval<slot_type*>()));
459 using pointer =
typename std::remove_reference<reference>::type*;
460 using value_type =
typename std::remove_reference<reference>::type;
466 using constant_iterators = ConstantIteratorsImpl<>;
470 template <
class Alloc,
class... Args>
471 static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {
472 Policy::construct(alloc, slot, std::forward<Args>(args)...);
477 template <
class Alloc>
478 static void destroy(Alloc* alloc, slot_type* slot) {
479 Policy::destroy(alloc, slot);
493 template <
class Alloc>
494 static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) {
495 transfer_impl(alloc, new_slot, old_slot, 0);
500 template <
class P = Policy>
501 static auto element(slot_type* slot) ->
decltype(P::element(slot)) {
502 return P::element(slot);
511 template <
class P = Policy>
512 static size_t space_used(
const slot_type* slot) {
513 return P::space_used(slot);
545 template <
class F,
class... Ts,
class P = Policy>
546 static auto apply(F&& f, Ts&&... ts)
547 ->
decltype(P::apply(std::forward<F>(f), std::forward<Ts>(ts)...)) {
548 return P::apply(std::forward<F>(f), std::forward<Ts>(ts)...);
553 template <
class P = Policy>
554 static auto key(slot_type* slot)
555 ->
decltype(P::apply(ReturnKey(), element(slot))) {
556 return P::apply(ReturnKey(), element(slot));
561 template <
class T,
class P = Policy>
562 static auto value(T* elem) ->
decltype(P::value(elem)) {
563 return P::value(elem);
569 template <
class Alloc,
class P = Policy>
570 static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
571 slot_type* old_slot,
int)
572 ->
decltype((void)P::transfer(alloc, new_slot, old_slot)) {
573 P::transfer(alloc, new_slot, old_slot);
576 template <
class Alloc>
577 static void transfer_impl(Alloc* alloc, slot_type* new_slot,
578 slot_type* old_slot,
char) {
579 construct(alloc, new_slot, std::move(element(old_slot)));
580 destroy(alloc, old_slot);
601using identity_t =
typename identity<T>::type;
609#ifdef __cpp_inline_variables
611#if defined(__clang__)
612 #define PHMAP_INTERNAL_EXTERN_DECL(type, name) \
613 extern const ::phmap::internal::identity_t<type> name;
615 #define PHMAP_INTERNAL_EXTERN_DECL(type, name)
619#define PHMAP_INTERNAL_INLINE_CONSTEXPR(type, name, init) \
620 PHMAP_INTERNAL_EXTERN_DECL(type, name) \
621 inline constexpr ::phmap::internal::identity_t<type> name = init
631#define PHMAP_INTERNAL_INLINE_CONSTEXPR(var_type, name, init) \
632 template <class = void> \
633 struct PhmapInternalInlineVariableHolder##name { \
634 static constexpr ::phmap::internal::identity_t<var_type> kInstance = init; \
637 template <class PhmapInternalDummy> \
638 constexpr ::phmap::internal::identity_t<var_type> \
639 PhmapInternalInlineVariableHolder##name<PhmapInternalDummy>::kInstance; \
641 static constexpr const ::phmap::internal::identity_t<var_type>& \
643 PhmapInternalInlineVariableHolder##name<>::kInstance; \
644 static_assert(sizeof(void (*)(decltype(name))) != 0, \
645 "Silence unused variable warnings.")
652namespace base_internal {
656#ifdef PHMAP_HAVE_EXCEPTIONS
657[[noreturn]]
void Throw(
const T& error) {
661[[noreturn]]
void Throw(
const T&) {
667static inline void ThrowStdLogicError(
const std::string& what_arg) {
668 Throw(std::logic_error(what_arg));
670static inline void ThrowStdLogicError(
const char* what_arg) {
671 Throw(std::logic_error(what_arg));
673static inline void ThrowStdInvalidArgument(
const std::string& what_arg) {
674 Throw(std::invalid_argument(what_arg));
676static inline void ThrowStdInvalidArgument(
const char* what_arg) {
677 Throw(std::invalid_argument(what_arg));
680static inline void ThrowStdDomainError(
const std::string& what_arg) {
681 Throw(std::domain_error(what_arg));
683static inline void ThrowStdDomainError(
const char* what_arg) {
684 Throw(std::domain_error(what_arg));
687static inline void ThrowStdLengthError(
const std::string& what_arg) {
688 Throw(std::length_error(what_arg));
690static inline void ThrowStdLengthError(
const char* what_arg) {
691 Throw(std::length_error(what_arg));
694static inline void ThrowStdOutOfRange(
const std::string& what_arg) {
695 Throw(std::out_of_range(what_arg));
697static inline void ThrowStdOutOfRange(
const char* what_arg) {
698 Throw(std::out_of_range(what_arg));
701static inline void ThrowStdRuntimeError(
const std::string& what_arg) {
702 Throw(std::runtime_error(what_arg));
704static inline void ThrowStdRuntimeError(
const char* what_arg) {
705 Throw(std::runtime_error(what_arg));
708static inline void ThrowStdRangeError(
const std::string& what_arg) {
709 Throw(std::range_error(what_arg));
711static inline void ThrowStdRangeError(
const char* what_arg) {
712 Throw(std::range_error(what_arg));
715static inline void ThrowStdOverflowError(
const std::string& what_arg) {
716 Throw(std::overflow_error(what_arg));
718static inline void ThrowStdOverflowError(
const char* what_arg) {
719 Throw(std::overflow_error(what_arg));
722static inline void ThrowStdUnderflowError(
const std::string& what_arg) {
723 Throw(std::underflow_error(what_arg));
725static inline void ThrowStdUnderflowError(
const char* what_arg) {
726 Throw(std::underflow_error(what_arg));
729static inline void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
731static inline void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
739namespace base_internal {
741template <
typename Derived>
744 template <
typename... Args>
745 struct Accept : Derived::template AcceptImpl<typename std::remove_cv<
746 typename std::remove_reference<Args>::type>::type...> {};
754 template <
typename... Args>
757 template <
typename R,
typename C,
typename... Params,
typename Obj,
760 : std::is_base_of<C, Obj> {};
762 template <
typename R,
typename C,
typename... Params,
typename Obj,
765 : std::is_base_of<C, Obj> {};
767 template <
typename MemFun,
typename Obj,
typename... Args>
768 static decltype((std::declval<Obj>().*
769 std::declval<MemFun>())(std::declval<Args>()...))
770 Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) {
771 return (std::forward<Obj>(obj).*
772 std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
780 template <
typename... Args>
783 template <
typename R,
typename C,
typename... Params,
typename Ptr,
786 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
788 template <
typename R,
typename C,
typename... Params,
typename Ptr,
791 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
793 template <
typename MemFun,
typename Ptr,
typename... Args>
794 static decltype(((*std::declval<Ptr>()).*
795 std::declval<MemFun>())(std::declval<Args>()...))
796 Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) {
797 return ((*std::forward<Ptr>(ptr)).*
798 std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
807 template <
typename... Args>
810 template <
typename R,
typename C,
typename Obj>
813 template <
typename DataMem,
typename Ref>
814 static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke(
815 DataMem&& data_mem, Ref&& ref) {
816 return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem);
824 template <
typename... Args>
827 template <
typename R,
typename C,
typename Ptr>
829 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
831 template <
typename DataMem,
typename Ptr>
832 static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke(
833 DataMem&& data_mem, Ptr&& ptr) {
834 return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem);
843 template <
typename F,
typename... Args>
844 static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke(
845 F&& f, Args&&... args) {
846 return std::forward<F>(f)(std::forward<Args>(args)...);
851template <
typename... Args>
854 typedef typename std::conditional<
856 typename std::conditional<
858 typename std::conditional<
860 typename std::conditional<DataMemAndPtr::Accept<Args...>::value,
866template <
typename F,
typename... Args>
868 std::declval<F>(), std::declval<Args>()...));
872template <
typename F,
typename... Args>
873InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
875 std::forward<Args>(args)...);
904template <
typename T, T... Ints>
907 using value_type = T;
908 static constexpr size_t size()
noexcept {
return sizeof...(Ints); }
916template <
size_t... Ints>
919namespace utility_internal {
921template <
typename Seq,
size_t SeqSize,
size_t Rem>
925template <
typename T, T... Ints,
size_t SeqSize>
930template <
typename T, T... Ints,
size_t SeqSize>
937template <
typename T,
size_t N>
940 typename Extend<
typename Gen<T, N / 2>::type, N / 2, N % 2>::type;
957template <
typename T, T N>
958using make_integer_sequence =
typename utility_internal::Gen<T, N>::type;
966using make_index_sequence = make_integer_sequence<size_t, N>;
973template <
typename... Ts>
974using index_sequence_for = make_index_sequence<
sizeof...(Ts)>;
978#ifdef PHMAP_HAVE_STD_OPTIONAL
980using std::in_place_t;
992PHMAP_INTERNAL_INLINE_CONSTEXPR(
in_place_t, in_place, {});
996#if defined(PHMAP_HAVE_STD_ANY) || defined(PHMAP_HAVE_STD_VARIANT)
997using std::in_place_type_t;
1005template <
typename T>
1009#ifdef PHMAP_HAVE_STD_VARIANT
1010using std::in_place_index_t;
1028template <
typename T>
1029constexpr phmap::remove_reference_t<T>&& move(T&& t)
noexcept {
1030 return static_cast<phmap::remove_reference_t<T>&&
>(t);
1037template <
typename T>
1038constexpr T&& forward(
1039 phmap::remove_reference_t<T>& t)
noexcept {
1040 return static_cast<T&&
>(t);
1043namespace utility_internal {
1045template <
typename Functor,
typename Tuple, std::size_t... Indexes>
1046auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>)
1047 ->
decltype(phmap::base_internal::Invoke(
1048 phmap::forward<Functor>(functor),
1049 std::get<Indexes>(phmap::forward<Tuple>(t))...)) {
1050 return phmap::base_internal::Invoke(
1051 phmap::forward<Functor>(functor),
1052 std::get<Indexes>(phmap::forward<Tuple>(t))...);
1096template <
typename Functor,
typename Tuple>
1097auto apply(Functor&& functor, Tuple&& t)
1098 ->
decltype(utility_internal::apply_helper(
1099 phmap::forward<Functor>(functor), phmap::forward<Tuple>(t),
1100 phmap::make_index_sequence<std::tuple_size<
1101 typename std::remove_reference<Tuple>::type>::value>{})) {
1102 return utility_internal::apply_helper(
1103 phmap::forward<Functor>(functor), phmap::forward<Tuple>(t),
1104 phmap::make_index_sequence<std::tuple_size<
1105 typename std::remove_reference<Tuple>::type>::value>{});
1109 #pragma warning(push)
1110 #pragma warning(disable : 4365)
1126template <
typename T,
typename U = T>
1127T exchange(T& obj, U&& new_value)
1129 T old_value = phmap::move(obj);
1130 obj = phmap::forward<U>(new_value);
1135 #pragma warning(pop)
1147template <
typename T>
1148std::unique_ptr<T> WrapUnique(T* ptr)
1150 static_assert(!std::is_array<T>::value,
"array types are unsupported");
1151 static_assert(std::is_object<T>::value,
"non-object types are unsupported");
1152 return std::unique_ptr<T>(ptr);
1155namespace memory_internal {
1158template <
typename T>
1160 using scalar = std::unique_ptr<T>;
1162template <
typename T>
1164 using array = std::unique_ptr<T[]>;
1166template <
typename T,
size_t N>
1168 using invalid = void;
1173#if (__cplusplus > 201103L || defined(_MSC_VER)) && \
1174 !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8)
1175 using std::make_unique;
1178 template <
typename T,
typename... Args>
1179 typename memory_internal::MakeUniqueResult<T>::scalar make_unique(
1181 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
1184 template <
typename T>
1185 typename memory_internal::MakeUniqueResult<T>::array make_unique(
size_t n) {
1186 return std::unique_ptr<T>(
new typename phmap::remove_extent_t<T>[n]());
1189 template <
typename T,
typename... Args>
1190 typename memory_internal::MakeUniqueResult<T>::invalid make_unique(
1191 Args&&... ) =
delete;
1194template <
typename T>
1195auto RawPtr(T&& ptr) ->
decltype(std::addressof(*ptr))
1198 return (ptr !=
nullptr) ? std::addressof(*ptr) : nullptr;
1201inline std::nullptr_t RawPtr(std::nullptr_t) {
return nullptr; }
1203template <
typename T,
typename D>
1204std::shared_ptr<T> ShareUniquePtr(std::unique_ptr<T, D>&& ptr) {
1205 return ptr ? std::shared_ptr<T>(std::move(ptr)) : std::shared_ptr<T>();
1208template <
typename T>
1209std::weak_ptr<T> WeakenPtr(
const std::shared_ptr<T>& ptr) {
1210 return std::weak_ptr<T>(ptr);
1213namespace memory_internal {
1216template <
template <
typename>
class Extract,
typename Obj,
typename Default,
1219 using type = Default;
1222template <
template <
typename>
class Extract,
typename Obj,
typename Default>
1223struct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> {
1224 using type = Extract<Obj>;
1227template <
template <
typename>
class Extract,
typename Obj,
typename Default>
1228using ExtractOrT =
typename ExtractOr<Extract, Obj, Default, void>::type;
1231template <
typename T>
1232using GetPointer =
typename T::pointer;
1234template <
typename T>
1235using GetConstPointer =
typename T::const_pointer;
1237template <
typename T>
1238using GetVoidPointer =
typename T::void_pointer;
1240template <
typename T>
1241using GetConstVoidPointer =
typename T::const_void_pointer;
1243template <
typename T>
1244using GetDifferenceType =
typename T::difference_type;
1246template <
typename T>
1247using GetSizeType =
typename T::size_type;
1249template <
typename T>
1250using GetPropagateOnContainerCopyAssignment =
1251 typename T::propagate_on_container_copy_assignment;
1253template <
typename T>
1254using GetPropagateOnContainerMoveAssignment =
1255 typename T::propagate_on_container_move_assignment;
1257template <
typename T>
1258using GetPropagateOnContainerSwap =
typename T::propagate_on_container_swap;
1260template <
typename T>
1261using GetIsAlwaysEqual =
typename T::is_always_equal;
1263template <
typename T>
1266template <
template <
typename...>
class Class,
typename T,
typename... Args>
1271template <
typename Ptr,
typename =
void>
1276template <
typename T>
1278 using type =
typename T::element_type;
1281template <
typename T,
typename U>
1284template <
template <
typename...>
class Class,
typename T,
typename... Args,
1287 using type = Class<U, Args...>;
1290template <
typename T,
typename U,
typename =
void>
1295template <
typename T,
typename U>
1296struct RebindPtr<T, U, void_t<typename T::template rebind<U>>> {
1297 using type =
typename T::template rebind<U>;
1300template <
typename T,
typename U>
1301constexpr bool HasRebindAlloc(...) {
1305template <
typename T,
typename U>
1306constexpr bool HasRebindAlloc(
typename std::allocator_traits<T>::template rebind_alloc<U>*) {
1310template <typename T, typename U, bool = HasRebindAlloc<T, U>(
nullptr)>
1315template <
typename A,
typename U>
1317 using type =
typename std::allocator_traits<A>::template rebind_alloc<U>;
1323template <
typename Ptr>
1326 using pointer = Ptr;
1331 using element_type =
typename memory_internal::ElementType<Ptr>::type;
1335 using difference_type =
1336 memory_internal::ExtractOrT<memory_internal::GetDifferenceType, Ptr,
1342 template <
typename U>
1343 using rebind =
typename memory_internal::RebindPtr<Ptr, U>::type;
1347 static pointer pointer_to(element_type& r) {
1348 return Ptr::pointer_to(r);
1353template <
typename T>
1357 using element_type = T;
1358 using difference_type = std::ptrdiff_t;
1360 template <
typename U>
1365 static pointer pointer_to(
1366 element_type& r)
noexcept {
1367 return std::addressof(r);
1377template <
typename Alloc>
1380 using allocator_type = Alloc;
1384 using value_type =
typename Alloc::value_type;
1388 using pointer = memory_internal::ExtractOrT<memory_internal::GetPointer,
1389 Alloc, value_type*>;
1394 using const_pointer =
1395 memory_internal::ExtractOrT<memory_internal::GetConstPointer, Alloc,
1397 template rebind<const value_type>>;
1402 using void_pointer = memory_internal::ExtractOrT<
1403 memory_internal::GetVoidPointer, Alloc,
1409 using const_void_pointer = memory_internal::ExtractOrT<
1410 memory_internal::GetConstVoidPointer, Alloc,
1416 using difference_type = memory_internal::ExtractOrT<
1417 memory_internal::GetDifferenceType, Alloc,
1418 typename phmap::pointer_traits<pointer>::difference_type>;
1423 using size_type = memory_internal::ExtractOrT<
1424 memory_internal::GetSizeType, Alloc,
1425 typename std::make_unsigned<difference_type>::type>;
1430 using propagate_on_container_copy_assignment = memory_internal::ExtractOrT<
1431 memory_internal::GetPropagateOnContainerCopyAssignment, Alloc,
1437 using propagate_on_container_move_assignment = memory_internal::ExtractOrT<
1438 memory_internal::GetPropagateOnContainerMoveAssignment, Alloc,
1443 using propagate_on_container_swap =
1444 memory_internal::ExtractOrT<memory_internal::GetPropagateOnContainerSwap,
1445 Alloc, std::false_type>;
1449 using is_always_equal =
1450 memory_internal::ExtractOrT<memory_internal::GetIsAlwaysEqual, Alloc,
1451 typename std::is_empty<Alloc>::type>;
1456 template <
typename T>
1457 using rebind_alloc =
typename memory_internal::RebindAlloc<Alloc, T>::type;
1461 template <
typename T>
1466 static pointer allocate(Alloc& a,
1468 return a.allocate(n);
1474 static pointer allocate(Alloc& a, size_type n,
1475 const_void_pointer hint) {
1476 return allocate_impl(0, a, n, hint);
1481 static void deallocate(Alloc& a, pointer p,
1490 template <
typename T,
typename... Args>
1491 static void construct(Alloc& a, T* p,
1493 construct_impl(0, a, p, std::forward<Args>(args)...);
1498 template <
typename T>
1499 static void destroy(Alloc& a, T* p) {
1500 destroy_impl(0, a, p);
1506 static size_type max_size(
const Alloc& a) {
return max_size_impl(0, a); }
1511 static Alloc select_on_container_copy_construction(
const Alloc& a) {
1512 return select_on_container_copy_construction_impl(0, a);
1516 template <
typename A>
1517 static auto allocate_impl(
int, A& a,
1518 size_type n, const_void_pointer hint)
1519 ->
decltype(a.allocate(n, hint)) {
1520 return a.allocate(n, hint);
1522 static pointer allocate_impl(
char, Alloc& a,
1523 size_type n, const_void_pointer) {
1524 return a.allocate(n);
1527 template <
typename A,
typename... Args>
1528 static auto construct_impl(
int, A& a,
1530 ->
decltype(std::allocator_traits<A>::construct(a, std::forward<Args>(args)...)) {
1531 std::allocator_traits<A>::construct(a, std::forward<Args>(args)...);
1534 template <
typename T,
typename... Args>
1535 static void construct_impl(
char, Alloc&, T* p, Args&&... args) {
1536 ::new (
static_cast<void*
>(p)) T(std::forward<Args>(args)...);
1539 template <
typename A,
typename T>
1540 static auto destroy_impl(
int, A& a,
1541 T* p) ->
decltype(std::allocator_traits<A>::destroy(a, p)) {
1542 std::allocator_traits<A>::destroy(a, p);
1544 template <
typename T>
1545 static void destroy_impl(
char, Alloc&, T* p) {
1549 template <
typename A>
1550 static auto max_size_impl(
int,
const A& a) ->
decltype(a.max_size()) {
1551 return a.max_size();
1553 static size_type max_size_impl(
char,
const Alloc&) {
1554 return (std::numeric_limits<size_type>::max)() /
sizeof(value_type);
1557 template <
typename A>
1558 static auto select_on_container_copy_construction_impl(
int,
const A& a)
1559 ->
decltype(a.select_on_container_copy_construction()) {
1560 return a.select_on_container_copy_construction();
1562 static Alloc select_on_container_copy_construction_impl(
char,
1568namespace memory_internal {
1572template <
typename Alloc>
1573using GetIsNothrow =
typename Alloc::is_nothrow;
1596template <
typename Alloc>
1598 : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc,
1599 std::false_type> {};
1601#if defined(PHMAP_ALLOCATOR_NOTHROW) && PHMAP_ALLOCATOR_NOTHROW
1602 template <
typename T>
1604 struct default_allocator_is_nothrow : std::true_type {};
1609namespace memory_internal {
1610template <
typename Allocator,
typename Iterator,
typename... Args>
1611void ConstructRange(Allocator& alloc, Iterator first, Iterator last,
1612 const Args&... args)
1614 for (Iterator cur = first; cur != last; ++cur) {
1615 PHMAP_INTERNAL_TRY {
1616 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
1619 PHMAP_INTERNAL_CATCH_ANY {
1620 while (cur != first) {
1622 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
1624 PHMAP_INTERNAL_RETHROW;
1629template <
typename Allocator,
typename Iterator,
typename InputIterator>
1630void CopyRange(Allocator& alloc, Iterator destination, InputIterator first,
1633 for (Iterator cur = destination; first != last;
1634 static_cast<void>(++cur),
static_cast<void>(++first)) {
1635 PHMAP_INTERNAL_TRY {
1636 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
1639 PHMAP_INTERNAL_CATCH_ANY {
1640 while (cur != destination) {
1642 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
1644 PHMAP_INTERNAL_RETHROW;
1655#ifdef PHMAP_HAVE_STD_OPTIONAL
1660using std::bad_optional_access;
1662using std::make_optional;
1663using std::nullopt_t;
1669#if defined(__clang__)
1670 #if __has_feature(cxx_inheriting_constructors)
1671 #define PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
1673#elif (defined(__GNUC__) && \
1674 (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
1675 (__cpp_inheriting_constructors >= 200802) || \
1676 (defined(_MSC_VER) && _MSC_VER >= 1910)
1678 #define PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
1683class bad_optional_access :
public std::exception
1686 bad_optional_access() =
default;
1687 ~bad_optional_access()
override;
1688 const char* what() const noexcept override;
1691template <typename T>
1700 explicit constexpr nullopt_t(
init_t& ) {}
1703constexpr nullopt_t nullopt(nullopt_t::init);
1705namespace optional_internal {
1708[[noreturn]]
void throw_bad_optional_access();
1716template <typename T, bool unused = std::is_trivially_destructible<T>::value>
1720 static_assert(
sizeof(T) %
sizeof(
empty_struct) == 0,
"");
1734 void destruct()
noexcept {
1744 template <
typename... Args>
1746 : engaged_(
true), data_(phmap::forward<Args>(args)...) {}
1752template <
typename T>
1756 static_assert(
sizeof(T) %
sizeof(
empty_struct) == 0,
"");
1769 void destruct()
noexcept { engaged_ =
false; }
1774 template <
typename... Args>
1776 : engaged_(
true), data_(phmap::forward<Args>(args)...) {}
1779template <
typename T>
1784#if PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS
1789 template <
typename... Args>
1791 :
base(t, phmap::forward<Args>(args)...) {}
1794 template <
typename... Args>
1795 void construct(Args&&... args) {
1797 ::new (
static_cast<void*
>(&this->dummy_)) T(std::forward<Args>(args)...);
1798 this->engaged_ =
true;
1801 template <
typename U>
1802 void assign(U&& u) {
1803 if (this->engaged_) {
1804 this->data_ = std::forward<U>(u);
1806 construct(std::forward<U>(u));
1817template <
typename T,
1820 T>::type>::value&& std::is_trivially_destructible<T>::value>
1824template <
typename T>
1828#if PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS
1833 template <
typename... Args>
1839template <
typename T>
1843#if PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS
1846 template <
typename... Args>
1855 this->construct(rhs.data_);
1860 phmap::default_allocator_is_nothrow::value ||
1861 std::is_nothrow_move_constructible<T>::value)
1864 this->construct(std::move(rhs.data_));
1870 this->assign(rhs.data_);
1878 std::is_nothrow_move_assignable<T>::value&&
1879 std::is_nothrow_move_constructible<T>::value) {
1881 this->assign(std::move(rhs.data_));
1891enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
1894template <copy_traits>
1931template <copy_traits>
1967template <
typename T>
1968constexpr copy_traits get_ctor_copy_traits()
1970 return std::is_copy_constructible<T>::value
1971 ? copy_traits::copyable
1972 : std::is_move_constructible<T>::value ? copy_traits::movable
1973 : copy_traits::non_movable;
1976template <
typename T>
1977constexpr copy_traits get_assign_copy_traits()
1980 std::is_copy_constructible<T>::value
1981 ? copy_traits::copyable
1983 std::is_move_constructible<T>::value
1984 ? copy_traits::movable
1985 : copy_traits::non_movable;
1989template <
typename T,
typename U>
1991 : std::integral_constant<
1992 bool, std::is_constructible<T, optional<U>&>::value ||
1993 std::is_constructible<T, optional<U>&&>::value ||
1994 std::is_constructible<T, const optional<U>&>::value ||
1995 std::is_constructible<T, const optional<U>&&>::value ||
1996 std::is_convertible<optional<U>&, T>::value ||
1997 std::is_convertible<optional<U>&&, T>::value ||
1998 std::is_convertible<const optional<U>&, T>::value ||
1999 std::is_convertible<const optional<U>&&, T>::value> {};
2002template <
typename T,
typename U>
2004 : std::integral_constant<
2005 bool, is_constructible_convertible_from_optional<T, U>::value ||
2006 std::is_assignable<T&, optional<U>&>::value ||
2007 std::is_assignable<T&, optional<U>&&>::value ||
2008 std::is_assignable<T&, const optional<U>&>::value ||
2009 std::is_assignable<T&, const optional<U>&&>::value> {};
2013bool convertible_to_bool(
bool);
2019template <
typename T,
typename =
size_t>
2029template <
typename T>
2031 std::declval<phmap::remove_const_t<T> >()))>
2033 using argument_type = phmap::optional<T>;
2034 using result_type = size_t;
2035 size_t operator()(
const phmap::optional<T>& opt)
const {
2036 phmap::type_traits_internal::AssertHashEnabled<phmap::remove_const_t<T>>();
2038 return std::hash<phmap::remove_const_t<T> >()(*opt);
2040 return static_cast<size_t>(0x297814aaad196e6dULL);
2052template <
typename T>
2055 optional_internal::get_ctor_copy_traits<T>()>,
2057 optional_internal::get_assign_copy_traits<T>()>
2062 typedef T value_type;
2068 constexpr optional() noexcept {}
2071 constexpr optional(nullopt_t)
noexcept {}
2074 optional(
const optional& src) =
default;
2077 optional(optional&& src) =
default;
2083 template <
typename InPlaceT,
typename... Args,
2085 std::is_same<InPlaceT, in_place_t>,
2086 std::is_constructible<T, Args&&...> >::value>* =
nullptr>
2087 constexpr explicit optional(InPlaceT, Args&&... args)
2088 : data_base(in_place_t(), phmap::forward<Args>(args)...) {}
2094 template <
typename U,
typename... Args,
2095 typename =
typename std::enable_if<std::is_constructible<
2096 T, std::initializer_list<U>&, Args&&...>::value>::type>
2097 constexpr explicit optional(in_place_t, std::initializer_list<U> il,
2099 : data_base(in_place_t(), il, phmap::forward<Args>(args)...) {
2105 typename std::enable_if<
2107 in_place_t,
typename std::decay<U>::type> >,
2109 optional<T>,
typename std::decay<U>::type> >,
2110 std::is_convertible<U&&, T>,
2111 std::is_constructible<T, U&&> >::value,
2112 bool>::type =
false>
2113 constexpr optional(U&& v) : data_base(in_place_t(), phmap::forward<U>(v)) {}
2118 typename std::enable_if<
2120 in_place_t,
typename std::decay<U>::type>>,
2122 optional<T>,
typename std::decay<U>::type>>,
2124 std::is_constructible<T, U&&>>::value,
2125 bool>::type =
false>
2126 explicit constexpr optional(U&& v)
2127 : data_base(in_place_t(), phmap::forward<U>(v)) {}
2130 template <
typename U,
2131 typename std::enable_if<
2134 std::is_constructible<T, const U&>,
2137 is_constructible_convertible_from_optional<T, U> >,
2138 std::is_convertible<const U&, T> >::value,
2139 bool>::type =
false>
2140 optional(
const optional<U>& rhs) {
2142 this->construct(*rhs);
2147 template <
typename U,
2148 typename std::enable_if<
2151 std::is_constructible<T, const U&>,
2154 is_constructible_convertible_from_optional<T, U>>,
2156 bool>::type =
false>
2157 explicit optional(
const optional<U>& rhs) {
2159 this->construct(*rhs);
2164 template <
typename U,
2165 typename std::enable_if<
2168 std::is_constructible<T, U&&>,
2171 is_constructible_convertible_from_optional<T, U> >,
2172 std::is_convertible<U&&, T> >::value,
2173 bool>::type =
false>
2174 optional(optional<U>&& rhs) {
2176 this->construct(std::move(*rhs));
2183 typename std::enable_if<
2187 optional_internal::is_constructible_convertible_from_optional<
2190 bool>::type =
false>
2191 explicit optional(optional<U>&& rhs) {
2193 this->construct(std::move(*rhs));
2198 ~optional() =
default;
2208 optional& operator=(nullopt_t)
noexcept {
2214 optional& operator=(
const optional& src) =
default;
2217 optional& operator=(optional&& src) =
default;
2224 std::is_same<optional<T>,
typename std::decay<U>::type>>,
2227 std::is_same<T, typename std::decay<U>::type>>>,
2228 std::is_constructible<T, U>, std::is_assignable<T&, U>>::value>::type>
2229 optional& operator=(U&& v) {
2230 this->assign(std::forward<U>(v));
2238 std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>,
2241 is_constructible_convertible_assignable_from_optional<
2242 T, U>>>::value>::type>
2243 optional& operator=(
const optional<U>& rhs) {
2252 template <
typename U,
2255 std::is_assignable<T&, U>,
2258 is_constructible_convertible_assignable_from_optional<
2259 T, U>>>::value>::type>
2260 optional& operator=(optional<U>&& rhs) {
2262 this->assign(std::move(*rhs));
2274 PHMAP_ATTRIBUTE_REINITIALIZES
void reset() noexcept { this->destruct(); }
2289 template <
typename... Args,
2290 typename =
typename std::enable_if<
2291 std::is_constructible<T, Args&&...>::value>::type>
2292 T& emplace(Args&&... args) {
2294 this->construct(std::forward<Args>(args)...);
2309 template <
typename U,
typename... Args,
2310 typename =
typename std::enable_if<std::is_constructible<
2311 T, std::initializer_list<U>&, Args&&...>::value>::type>
2312 T& emplace(std::initializer_list<U> il, Args&&... args) {
2314 this->construct(il, std::forward<Args>(args)...);
2321 void swap(optional& rhs)
noexcept(
2322 std::is_nothrow_move_constructible<T>::value&&
2323 std::is_trivial<T>::value) {
2329 rhs.construct(std::move(**
this));
2334 this->construct(std::move(*rhs));
2350 const T* operator->()
const {
2351 assert(this->engaged_);
2352 return std::addressof(this->data_);
2355 assert(this->engaged_);
2356 return std::addressof(this->data_);
2363 constexpr const T& operator*() const & {
return reference(); }
2365 assert(this->engaged_);
2368 constexpr const T&& operator*() const && {
2369 return phmap::move(reference());
2371 T&& operator*() && {
2372 assert(this->engaged_);
2373 return std::move(reference());
2386 constexpr explicit operator bool() const noexcept {
return this->engaged_; }
2392 constexpr bool has_value() const noexcept {
return this->engaged_; }
2397 #pragma warning(push)
2398 #pragma warning(disable : 4702)
2406 constexpr const T& value() const & {
2407 return static_cast<bool>(*this)
2409 : (optional_internal::throw_bad_optional_access(), reference());
2412 return static_cast<bool>(*this)
2414 : (optional_internal::throw_bad_optional_access(), reference());
2418 static_cast<bool>(*
this)
2420 : (optional_internal::throw_bad_optional_access(), reference()));
2422 constexpr const T&& value() const && {
2424 static_cast<bool>(*
this)
2426 : (optional_internal::throw_bad_optional_access(), reference()));
2429 #pragma warning(pop)
2436 template <
typename U>
2437 constexpr T value_or(U&& v)
const& {
2438 static_assert(std::is_copy_constructible<value_type>::value,
2439 "optional<T>::value_or: T must by copy constructible");
2440 static_assert(std::is_convertible<U&&, value_type>::value,
2441 "optional<T>::value_or: U must be convertible to T");
2442 return static_cast<bool>(*this)
2444 :
static_cast<T
>(phmap::forward<U>(v));
2446 template <
typename U>
2447 T value_or(U&& v) && {
2448 static_assert(std::is_move_constructible<value_type>::value,
2449 "optional<T>::value_or: T must by move constructible");
2450 static_assert(std::is_convertible<U&&, value_type>::value,
2451 "optional<T>::value_or: U must be convertible to T");
2452 return static_cast<bool>(*this) ? std::move(**
this)
2453 : static_cast<T>(std::forward<U>(v));
2458 constexpr const T& reference()
const {
return this->data_; }
2459 T& reference() {
return this->data_; }
2464 !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value,
2465 "optional<nullopt_t> is not allowed.");
2467 !std::is_same<in_place_t, typename std::remove_cv<T>::type>::value,
2468 "optional<in_place_t> is not allowed.");
2469 static_assert(!std::is_reference<T>::value,
2470 "optional<reference> is not allowed.");
2482template <
typename T,
2483 typename std::enable_if<std::is_move_constructible<T>::value,
2484 bool>::type =
false>
2485void swap(optional<T>& a, optional<T>& b)
noexcept(
noexcept(a.swap(b))) {
2504template <
typename T>
2505constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
2506 return optional<typename std::decay<T>::type>(phmap::forward<T>(v));
2509template <
typename T,
typename... Args>
2510constexpr optional<T> make_optional(Args&&... args) {
2511 return optional<T>(in_place_t(), phmap::forward<Args>(args)...);
2514template <
typename T,
typename U,
typename... Args>
2515constexpr optional<T> make_optional(std::initializer_list<U> il,
2517 return optional<T>(in_place_t(), il,
2518 phmap::forward<Args>(args)...);
2535template <
typename T,
typename U>
2536constexpr auto operator==(
const optional<T>& x,
const optional<U>& y)
2537 ->
decltype(optional_internal::convertible_to_bool(*x == *y)) {
2538 return static_cast<bool>(x) !=
static_cast<bool>(y)
2540 :
static_cast<bool>(x) ==
false ?
true
2541 : static_cast<bool>(*x == *y);
2546template <
typename T,
typename U>
2547constexpr auto operator!=(
const optional<T>& x,
const optional<U>& y)
2548 ->
decltype(optional_internal::convertible_to_bool(*x != *y)) {
2549 return static_cast<bool>(x) !=
static_cast<bool>(y)
2551 :
static_cast<bool>(x) ==
false ?
false
2552 : static_cast<bool>(*x != *y);
2555template <
typename T,
typename U>
2556constexpr auto operator<(
const optional<T>& x,
const optional<U>& y)
2557 ->
decltype(optional_internal::convertible_to_bool(*x < *y)) {
2558 return !y ? false : !x ? true :
static_cast<bool>(*x < *y);
2561template <
typename T,
typename U>
2562constexpr auto operator>(
const optional<T>& x,
const optional<U>& y)
2563 ->
decltype(optional_internal::convertible_to_bool(*x > *y)) {
2564 return !x ? false : !y ? true :
static_cast<bool>(*x > *y);
2567template <
typename T,
typename U>
2568constexpr auto operator<=(
const optional<T>& x,
const optional<U>& y)
2569 ->
decltype(optional_internal::convertible_to_bool(*x <= *y)) {
2570 return !x ? true : !y ? false :
static_cast<bool>(*x <= *y);
2573template <
typename T,
typename U>
2574constexpr auto operator>=(
const optional<T>& x,
const optional<U>& y)
2575 ->
decltype(optional_internal::convertible_to_bool(*x >= *y)) {
2576 return !y ? true : !x ? false :
static_cast<bool>(*x >= *y);
2581template <
typename T>
2582constexpr bool operator==(
const optional<T>& x, nullopt_t)
noexcept {
2585template <
typename T>
2586constexpr bool operator==(nullopt_t,
const optional<T>& x)
noexcept {
2589template <
typename T>
2590constexpr bool operator!=(
const optional<T>& x, nullopt_t)
noexcept {
2591 return static_cast<bool>(x);
2593template <
typename T>
2594constexpr bool operator!=(nullopt_t,
const optional<T>& x)
noexcept {
2595 return static_cast<bool>(x);
2597template <
typename T>
2598constexpr bool operator<(
const optional<T>&, nullopt_t)
noexcept {
2601template <
typename T>
2602constexpr bool operator<(nullopt_t,
const optional<T>& x)
noexcept {
2603 return static_cast<bool>(x);
2605template <
typename T>
2606constexpr bool operator<=(
const optional<T>& x, nullopt_t)
noexcept {
2609template <
typename T>
2610constexpr bool operator<=(nullopt_t,
const optional<T>&)
noexcept {
2613template <
typename T>
2614constexpr bool operator>(
const optional<T>& x, nullopt_t)
noexcept {
2615 return static_cast<bool>(x);
2617template <
typename T>
2618constexpr bool operator>(nullopt_t,
const optional<T>&)
noexcept {
2621template <
typename T>
2622constexpr bool operator>=(
const optional<T>&, nullopt_t)
noexcept {
2625template <
typename T>
2626constexpr bool operator>=(nullopt_t,
const optional<T>& x)
noexcept {
2635template <
typename T,
typename U>
2636constexpr auto operator==(
const optional<T>& x,
const U& v)
2637 ->
decltype(optional_internal::convertible_to_bool(*x == v)) {
2638 return static_cast<bool>(x) ?
static_cast<bool>(*x == v) :
false;
2640template <
typename T,
typename U>
2641constexpr auto operator==(
const U& v,
const optional<T>& x)
2642 ->
decltype(optional_internal::convertible_to_bool(v == *x)) {
2643 return static_cast<bool>(x) ?
static_cast<bool>(v == *x) :
false;
2645template <
typename T,
typename U>
2646constexpr auto operator!=(
const optional<T>& x,
const U& v)
2647 ->
decltype(optional_internal::convertible_to_bool(*x != v)) {
2648 return static_cast<bool>(x) ?
static_cast<bool>(*x != v) :
true;
2650template <
typename T,
typename U>
2651constexpr auto operator!=(
const U& v,
const optional<T>& x)
2652 ->
decltype(optional_internal::convertible_to_bool(v != *x)) {
2653 return static_cast<bool>(x) ?
static_cast<bool>(v != *x) :
true;
2655template <
typename T,
typename U>
2656constexpr auto operator<(
const optional<T>& x,
const U& v)
2657 ->
decltype(optional_internal::convertible_to_bool(*x < v)) {
2658 return static_cast<bool>(x) ?
static_cast<bool>(*x < v) :
true;
2660template <
typename T,
typename U>
2661constexpr auto operator<(
const U& v,
const optional<T>& x)
2662 ->
decltype(optional_internal::convertible_to_bool(v < *x)) {
2663 return static_cast<bool>(x) ?
static_cast<bool>(v < *x) :
false;
2665template <
typename T,
typename U>
2666constexpr auto operator<=(
const optional<T>& x,
const U& v)
2667 ->
decltype(optional_internal::convertible_to_bool(*x <= v)) {
2668 return static_cast<bool>(x) ?
static_cast<bool>(*x <= v) :
true;
2670template <
typename T,
typename U>
2671constexpr auto operator<=(
const U& v,
const optional<T>& x)
2672 ->
decltype(optional_internal::convertible_to_bool(v <= *x)) {
2673 return static_cast<bool>(x) ?
static_cast<bool>(v <= *x) :
false;
2675template <
typename T,
typename U>
2676constexpr auto operator>(
const optional<T>& x,
const U& v)
2677 ->
decltype(optional_internal::convertible_to_bool(*x > v)) {
2678 return static_cast<bool>(x) ?
static_cast<bool>(*x > v) :
false;
2680template <
typename T,
typename U>
2681constexpr auto operator>(
const U& v,
const optional<T>& x)
2682 ->
decltype(optional_internal::convertible_to_bool(v > *x)) {
2683 return static_cast<bool>(x) ?
static_cast<bool>(v > *x) :
true;
2685template <
typename T,
typename U>
2686constexpr auto operator>=(
const optional<T>& x,
const U& v)
2687 ->
decltype(optional_internal::convertible_to_bool(*x >= v)) {
2688 return static_cast<bool>(x) ?
static_cast<bool>(*x >= v) :
false;
2690template <
typename T,
typename U>
2691constexpr auto operator>=(
const U& v,
const optional<T>& x)
2692 ->
decltype(optional_internal::convertible_to_bool(v >= *x)) {
2693 return static_cast<bool>(x) ?
static_cast<bool>(v >= *x) :
true;
2701template <
typename T>
2702struct hash<phmap::optional<T> >
2715template <
class,
class =
void>
2716struct IsTransparent : std::false_type {};
2718struct IsTransparent<T, phmap::void_t<typename T::is_transparent>>
2719 : std::true_type {};
2721template <
bool is_transparent>
2725 template <
typename K,
typename key_type>
2733 template <
typename K,
typename key_type>
2734 using type = key_type;
2738 #pragma warning(push)
2740 #pragma warning(disable : 4820)
2747template <
typename PolicyTraits,
typename Alloc>
2748class node_handle_base
2751 using slot_type =
typename PolicyTraits::slot_type;
2754 using allocator_type = Alloc;
2756 constexpr node_handle_base() {}
2758 node_handle_base(node_handle_base&& other)
noexcept {
2759 *
this = std::move(other);
2762 ~node_handle_base() { destroy(); }
2764 node_handle_base& operator=(node_handle_base&& other)
noexcept {
2766 if (!other.empty()) {
2767 alloc_ = other.alloc_;
2768 PolicyTraits::transfer(alloc(), slot(), other.slot());
2774 bool empty() const noexcept {
return !alloc_; }
2775 explicit operator bool() const noexcept {
return !empty(); }
2776 allocator_type get_allocator()
const {
return *alloc_; }
2779 friend struct CommonAccess;
2782 node_handle_base(
transfer_tag_t,
const allocator_type& a, slot_type* s)
2784 PolicyTraits::transfer(alloc(), slot(), s);
2788 node_handle_base(
move_tag_t,
const allocator_type& a, slot_type* s)
2790 PolicyTraits::construct(alloc(), slot(), s);
2793 node_handle_base(
const allocator_type& a, slot_type* s) : alloc_(a) {
2794 PolicyTraits::transfer(alloc(), slot(), s);
2802 PolicyTraits::destroy(alloc(), slot());
2808 assert(alloc_.has_value());
2809 alloc_ = phmap::nullopt;
2812 slot_type* slot()
const {
2814 return reinterpret_cast<slot_type*
>(std::addressof(slot_space_));
2817 allocator_type* alloc() {
return std::addressof(*alloc_); }
2820 phmap::optional<allocator_type> alloc_;
2821 mutable phmap::aligned_storage_t<
sizeof(slot_type),
alignof(slot_type)> slot_space_;
2825 #pragma warning(pop)
2830template <
typename Policy,
typename PolicyTraits,
typename Alloc,
2832class node_handle :
public node_handle_base<PolicyTraits, Alloc>
2834 using Base = node_handle_base<PolicyTraits, Alloc>;
2837 using value_type =
typename PolicyTraits::value_type;
2839 constexpr node_handle() {}
2841 value_type& value()
const {
return PolicyTraits::element(this->slot()); }
2843 value_type& key()
const {
return PolicyTraits::element(this->slot()); }
2846 friend struct CommonAccess;
2853template <
typename Policy,
typename PolicyTraits,
typename Alloc>
2854class node_handle<Policy, PolicyTraits, Alloc,
2855 phmap::void_t<typename Policy::mapped_type>>
2856 :
public node_handle_base<PolicyTraits, Alloc>
2858 using Base = node_handle_base<PolicyTraits, Alloc>;
2861 using key_type =
typename Policy::key_type;
2862 using mapped_type =
typename Policy::mapped_type;
2864 constexpr node_handle() {}
2866 auto key() const -> decltype(PolicyTraits::key(this->slot())) {
2867 return PolicyTraits::key(this->slot());
2870 mapped_type& mapped()
const {
2871 return PolicyTraits::value(&PolicyTraits::element(this->slot()));
2875 friend struct CommonAccess;
2883 template <
typename Node>
2884 static auto GetSlot(
const Node& node) ->
decltype(node.slot()) {
2888 template <
typename Node>
2889 static void Destroy(Node* node) {
2893 template <
typename Node>
2894 static void Reset(Node* node) {
2898 template <
typename T,
typename... Args>
2899 static T Make(Args&&... args) {
2900 return T(std::forward<Args>(args)...);
2903 template <
typename T,
typename... Args>
2904 static T Transfer(Args&&... args) {
2905 return T(
typename T::transfer_tag_t{}, std::forward<Args>(args)...);
2908 template <
typename T,
typename... Args>
2909 static T Move(Args&&... args) {
2910 return T(
typename T::move_tag_t{}, std::forward<Args>(args)...);
2915template <
class Iterator,
class NodeType>
2916struct InsertReturnType
2927#ifdef ADDRESS_SANITIZER
2928 #include <sanitizer/asan_interface.h>
2937template <
typename T>
2940namespace span_internal {
2942constexpr size_t Min(
size_t a,
size_t b)
noexcept {
return a < b ? a : b; }
2945template <
typename C>
2946constexpr auto GetDataImpl(C& c,
char)
noexcept
2947 ->
decltype(c.data()) {
2952inline char* GetDataImpl(std::string& s,
2957template <
typename C>
2958constexpr auto GetData(C& c)
noexcept
2959 ->
decltype(GetDataImpl(c, 0)) {
2960 return GetDataImpl(c, 0);
2964template <
typename C>
2966 std::is_integral<phmap::decay_t<decltype(std::declval<C&>().size())>>;
2974template <
typename T,
typename C>
2976 std::is_convertible<phmap::decay_t<decltype(GetData(std::declval<C&>()))>*,
2980template <
typename C>
2982 using type =
typename phmap::remove_reference_t<C>::value_type;
2985template <
typename T,
size_t N>
2990template <
typename C>
2991using ElementT =
typename ElementType<C>::type;
2993template <
typename T>
2994using EnableIfMutable =
2995 typename std::enable_if<!std::is_const<T>::value,
int>::type;
2997template <
typename T>
2999 static_assert(std::is_const<T>::value,
"");
3000 return std::equal(a.begin(), a.end(), b.begin(), b.end());
3003template <
typename T>
3005 static_assert(std::is_const<T>::value,
"");
3006 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
3013template <
typename From,
typename To>
3015 static std::true_type testval(To);
3016 static std::false_type testval(...);
3018 using type =
decltype(testval(std::declval<From>()));
3021template <
typename From,
typename To>
3026template <
typename From,
typename To>
3027using EnableIfConvertibleToSpanConst =
3028 typename std::enable_if<IsConvertible<From, Span<const To>>::value>::type;
3108template <
typename T>
3114 template <
typename C>
3115 using EnableIfConvertibleFrom =
3116 typename std::enable_if<span_internal::HasData<T, C>::value &&
3117 span_internal::HasSize<C>::value>::type;
3120 template <
typename U>
3121 using EnableIfConstView =
3122 typename std::enable_if<std::is_const<T>::value, U>::type;
3125 template <
typename U>
3126 using EnableIfMutableView =
3127 typename std::enable_if<!std::is_const<T>::value, U>::type;
3130 using value_type = phmap::remove_cv_t<T>;
3132 using const_pointer =
const T*;
3133 using reference = T&;
3134 using const_reference =
const T&;
3135 using iterator = pointer;
3136 using const_iterator = const_pointer;
3137 using reverse_iterator = std::reverse_iterator<iterator>;
3138 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
3139 using size_type = size_t;
3140 using difference_type = ptrdiff_t;
3142 static const size_type npos = ~(size_type(0));
3144 constexpr Span() noexcept :
Span(
nullptr, 0) {}
3145 constexpr Span(pointer array, size_type lgth) noexcept
3146 : ptr_(array), len_(lgth) {}
3150 constexpr Span(T (&a)[N])
noexcept
3155 template <
typename V,
typename = EnableIfConvertibleFrom<V>,
3156 typename = EnableIfMutableView<V>>
3157 explicit Span(V& v)
noexcept
3158 :
Span(span_internal::GetData(v), v.size()) {}
3161 template <
typename V,
typename = EnableIfConvertibleFrom<V>,
3162 typename = EnableIfConstView<V>>
3163 constexpr Span(
const V& v)
noexcept
3164 :
Span(span_internal::GetData(v), v.size()) {}
3201 template <
typename LazyT = T,
3202 typename = EnableIfConstView<LazyT>>
3204 std::initializer_list<value_type> v)
noexcept
3205 :
Span(v.begin(), v.size()) {}
3213 constexpr pointer data()
const noexcept {
return ptr_; }
3218 constexpr size_type size()
const noexcept {
return len_; }
3223 constexpr size_type length()
const noexcept {
return size(); }
3228 constexpr bool empty()
const noexcept {
return size() == 0; }
3233 constexpr reference operator[](size_type i)
const noexcept {
3235 return *(data() + i);
3241 constexpr reference at(size_type i)
const {
3242 return PHMAP_PREDICT_TRUE(i < size())
3244 : (base_internal::ThrowStdOutOfRange(
3245 "Span::at failed bounds check"),
3252 constexpr reference front()
const noexcept {
3253 return PHMAP_ASSERT(size() > 0), *data();
3259 constexpr reference back()
const noexcept {
3260 return PHMAP_ASSERT(size() > 0), *(data() + size() - 1);
3266 constexpr iterator begin()
const noexcept {
return data(); }
3271 constexpr const_iterator cbegin()
const noexcept {
return begin(); }
3276 constexpr iterator end()
const noexcept {
return data() + size(); }
3281 constexpr const_iterator cend()
const noexcept {
return end(); }
3286 constexpr reverse_iterator rbegin()
const noexcept {
3287 return reverse_iterator(end());
3293 constexpr const_reverse_iterator crbegin()
const noexcept {
return rbegin(); }
3298 constexpr reverse_iterator rend()
const noexcept {
3299 return reverse_iterator(begin());
3305 constexpr const_reverse_iterator crend()
const noexcept {
return rend(); }
3312 void remove_prefix(size_type n)
noexcept {
3313 assert(size() >= n);
3321 void remove_suffix(size_type n)
noexcept {
3322 assert(size() >= n);
3342 constexpr Span subspan(size_type pos = 0, size_type len = npos)
const {
3343 return (pos <= size())
3344 ?
Span(data() + pos, span_internal::Min(size() - pos, len))
3345 : (base_internal::ThrowStdOutOfRange(
"pos > size()"),
Span());
3359 constexpr Span first(size_type len)
const {
3360 return (len <= size())
3362 : (base_internal::ThrowStdOutOfRange(
"len > size()"),
Span());
3376 constexpr Span last(size_type len)
const {
3377 return (len <= size())
3378 ?
Span(size() - len + data(), len)
3379 : (base_internal::ThrowStdOutOfRange(
"len > size()"),
Span());
3383 template <
typename H>
3384 friend H AbslHashValue(H h,
Span v) {
3385 return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
3394template <
typename T>
3412template <
typename T>
3414 return span_internal::EqualImpl<const T>(a, b);
3417template <
typename T>
3418bool operator==(Span<const T> a, Span<T> b) {
3419 return span_internal::EqualImpl<const T>(a, b);
3422template <
typename T>
3423bool operator==(Span<T> a, Span<const T> b) {
3424 return span_internal::EqualImpl<const T>(a, b);
3427template <
typename T,
typename U,
3428 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3429bool operator==(
const U& a, Span<T> b) {
3430 return span_internal::EqualImpl<const T>(a, b);
3433template <
typename T,
typename U,
3434 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3435bool operator==(Span<T> a,
const U& b) {
3436 return span_internal::EqualImpl<const T>(a, b);
3440template <
typename T>
3441bool operator!=(Span<T> a, Span<T> b) {
3445template <
typename T>
3446bool operator!=(Span<const T> a, Span<T> b) {
3450template <
typename T>
3451bool operator!=(Span<T> a, Span<const T> b) {
3455template <
typename T,
typename U,
3456 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3457bool operator!=(
const U& a, Span<T> b) {
3461template <
typename T,
typename U,
3462 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3463bool operator!=(Span<T> a,
const U& b) {
3468template <
typename T>
3469bool operator<(Span<T> a, Span<T> b) {
3470 return span_internal::LessThanImpl<const T>(a, b);
3473template <
typename T>
3474bool operator<(Span<const T> a, Span<T> b) {
3475 return span_internal::LessThanImpl<const T>(a, b);
3478template <
typename T>
3479bool operator<(Span<T> a, Span<const T> b) {
3480 return span_internal::LessThanImpl<const T>(a, b);
3483template <
typename T,
typename U,
3484 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3485bool operator<(
const U& a, Span<T> b) {
3486 return span_internal::LessThanImpl<const T>(a, b);
3489template <
typename T,
typename U,
3490 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3491bool operator<(Span<T> a,
const U& b) {
3492 return span_internal::LessThanImpl<const T>(a, b);
3496template <
typename T>
3497bool operator>(Span<T> a, Span<T> b) {
3501template <
typename T>
3502bool operator>(Span<const T> a, Span<T> b) {
3506template <
typename T>
3507bool operator>(Span<T> a, Span<const T> b) {
3511template <
typename T,
typename U,
3512 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3513bool operator>(
const U& a, Span<T> b) {
3517template <
typename T,
typename U,
3518 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3519bool operator>(Span<T> a,
const U& b) {
3524template <
typename T>
3525bool operator<=(Span<T> a, Span<T> b) {
3529template <
typename T>
3530bool operator<=(Span<const T> a, Span<T> b) {
3534template <
typename T>
3535bool operator<=(Span<T> a, Span<const T> b) {
3539template <
typename T,
typename U,
3540 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3541bool operator<=(
const U& a, Span<T> b) {
3545template <
typename T,
typename U,
3546 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3547bool operator<=(Span<T> a,
const U& b) {
3552template <
typename T>
3553bool operator>=(Span<T> a, Span<T> b) {
3557template <
typename T>
3558bool operator>=(Span<const T> a, Span<T> b) {
3562template <
typename T>
3563bool operator>=(Span<T> a, Span<const T> b) {
3567template <
typename T,
typename U,
3568 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3569bool operator>=(
const U& a, Span<T> b) {
3573template <
typename T,
typename U,
3574 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3575bool operator>=(Span<T> a,
const U& b) {
3615template <
int&... ExplicitArgumentBarrier,
typename T>
3616constexpr Span<T> MakeSpan(T* ptr,
size_t size)
noexcept {
3617 return Span<T>(ptr, size);
3620template <
int&... ExplicitArgumentBarrier,
typename T>
3621Span<T> MakeSpan(T* begin, T* end)
noexcept {
3622 return PHMAP_ASSERT(begin <= end), Span<T>(begin, end - begin);
3625template <
int&... ExplicitArgumentBarrier,
typename C>
3626constexpr auto MakeSpan(C& c)
noexcept
3627 ->
decltype(phmap::MakeSpan(span_internal::GetData(c), c.size())) {
3628 return MakeSpan(span_internal::GetData(c), c.size());
3631template <
int&... ExplicitArgumentBarrier,
typename T,
size_t N>
3632constexpr Span<T> MakeSpan(T (&array)[N])
noexcept {
3633 return Span<T>(array, N);
3660template <
int&... ExplicitArgumentBarrier,
typename T>
3661constexpr Span<const T> MakeConstSpan(T* ptr,
size_t size)
noexcept {
3662 return Span<const T>(ptr, size);
3665template <
int&... ExplicitArgumentBarrier,
typename T>
3666Span<const T> MakeConstSpan(T* begin, T* end)
noexcept {
3667 return PHMAP_ASSERT(begin <= end), Span<const T>(begin, end - begin);
3670template <
int&... ExplicitArgumentBarrier,
typename C>
3671constexpr auto MakeConstSpan(
const C& c)
noexcept ->
decltype(MakeSpan(c)) {
3675template <
int&... ExplicitArgumentBarrier,
typename T,
size_t N>
3676constexpr Span<const T> MakeConstSpan(
const T (&array)[N])
noexcept {
3677 return Span<const T>(array, N);
3684#if defined(__GXX_RTTI)
3685 #define PHMAP_INTERNAL_HAS_CXA_DEMANGLE
3688#ifdef PHMAP_INTERNAL_HAS_CXA_DEMANGLE
3702template <
class T,
size_t N>
3705namespace internal_layout {
3708struct NotAligned {};
3710template <
class T,
size_t N>
3711struct NotAligned<const
Aligned<T, N>> {
3712 static_assert(
sizeof(T) == 0,
"Aligned<T, N> cannot be const-qualified");
3716using IntToSize = size_t;
3719using TypeToSize = size_t;
3722struct Type : NotAligned<T> {
3726template <
class T,
size_t N>
3732struct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {};
3734template <
class T,
size_t N>
3735struct SizeOf<
Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
3739struct AlignOf : NotAligned<T> {
3740 static constexpr size_t value =
alignof(T);
3743template <
class T,
size_t N>
3744struct AlignOf<
Aligned<T, N>> {
3745 static_assert(N %
alignof(T) == 0,
3746 "Custom alignment can't be lower than the type's alignment");
3747 static constexpr size_t value = N;
3751template <
class T,
class... Ts>
3754template <
class From,
class To>
3756 typename std::conditional<std::is_const<From>::value,
const To, To>::type;
3761using SliceType = Span<T>;
3765namespace adl_barrier {
3767template <
class Needle,
class... Ts>
3768constexpr size_t Find(Needle, Needle, Ts...) {
3769 static_assert(!Contains<Needle, Ts...>(),
"Duplicate element type");
3773template <
class Needle,
class T,
class... Ts>
3774constexpr size_t Find(Needle, T, Ts...) {
3775 return adl_barrier::Find(Needle(), Ts()...) + 1;
3778constexpr bool IsPow2(
size_t n) {
return !(n & (n - 1)); }
3782constexpr size_t Align(
size_t n,
size_t m) {
return (n + m - 1) & ~(m - 1); }
3784constexpr size_t Min(
size_t a,
size_t b) {
return b < a ? b : a; }
3786constexpr size_t Max(
size_t a) {
return a; }
3788template <
class... Ts>
3789constexpr size_t Max(
size_t a,
size_t b, Ts... rest) {
3790 return adl_barrier::Max(b < a ? a : b, rest...);
3796using EnableIf =
typename std::enable_if<C, int>::type;
3801using IsLegalElementType = std::integral_constant<
3802 bool, !std::is_reference<T>::value && !std::is_volatile<T>::value &&
3803 !std::is_reference<typename Type<T>::type>::value &&
3804 !std::is_volatile<typename Type<T>::type>::value &&
3805 adl_barrier::IsPow2(AlignOf<T>::value)>;
3807template <
class Elements,
class SizeSeq,
class OffsetSeq>
3823template <
class... Elements,
size_t... SizeSeq,
size_t... OffsetSeq>
3828 static_assert(
sizeof...(Elements) > 0,
"At least one field is required");
3830 "Invalid element type (see IsLegalElementType)");
3833 NumTypes =
sizeof...(Elements),
3834 NumSizes =
sizeof...(SizeSeq),
3835 NumOffsets =
sizeof...(OffsetSeq),
3839 static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1),
3841 static_assert(NumTypes > 0,
"Internal error");
3846 static constexpr size_t ElementIndex() {
3847 static_assert(Contains<Type<T>, Type<typename Type<Elements>::type>...>(),
3849 return adl_barrier::Find(Type<T>(),
3850 Type<
typename Type<Elements>::type>()...);
3854 using ElementAlignment =
3855 AlignOf<
typename std::tuple_element<N, std::tuple<Elements...>>::type>;
3859 using ElementTypes = std::tuple<typename Type<Elements>::type...>;
3863 using ElementType =
typename std::tuple_element<N, ElementTypes>::type;
3865 constexpr explicit LayoutImpl(IntToSize<SizeSeq>... sizes)
3866 : size_{sizes...} {}
3870 static constexpr size_t Alignment() {
3871 return adl_barrier::Max(AlignOf<Elements>::value...);
3882 template <
size_t N, EnableIf<N == 0> = 0>
3883 constexpr size_t Offset()
const {
3887 template <
size_t N, EnableIf<N != 0> = 0>
3888 constexpr size_t Offset()
const {
3889 static_assert(N < NumOffsets,
"Index out of bounds");
3890 return adl_barrier::Align(
3891 Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1],
3892 ElementAlignment<N>::value);
3904 constexpr size_t Offset()
const {
3905 return Offset<ElementIndex<T>()>();
3909 constexpr std::array<size_t, NumOffsets> Offsets()
const {
3910 return {{Offset<OffsetSeq>()...}};
3923 constexpr size_t Size()
const {
3924 static_assert(N < NumSizes,
"Index out of bounds");
3937 constexpr size_t Size()
const {
3938 return Size<ElementIndex<T>()>();
3942 constexpr std::array<size_t, NumSizes> Sizes()
const {
3943 return {{Size<SizeSeq>()...}};
3958 template <
size_t N,
class Char>
3959 CopyConst<Char, ElementType<N>>* Pointer(Char* p)
const {
3960 using C =
typename std::remove_const<Char>::type;
3962 std::is_same<C, char>() || std::is_same<C, unsigned char>() ||
3963 std::is_same<C, signed char>(),
3964 "The argument must be a pointer to [const] [signed|unsigned] char");
3965 constexpr size_t alignment = Alignment();
3967 assert(
reinterpret_cast<uintptr_t
>(p) % alignment == 0);
3968 return reinterpret_cast<CopyConst<Char, ElementType<N>
>*>(p + Offset<N>());
3984 template <
class T,
class Char>
3985 CopyConst<Char, T>* Pointer(Char* p)
const {
3986 return Pointer<ElementIndex<T>()>(p);
4005 template <
class Char>
4006 std::tuple<CopyConst<
4007 Char,
typename std::tuple_element<OffsetSeq, ElementTypes>::type>*...>
4008 Pointers(Char* p)
const {
4009 return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(
4010 Pointer<OffsetSeq>(p)...);
4025 template <
size_t N,
class Char>
4026 SliceType<CopyConst<Char, ElementType<N>>> Slice(Char* p)
const {
4027 return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>());
4042 template <
class T,
class Char>
4043 SliceType<CopyConst<Char, T>> Slice(Char* p)
const {
4044 return Slice<ElementIndex<T>()>(p);
4063 template <
class Char>
4064 std::tuple<SliceType<CopyConst<
4065 Char,
typename std::tuple_element<SizeSeq, ElementTypes>::type>>...>
4066 Slices(Char* p)
const {
4070 return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
4071 Slice<SizeSeq>(p)...);
4081 constexpr size_t AllocSize()
const {
4082 static_assert(NumTypes == NumSizes,
"You must specify sizes of all fields");
4083 return Offset<NumTypes - 1>() +
4084 SizeOf<ElementType<NumTypes - 1>>() * size_[NumTypes - 1];
4094 template <
class Char,
size_t N = NumOffsets - 1, EnableIf<N == 0> = 0>
4095 void PoisonPadding(
const Char* p)
const {
4099 template <
class Char,
size_t N = NumOffsets - 1, EnableIf<N != 0> = 0>
4100 void PoisonPadding(
const Char* p)
const {
4101 static_assert(N < NumOffsets,
"Index out of bounds");
4103#ifdef ADDRESS_SANITIZER
4104 PoisonPadding<Char, N - 1>(p);
4106 if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
4108 Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1];
4109 ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
4116 size_t size_[NumSizes > 0 ? NumSizes : 1];
4119template <
size_t NumSizes,
class... Ts>
4120using LayoutType = LayoutImpl<
4121 std::tuple<Ts...>, phmap::make_index_sequence<NumSizes>,
4122 phmap::make_index_sequence<adl_barrier::Min(
sizeof...(Ts), NumSizes + 1)>>;
4134template <
class... Ts>
4135class Layout :
public internal_layout::LayoutType<sizeof...(Ts), Ts...>
4138 static_assert(
sizeof...(Ts) > 0,
"At least one field is required");
4141 "Invalid element type (see IsLegalElementType)");
4143 template <
size_t NumSizes>
4144 using PartialType = internal_layout::LayoutType<NumSizes, Ts...>;
4146 template <
class... Sizes>
4147 static constexpr PartialType<
sizeof...(Sizes)> Partial(Sizes&&... sizes) {
4148 static_assert(
sizeof...(Sizes) <=
sizeof...(Ts),
"");
4149 return PartialType<
sizeof...(Sizes)>(phmap::forward<Sizes>(sizes)...);
4160 constexpr explicit Layout(internal_layout::TypeToSize<Ts>... sizes)
4161 : internal_layout::LayoutType<sizeof...(Ts), Ts...>(sizes...) {}
4174 #define PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
4176 #define PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
4182template <
typename... Ts>
4183class CompressedTuple;
4185namespace internal_compressed_tuple {
4187template <
typename D,
size_t I>
4189template <
typename... B,
size_t I>
4191 : std::tuple_element<I, std::tuple<B...>> {};
4192template <
typename D,
size_t I>
4201template <
typename T>
4202constexpr bool IsFinal() {
4203#if defined(__clang__) || defined(__GNUC__)
4204 return __is_final(T);
4210template <
typename T>
4211constexpr bool ShouldUseBase() {
4212#ifdef __INTEL_COMPILER
4217 return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>();
4225template <
typename D,
size_t I,
bool = ShouldUseBase<ElemT<D, I>>()>
4228 using T = ElemT<D, I>;
4230 constexpr Storage() =
default;
4231 explicit constexpr Storage(T&& v) : value(phmap::forward<T>(v)) {}
4232 constexpr const T& get()
const& {
return value; }
4233 T& get() & {
return value; }
4234 constexpr const T&& get()
const&& {
return phmap::move(*this).value; }
4235 T&& get() && {
return std::move(*this).value; }
4238template <
typename D,
size_t I>
4239struct PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
Storage<D, I, true>
4242 using T = internal_compressed_tuple::ElemT<D, I>;
4243 constexpr Storage() =
default;
4244 explicit constexpr Storage(T&& v) : T(phmap::forward<T>(v)) {}
4245 constexpr const T& get()
const& {
return *
this; }
4246 T& get() & {
return *
this; }
4247 constexpr const T&& get()
const&& {
return phmap::move(*
this); }
4248 T&& get() && {
return std::move(*
this); }
4251template <
typename D,
typename I>
4252struct PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl;
4254template <
typename... Ts,
size_t... I>
4255struct PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
4261 :
Storage<CompressedTuple<Ts...>,
4262 std::integral_constant<size_t, I>::value>...
4264 constexpr CompressedTupleImpl() =
default;
4265 explicit constexpr CompressedTupleImpl(Ts&&... args)
4289template <
typename... Ts>
4291 :
private internal_compressed_tuple::CompressedTupleImpl<
4292 CompressedTuple<Ts...>, phmap::index_sequence_for<Ts...>>
4296 using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>;
4301 : CompressedTuple::CompressedTupleImpl(phmap::forward<Ts>(base)...) {}
4309 constexpr const ElemT<I>& get()
const& {
4314 ElemT<I>&& get() && {
4315 return std::move(*
this)
4316 .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
4320 constexpr const ElemT<I>&& get()
const&& {
4321 return phmap::move(*
this)
4322 .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
4340 #pragma warning(push)
4342 #pragma warning(disable : 4324)
4355template <
size_t Alignment,
class Alloc>
4356void* Allocate(Alloc* alloc,
size_t n) {
4357 static_assert(Alignment > 0,
"");
4358 assert(n &&
"n must be positive");
4359 struct alignas(Alignment) M {};
4362 A mem_alloc(*alloc);
4363 void* p = AT::allocate(mem_alloc, (n +
sizeof(M) - 1) /
sizeof(M));
4364 assert(
reinterpret_cast<uintptr_t
>(p) % Alignment == 0 &&
4365 "allocator does not respect alignment");
4373template <
size_t Alignment,
class Alloc>
4374void Deallocate(Alloc* alloc,
void* p,
size_t n) {
4375 static_assert(Alignment > 0,
"");
4376 assert(n &&
"n must be positive");
4377 struct alignas(Alignment) M {};
4380 A mem_alloc(*alloc);
4381 AT::deallocate(mem_alloc,
static_cast<M*
>(p),
4382 (n +
sizeof(M) - 1) /
sizeof(M));
4386 #pragma warning(pop)
4391inline void SanitizerPoisonMemoryRegion(
const void* m,
size_t s) {
4392#ifdef ADDRESS_SANITIZER
4393 ASAN_POISON_MEMORY_REGION(m, s);
4395#ifdef MEMORY_SANITIZER
4396 __msan_poison(m, s);
4402inline void SanitizerUnpoisonMemoryRegion(
const void* m,
size_t s) {
4403#ifdef ADDRESS_SANITIZER
4404 ASAN_UNPOISON_MEMORY_REGION(m, s);
4406#ifdef MEMORY_SANITIZER
4407 __msan_unpoison(m, s);
4413template <
typename T>
4414inline void SanitizerPoisonObject(
const T*
object) {
4415 SanitizerPoisonMemoryRegion(
object,
sizeof(T));
4418template <
typename T>
4419inline void SanitizerUnpoisonObject(
const T*
object) {
4420 SanitizerUnpoisonMemoryRegion(
object,
sizeof(T));
4431#if defined(__clang__)
4432 #define PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
4434 #define PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(x)
4437#define PHMAP_GUARDED_BY(x) PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
4438#define PHMAP_PT_GUARDED_BY(x) PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
4440#define PHMAP_ACQUIRED_AFTER(...) \
4441 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
4443#define PHMAP_ACQUIRED_BEFORE(...) \
4444 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
4446#define PHMAP_EXCLUSIVE_LOCKS_REQUIRED(...) \
4447 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
4449#define PHMAP_SHARED_LOCKS_REQUIRED(...) \
4450 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
4452#define PHMAP_LOCKS_EXCLUDED(...) \
4453 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
4455#define PHMAP_LOCK_RETURNED(x) \
4456 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
4458#define PHMAP_LOCKABLE \
4459 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(lockable)
4461#define PHMAP_SCOPED_LOCKABLE \
4462 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
4464#define PHMAP_EXCLUSIVE_LOCK_FUNCTION(...) \
4465 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
4467#define PHMAP_SHARED_LOCK_FUNCTION(...) \
4468 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
4470#define PHMAP_UNLOCK_FUNCTION(...) \
4471 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
4473#define PHMAP_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
4474 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
4476#define PHMAP_SHARED_TRYLOCK_FUNCTION(...) \
4477 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
4479#define PHMAP_ASSERT_EXCLUSIVE_LOCK(...) \
4480 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
4482#define PHMAP_ASSERT_SHARED_LOCK(...) \
4483 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
4485#define PHMAP_NO_THREAD_SAFETY_ANALYSIS \
4486 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
4495#define PHMAP_TS_UNCHECKED(x) ""
4500#define PHMAP_TS_FIXME(x) ""
4507#define PHMAP_NO_THREAD_SAFETY_ANALYSIS_FIXME PHMAP_NO_THREAD_SAFETY_ANALYSIS
4512#define PHMAP_GUARDED_BY_FIXME(x)
4517#define PHMAP_TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x)
4521namespace thread_safety_analysis {
4525template <
typename T>
4526inline const T& ts_unchecked_read(
const T& v) PHMAP_NO_THREAD_SAFETY_ANALYSIS {
4530template <
typename T>
4531inline T& ts_unchecked_read(T& v) PHMAP_NO_THREAD_SAFETY_ANALYSIS {
4539namespace memory_internal {
4549template <
class Pair,
class = std::true_type>
4551 static constexpr size_t kFirst = (size_t)-1;
4552 static constexpr size_t kSecond = (size_t)-1;
4555template <
class Pair>
4558 static constexpr size_t kFirst = offsetof(
Pair, first);
4559 static constexpr size_t kSecond = offsetof(
Pair, second);
4563template <
class K,
class V>
4574 static constexpr bool LayoutCompatible() {
4575 return std::is_standard_layout<P>() &&
sizeof(P) ==
sizeof(Pair) &&
4576 alignof(P) ==
alignof(Pair) &&
4586 static constexpr bool value = std::is_standard_layout<K>() &&
4587 std::is_standard_layout<Pair>() &&
4589 LayoutCompatible<std::pair<K, V>>() &&
4590 LayoutCompatible<std::pair<const K, V>>();
4621template <
class K,
class V>
4629 using value_type = std::pair<const K, V>;
4630 using mutable_value_type = std::pair<K, V>;
4633 mutable_value_type mutable_value;
4639template <
class K,
class V>
4643 using value_type = std::pair<const K, V>;
4644 using mutable_value_type = std::pair<K, V>;
4658 static value_type& element(
slot_type* slot) {
return slot->value; }
4659 static const value_type& element(
const slot_type* slot) {
4663 static const K& key(
const slot_type* slot) {
4664 return kMutableKeys::value ? slot->key : slot->value.first;
4667 template <
class Allocator,
class... Args>
4668 static void construct(Allocator* alloc,
slot_type* slot, Args&&... args) {
4670 if (kMutableKeys::value) {
4672 std::forward<Args>(args)...);
4675 std::forward<Args>(args)...);
4680 template <
class Allocator>
4683 if (kMutableKeys::value) {
4685 *alloc, &slot->mutable_value, std::move(other->mutable_value));
4688 std::move(other->value));
4692 template <
class Allocator>
4693 static void destroy(Allocator* alloc,
slot_type* slot) {
4694 if (kMutableKeys::value) {
4701 template <
class Allocator>
4702 static void transfer(Allocator* alloc,
slot_type* new_slot,
4705 if (kMutableKeys::value) {
4707 *alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));
4710 std::move(old_slot->value));
4712 destroy(alloc, old_slot);
4715 template <
class Allocator>
4717 if (kMutableKeys::value) {
4719 swap(a->mutable_value, b->mutable_value);
4721 value_type tmp = std::move(a->value);
4724 std::move(b->value));
4731 template <
class Allocator>
4733 if (kMutableKeys::value) {
4734 dest->mutable_value = std::move(src->mutable_value);
4738 std::move(src->value));
4742 template <
class Allocator>
4745 for (
slot_type *src = first, *dest = result; src != last; ++src, ++dest)
4746 move(alloc, src, dest);
4756#ifdef BOOST_THREAD_LOCK_OPTIONS_HPP
4757 using defer_lock_t = boost::defer_lock_t;
4758 using try_to_lock_t = boost::try_to_lock_t;
4759 using adopt_lock_t = boost::adopt_lock_t;
4779 bool try_lock() {
return true; }
4780 void lock_shared() {}
4781 void unlock_shared() {}
4782 bool try_lock_shared() {
return true; }
4786template <
class MutexType>
4793 using mutex_type = MutexType;
4795 explicit DoNothing(mutex_type& )
noexcept {}
4796 explicit DoNothing(mutex_type& , mutex_type&)
noexcept {}
4800 template<
class T>
explicit DoNothing(T&&) {}
4804 bool owns_lock()
const noexcept {
return true; }
4811 using mutex_type = MutexType;
4813 WriteLock() : m_(
nullptr), locked_(
false) {}
4815 explicit WriteLock(mutex_type &m) : m_(&m) {
4821 m_(&m), locked_(
true)
4825 m_(&m), locked_(
false)
4829 m_(&m), locked_(
false) {
4834 m_(std::move(o.m_)), locked_(std::move(o.locked_)) {
4867 locked_ = m_->try_lock();
4871 bool owns_lock()
const noexcept {
return locked_; }
4874 std::swap(m_, o.m_);
4875 std::swap(locked_, o.locked_);
4878 mutex_type *mutex()
const noexcept {
return m_; }
4889 using mutex_type = MutexType;
4891 ReadLock() : m_(
nullptr), locked_(
false) {}
4893 explicit ReadLock(mutex_type &m) : m_(&m) {
4899 m_(&m), locked_(
true)
4903 m_(&m), locked_(
false)
4907 m_(&m), locked_(
false) {
4908 m_->try_lock_shared();
4912 m_(std::move(o.m_)), locked_(std::move(o.locked_)) {
4925 m_->unlock_shared();
4937 m_->unlock_shared();
4945 locked_ = m_->try_lock_shared();
4949 bool owns_lock()
const noexcept {
return locked_; }
4952 std::swap(m_, o.m_);
4953 std::swap(locked_, o.locked_);
4956 mutex_type *mutex()
const noexcept {
return m_; }
4967 using mutex_type = MutexType;
4969 explicit WriteLocks(mutex_type& m1, mutex_type& m2) :
4997 using mutex_type = MutexType;
4999 explicit ReadLocks(mutex_type& m1, mutex_type& m2) :
5013 _m1.unlock_shared();
5014 _m2.unlock_shared();
5042template <
class Mtx_>
5046 using mutex_type = Mtx_;
5076#ifdef ABSL_SYNCHRONIZATION_MUTEX_H_
5078 struct AbslMutex :
protected absl::Mutex
5080 void lock() { this->Lock(); }
5081 void unlock() { this->Unlock(); }
5082 void try_lock() { this->TryLock(); }
5083 void lock_shared() { this->ReaderLock(); }
5084 void unlock_shared() { this->ReaderUnlock(); }
5085 void try_lock_shared() { this->ReaderTryLock(); }
5089 class LockableImpl<absl::Mutex> :
public AbslMutex
5092 using mutex_type = phmap::AbslMutex;
5093 using Base = LockableBaseImpl<phmap::AbslMutex>;
5094 using SharedLock =
typename Base::ReadLock;
5095 using UpgradeLock =
typename Base::WriteLock;
5096 using UniqueLock =
typename Base::WriteLock;
5097 using SharedLocks =
typename Base::ReadLocks;
5098 using UniqueLocks =
typename Base::WriteLocks;
5099 using UpgradeToUnique =
typename Base::DoNothing;
5107#ifdef BOOST_THREAD_SHARED_MUTEX_HPP
5112 class LockableImpl<boost::shared_mutex> :
public boost::shared_mutex
5115 using mutex_type = boost::shared_mutex;
5116 using Base = LockableBaseImpl<boost::shared_mutex>;
5117 using SharedLock = boost::shared_lock<mutex_type>;
5118 using UpgradeLock = boost::unique_lock<mutex_type>;
5119 using UniqueLock = boost::unique_lock<mutex_type>;
5120 using SharedLocks =
typename Base::ReadLocks;
5121 using UniqueLocks =
typename Base::WriteLocks;
5122 using UpgradeToUnique =
typename Base::DoNothing;
5127 class LockableImpl<boost::upgrade_mutex> :
public boost::upgrade_mutex
5130 using mutex_type = boost::upgrade_mutex;
5131 using SharedLock = boost::shared_lock<mutex_type>;
5132 using UpgradeLock = boost::upgrade_lock<mutex_type>;
5133 using UniqueLock = boost::unique_lock<mutex_type>;
5134 using SharedLocks =
typename Base::ReadLocks;
5135 using UniqueLocks =
typename Base::WriteLocks;
5136 using UpgradeToUnique = boost::upgrade_to_unique_lock<mutex_type>;
5145#ifdef PHMAP_HAVE_SHARED_MUTEX
5149 class LockableImpl<std::shared_mutex> :
public std::shared_mutex
5152 using mutex_type = std::shared_mutex;
5153 using Base = LockableBaseImpl<std::shared_mutex>;
5154 using SharedLock = std::shared_lock<mutex_type>;
5155 using UpgradeLock = std::unique_lock<mutex_type>;
5156 using UniqueLock = std::unique_lock<mutex_type>;
5157 using SharedLocks =
typename Base::ReadLocks;
5158 using UniqueLocks =
typename Base::WriteLocks;
5159 using UpgradeToUnique =
typename Base::DoNothing;
5167 #pragma warning(pop)
A generic couple structure.
Definition GuCookingConvexPolygonsBuilder.cpp:76
Definition phmap_base.h:4887
Definition phmap_base.h:4995
Definition phmap_base.h:4809
Definition phmap_base.h:4965
Definition phmap_base.h:4788
Definition phmap_base.h:5044
Definition phmap_base.h:4773
Definition phmap_base.h:3110
Definition phmap_base.h:1932
Definition phmap_base.h:1895
Definition phmap_base.h:1781
Definition phmap_base.h:1718
Definition phmap_base.h:1821
Definition phmap_base.h:4293
@ Aligned
Definition Constants.h:240
Definition phmap_base.h:76
Definition phmap_base.h:85
Definition phmap_base.h:4792
Definition phmap_base.h:4761
Definition phmap_base.h:1599
Definition phmap_base.h:1379
Definition phmap_base.h:840
Definition phmap_base.h:825
Definition phmap_base.h:823
Definition phmap_base.h:808
Definition phmap_base.h:806
Definition phmap_base.h:853
Definition phmap_base.h:781
Definition phmap_base.h:779
Definition phmap_base.h:755
Definition phmap_base.h:753
Definition phmap_base.h:746
Definition phmap_base.h:743
Definition phmap_base.h:200
Definition phmap_base.h:1606
Definition phmap_base.h:4762
Definition phmap_base.h:224
Definition phmap_base.h:1019
Definition phmap_base.h:990
Definition phmap_base.h:1006
Definition phmap_base.h:906
Definition phmap_base.h:596
Definition phmap_base.h:163
Definition phmap_base.h:168
Definition phmap_base.h:260
Definition phmap_base.h:254
Definition phmap_base.h:248
Definition phmap_base.h:242
Definition phmap_base.h:1272
Definition phmap_base.h:1264
Definition phmap_base.h:1159
Definition phmap_base.h:1311
Definition phmap_base.h:1282
Definition phmap_base.h:1291
Definition phmap_base.h:237
Definition phmap_base.h:1697
Definition phmap_base.h:1711
Definition phmap_base.h:2009
Definition phmap_base.h:1999
Definition phmap_base.h:2021
Definition phmap_base.h:1325
Definition phmap_base.h:4188
Definition phmap_base.h:4227
Definition phmap_base.h:4641
Definition phmap_base.h:4565
Definition phmap_base.h:4550
Definition phmap_base.h:2787
Definition phmap_base.h:2781
Definition phmap_base.h:2981
Definition phmap_base.h:3014
Definition phmap_base.h:3022
Definition phmap_base.h:4763
Definition phmap_base.h:367
Definition phmap_base.h:357
Definition phmap_base.h:95
Definition phmap_base.h:104
Definition phmap_base.h:137
Definition phmap_base.h:150
Definition phmap_base.h:124
Definition phmap_base.h:134
Definition phmap_base.h:922
Definition phmap_base.h:938
Definition phmap_base.h:4623