NIM 跨平台 C++ SDK
载入中...
搜索中...
未找到
phmap_base.h
浏览该文件的文档.
1#if !defined(phmap_base_h_guard_)
2#define phmap_base_h_guard_
3
4// ---------------------------------------------------------------------------
5// Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
6//
7// Licensed under the Apache License, Version 2.0 (the "License");
8// you may not use this file except in compliance with the License.
9// You may obtain a copy of the License at
10//
11// https://www.apache.org/licenses/LICENSE-2.0
12//
13// Unless required by applicable law or agreed to in writing, software
14// distributed under the License is distributed on an "AS IS" BASIS,
15// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16// See the License for the specific language governing permissions and
17// limitations under the License.
18//
19// Includes work from abseil-cpp (https://github.com/abseil/abseil-cpp)
20// with modifications.
21//
22// Copyright 2018 The Abseil Authors.
23//
24// Licensed under the Apache License, Version 2.0 (the "License");
25// you may not use this file except in compliance with the License.
26// You may obtain a copy of the License at
27//
28// https://www.apache.org/licenses/LICENSE-2.0
29//
30// Unless required by applicable law or agreed to in writing, software
31// distributed under the License is distributed on an "AS IS" BASIS,
32// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33// See the License for the specific language governing permissions and
34// limitations under the License.
35// ---------------------------------------------------------------------------
36
37#include <algorithm>
38#include <cassert>
39#include <cstddef>
40#include <initializer_list>
41#include <iterator>
42#include <string>
43#include <type_traits>
44#include <utility>
45#include <functional>
46#include <tuple>
47#include <utility>
48#include <memory>
49#include <mutex> // for std::lock
50
51#include "phmap_config.h"
52
53#ifdef PHMAP_HAVE_SHARED_MUTEX
54 #include <shared_mutex> // after "phmap_config.h"
55#endif
56
57#ifdef _MSC_VER
58 #pragma warning(push)
59 #pragma warning(disable : 4514) // unreferenced inline function has been removed
60 #pragma warning(disable : 4582) // constructor is not implicitly called
61 #pragma warning(disable : 4625) // copy constructor was implicitly defined as deleted
62 #pragma warning(disable : 4626) // assignment operator was implicitly defined as deleted
63 #pragma warning(disable : 4710) // function not inlined
64 #pragma warning(disable : 4711) // selected for automatic inline expansion
65 #pragma warning(disable : 4820) // '6' bytes padding added after data member
66#endif // _MSC_VER
67
68namespace phmap {
69
70template <class T> using Allocator = typename std::allocator<T>;
71
72template<class T1, class T2> using Pair = typename std::pair<T1, T2>;
73
74template <class T>
75struct EqualTo
76{
77 inline bool operator()(const T& a, const T& b) const
78 {
79 return std::equal_to<T>()(a, b);
80 }
81};
82
83template <class T>
84struct Less
85{
86 inline bool operator()(const T& a, const T& b) const
87 {
88 return std::less<T>()(a, b);
89 }
90};
91
92namespace type_traits_internal {
93
94template <typename... Ts>
95struct VoidTImpl {
96 using type = void;
97};
98
99// This trick to retrieve a default alignment is necessary for our
100// implementation of aligned_storage_t to be consistent with any implementation
101// of std::aligned_storage.
102// ---------------------------------------------------------------------------
103template <size_t Len, typename T = std::aligned_storage<Len>>
105
106template <size_t Len, size_t Align>
108 std::aligned_storage<Len, Align>> {
109 static constexpr size_t value = Align;
110};
111
112// NOTE: The `is_detected` family of templates here differ from the library
113// fundamentals specification in that for library fundamentals, `Op<Args...>` is
114// evaluated as soon as the type `is_detected<Op, Args...>` undergoes
115// substitution, regardless of whether or not the `::value` is accessed. That
116// is inconsistent with all other standard traits and prevents lazy evaluation
117// in larger contexts (such as if the `is_detected` check is a trailing argument
118// of a `conjunction`. This implementation opts to instead be lazy in the same
119// way that the standard traits are (this "defect" of the detection idiom
120// specifications has been reported).
121// ---------------------------------------------------------------------------
122
123template <class Enabler, template <class...> class Op, class... Args>
125 using type = std::false_type;
126};
127
128template <template <class...> class Op, class... Args>
129struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
130 using type = std::true_type;
131};
132
133template <template <class...> class Op, class... Args>
134struct is_detected : is_detected_impl<void, Op, Args...>::type {};
135
136template <class Enabler, class To, template <class...> class Op, class... Args>
138 using type = std::false_type;
139};
140
141template <class To, template <class...> class Op, class... Args>
143 typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
144 To, Op, Args...> {
145 using type = std::true_type;
146};
147
148template <class To, template <class...> class Op, class... Args>
150 : is_detected_convertible_impl<void, To, Op, Args...>::type {};
151
152template <typename T>
154 decltype(std::declval<T&>() = std::declval<const T&>());
155
156template <typename T>
157using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
158
159} // namespace type_traits_internal
160
161template <typename T>
163 type_traits_internal::IsCopyAssignableImpl, T> {
164};
165
166template <typename T>
168 type_traits_internal::IsMoveAssignableImpl, T> {
169};
170
171// ---------------------------------------------------------------------------
172// void_t()
173//
174// Ignores the type of any its arguments and returns `void`. In general, this
175// metafunction allows you to create a general case that maps to `void` while
176// allowing specializations that map to specific types.
177//
178// This metafunction is designed to be a drop-in replacement for the C++17
179// `std::void_t` metafunction.
180//
181// NOTE: `phmap::void_t` does not use the standard-specified implementation so
182// that it can remain compatible with gcc < 5.1. This can introduce slightly
183// different behavior, such as when ordering partial specializations.
184// ---------------------------------------------------------------------------
185template <typename... Ts>
186using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
187
188// ---------------------------------------------------------------------------
189// conjunction
190//
191// Performs a compile-time logical AND operation on the passed types (which
192// must have `::value` members convertible to `bool`. Short-circuits if it
193// encounters any `false` members (and does not compare the `::value` members
194// of any remaining arguments).
195//
196// This metafunction is designed to be a drop-in replacement for the C++17
197// `std::conjunction` metafunction.
198// ---------------------------------------------------------------------------
199template <typename... Ts>
201
202template <typename T, typename... Ts>
203struct conjunction<T, Ts...>
204 : std::conditional<T::value, conjunction<Ts...>, T>::type {};
205
206template <typename T>
207struct conjunction<T> : T {};
208
209template <>
210struct conjunction<> : std::true_type {};
211
212// ---------------------------------------------------------------------------
213// disjunction
214//
215// Performs a compile-time logical OR operation on the passed types (which
216// must have `::value` members convertible to `bool`. Short-circuits if it
217// encounters any `true` members (and does not compare the `::value` members
218// of any remaining arguments).
219//
220// This metafunction is designed to be a drop-in replacement for the C++17
221// `std::disjunction` metafunction.
222// ---------------------------------------------------------------------------
223template <typename... Ts>
225
226template <typename T, typename... Ts>
227struct disjunction<T, Ts...> :
228 std::conditional<T::value, T, disjunction<Ts...>>::type {};
229
230template <typename T>
231struct disjunction<T> : T {};
232
233template <>
234struct disjunction<> : std::false_type {};
235
236template <typename T>
237struct negation : std::integral_constant<bool, !T::value> {};
238
239template <typename T>
241 : std::integral_constant<bool, __has_trivial_destructor(T) &&
242 std::is_destructible<T>::value> {};
243
244template <typename T>
246 : std::integral_constant<bool, __has_trivial_constructor(T) &&
247 std::is_default_constructible<T>::value &&
248 is_trivially_destructible<T>::value> {};
249
250template <typename T>
252 : std::integral_constant<bool, __has_trivial_copy(T) &&
253 std::is_copy_constructible<T>::value &&
254 is_trivially_destructible<T>::value> {};
255
256template <typename T>
258 : std::integral_constant<
259 bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
260 phmap::is_copy_assignable<T>::value> {};
261
262// -----------------------------------------------------------------------------
263// C++14 "_t" trait aliases
264// -----------------------------------------------------------------------------
265
266template <typename T>
267using remove_cv_t = typename std::remove_cv<T>::type;
268
269template <typename T>
270using remove_const_t = typename std::remove_const<T>::type;
271
272template <typename T>
273using remove_volatile_t = typename std::remove_volatile<T>::type;
274
275template <typename T>
276using add_cv_t = typename std::add_cv<T>::type;
277
278template <typename T>
279using add_const_t = typename std::add_const<T>::type;
280
281template <typename T>
282using add_volatile_t = typename std::add_volatile<T>::type;
283
284template <typename T>
285using remove_reference_t = typename std::remove_reference<T>::type;
286
287template <typename T>
288using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
289
290template <typename T>
291using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
292
293template <typename T>
294using remove_pointer_t = typename std::remove_pointer<T>::type;
295
296template <typename T>
297using add_pointer_t = typename std::add_pointer<T>::type;
298
299template <typename T>
300using make_signed_t = typename std::make_signed<T>::type;
301
302template <typename T>
303using make_unsigned_t = typename std::make_unsigned<T>::type;
304
305template <typename T>
306using remove_extent_t = typename std::remove_extent<T>::type;
307
308template <typename T>
309using remove_all_extents_t = typename std::remove_all_extents<T>::type;
310
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;
314
315template <typename T>
316using decay_t = typename std::decay<T>::type;
317
318template <bool B, typename T = void>
319using enable_if_t = typename std::enable_if<B, T>::type;
320
321template <bool B, typename T, typename F>
322using conditional_t = typename std::conditional<B, T, F>::type;
323
324
325template <typename... T>
326using common_type_t = typename std::common_type<T...>::type;
327
328template <typename T>
329using underlying_type_t = typename std::underlying_type<T>::type;
330
331template< class F, class... ArgTypes>
332#if PHMAP_HAVE_CC17 && defined(__cpp_lib_result_of_sfinae)
333 using invoke_result_t = typename std::invoke_result_t<F, ArgTypes...>;
334#else
335 using invoke_result_t = typename std::result_of<F(ArgTypes...)>::type;
336#endif
337
338namespace type_traits_internal {
339
340// ----------------------------------------------------------------------
341// In MSVC we can't probe std::hash or stdext::hash because it triggers a
342// static_assert instead of failing substitution. Libc++ prior to 4.0
343// also used a static_assert.
344// ----------------------------------------------------------------------
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
348#else
349 #define PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
350#endif
351
352#if !PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
353 template <typename Key, typename = size_t>
354 struct IsHashable : std::true_type {};
355#else // PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
356 template <typename Key, typename = void>
357 struct IsHashable : std::false_type {};
358
359 template <typename Key>
360 struct IsHashable<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 {};
364#endif
365
367{
368private:
369 static void Sink(...) {}
370 struct NAT {};
371
372 template <class Key>
373 static auto GetReturnType(int)
374 -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
375 template <class Key>
376 static NAT GetReturnType(...);
377
378 template <class Key>
379 static std::nullptr_t DoIt() {
380 static_assert(IsHashable<Key>::value,
381 "std::hash<Key> does not provide a call operator");
382 static_assert(
383 std::is_default_constructible<std::hash<Key>>::value,
384 "std::hash<Key> must be default constructible when it is enabled");
385 static_assert(
386 std::is_copy_constructible<std::hash<Key>>::value,
387 "std::hash<Key> must be copy constructible when it is enabled");
388 static_assert(phmap::is_copy_assignable<std::hash<Key>>::value,
389 "std::hash<Key> must be copy assignable when it is enabled");
390 // is_destructible is unchecked as it's implied by each of the
391 // is_constructible checks.
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");
396 return nullptr;
397 }
398
399 template <class... Ts>
400 friend void AssertHashEnabled();
401};
402
403template <class... Ts>
405()
406{
407 using Helper = AssertHashEnabledHelper;
408 Helper::Sink(Helper::DoIt<Ts>()...);
409}
410
411} // namespace type_traits_internal
412
413} // namespace phmap
414
415
416// -----------------------------------------------------------------------------
417// hash_policy_traits
418// -----------------------------------------------------------------------------
419namespace phmap {
420namespace priv {
421
422// Defines how slots are initialized/destroyed/moved.
423template <class Policy, class = void>
425{
426private:
427 struct ReturnKey
428 {
429 // We return `Key` here.
430 // When Key=T&, we forward the lvalue reference.
431 // When Key=T, we return by value to avoid a dangling reference.
432 // eg, for string_hash_map.
433 template <class Key, class... Args>
434 Key operator()(Key&& k, const Args&...) const {
435 return std::forward<Key>(k);
436 }
437 };
438
439 template <class P = Policy, class = void>
440 struct ConstantIteratorsImpl : std::false_type {};
441
442 template <class P>
443 struct ConstantIteratorsImpl<P, phmap::void_t<typename P::constant_iterators>>
444 : P::constant_iterators {};
445
446public:
447 // The actual object stored in the hash table.
448 using slot_type = typename Policy::slot_type;
449
450 // The type of the keys stored in the hashtable.
451 using key_type = typename Policy::key_type;
452
453 // The argument type for insertions into the hashtable. This is different
454 // from value_type for increased performance. See initializer_list constructor
455 // and insert() member functions for more details.
456 using init_type = typename Policy::init_type;
457
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;
461
462 // Policies can set this variable to tell raw_hash_set that all iterators
463 // should be constant, even `iterator`. This is useful for set-like
464 // containers.
465 // Defaults to false if not provided by the policy.
467
468 // PRECONDITION: `slot` is UNINITIALIZED
469 // POSTCONDITION: `slot` is INITIALIZED
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)...);
473 }
474
475 // PRECONDITION: `slot` is INITIALIZED
476 // POSTCONDITION: `slot` is UNINITIALIZED
477 template <class Alloc>
478 static void destroy(Alloc* alloc, slot_type* slot) {
479 Policy::destroy(alloc, slot);
480 }
481
482 // Transfers the `old_slot` to `new_slot`. Any memory allocated by the
483 // allocator inside `old_slot` to `new_slot` can be transferred.
484 //
485 // OPTIONAL: defaults to:
486 //
487 // clone(new_slot, std::move(*old_slot));
488 // destroy(old_slot);
489 //
490 // PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED
491 // POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is
492 // UNINITIALIZED
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);
496 }
497
498 // PRECONDITION: `slot` is INITIALIZED
499 // POSTCONDITION: `slot` is INITIALIZED
500 template <class P = Policy>
501 static auto element(slot_type* slot) -> decltype(P::element(slot)) {
502 return P::element(slot);
503 }
504
505 // Returns the amount of memory owned by `slot`, exclusive of `sizeof(*slot)`.
506 //
507 // If `slot` is nullptr, returns the constant amount of memory owned by any
508 // full slot or -1 if slots own variable amounts of memory.
509 //
510 // PRECONDITION: `slot` is INITIALIZED or nullptr
511 template <class P = Policy>
512 static size_t space_used(const slot_type* slot) {
513 return P::space_used(slot);
514 }
515
516 // Provides generalized access to the key for elements, both for elements in
517 // the table and for elements that have not yet been inserted (or even
518 // constructed). We would like an API that allows us to say: `key(args...)`
519 // but we cannot do that for all cases, so we use this more general API that
520 // can be used for many things, including the following:
521 //
522 // - Given an element in a table, get its key.
523 // - Given an element initializer, get its key.
524 // - Given `emplace()` arguments, get the element key.
525 //
526 // Implementations of this must adhere to a very strict technical
527 // specification around aliasing and consuming arguments:
528 //
529 // Let `value_type` be the result type of `element()` without ref- and
530 // cv-qualifiers. The first argument is a functor, the rest are constructor
531 // arguments for `value_type`. Returns `std::forward<F>(f)(k, xs...)`, where
532 // `k` is the element key, and `xs...` are the new constructor arguments for
533 // `value_type`. It's allowed for `k` to alias `xs...`, and for both to alias
534 // `ts...`. The key won't be touched once `xs...` are used to construct an
535 // element; `ts...` won't be touched at all, which allows `apply()` to consume
536 // any rvalues among them.
537 //
538 // If `value_type` is constructible from `Ts&&...`, `Policy::apply()` must not
539 // trigger a hard compile error unless it originates from `f`. In other words,
540 // `Policy::apply()` must be SFINAE-friendly. If `value_type` is not
541 // constructible from `Ts&&...`, either SFINAE or a hard compile error is OK.
542 //
543 // If `Ts...` is `[cv] value_type[&]` or `[cv] init_type[&]`,
544 // `Policy::apply()` must work. A compile error is not allowed, SFINAE or not.
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)...);
549 }
550
551 // Returns the "key" portion of the slot.
552 // Used for node handle manipulation.
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));
557 }
558
559 // Returns the "value" (as opposed to the "key") portion of the element. Used
560 // by maps to implement `operator[]`, `at()` and `insert_or_assign()`.
561 template <class T, class P = Policy>
562 static auto value(T* elem) -> decltype(P::value(elem)) {
563 return P::value(elem);
564 }
565
566private:
567
568 // Use auto -> decltype as an enabler.
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);
574 }
575
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);
581 }
582};
583
584} // namespace priv
585} // namespace phmap
586
587// -----------------------------------------------------------------------------
588// file utility.h
589// -----------------------------------------------------------------------------
590
591// --------- identity.h
592namespace phmap {
593namespace internal {
594
595template <typename T>
596struct identity {
597 typedef T type;
598};
599
600template <typename T>
602
603} // namespace internal
604} // namespace phmap
605
606
607// --------- inline_variable.h
608
609#ifdef __cpp_inline_variables
610
611#if defined(__clang__)
612 #define PHMAP_INTERNAL_EXTERN_DECL(type, name) \
613 extern const ::phmap::internal::identity_t<type> name;
614#else // Otherwise, just define the macro to do nothing.
615 #define PHMAP_INTERNAL_EXTERN_DECL(type, name)
616#endif // defined(__clang__)
617
618// See above comment at top of file for details.
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
622
623#else
624
625// See above comment at top of file for details.
626//
627// Note:
628// identity_t is used here so that the const and name are in the
629// appropriate place for pointer types, reference types, function pointer
630// types, etc..
631#define PHMAP_INTERNAL_INLINE_CONSTEXPR(var_type, name, init) \
632 template <class /*PhmapInternalDummy*/ = void> \
633 struct PhmapInternalInlineVariableHolder##name { \
634 static constexpr ::phmap::internal::identity_t<var_type> kInstance = init; \
635 }; \
636 \
637 template <class PhmapInternalDummy> \
638 constexpr ::phmap::internal::identity_t<var_type> \
639 PhmapInternalInlineVariableHolder##name<PhmapInternalDummy>::kInstance; \
640 \
641 static constexpr const ::phmap::internal::identity_t<var_type>& \
642 name = /* NOLINT */ \
643 PhmapInternalInlineVariableHolder##name<>::kInstance; \
644 static_assert(sizeof(void (*)(decltype(name))) != 0, \
645 "Silence unused variable warnings.")
646
647#endif // __cpp_inline_variables
648
649// ----------- throw_delegate
650
651namespace phmap {
652namespace base_internal {
653
654namespace {
655template <typename T>
656#ifdef PHMAP_HAVE_EXCEPTIONS
657[[noreturn]] void Throw(const T& error) {
658 throw error;
659}
660#else
661[[noreturn]] void Throw(const T&) {
662 std::abort();
663}
664#endif
665} // namespace
666
667static inline void ThrowStdLogicError(const std::string& what_arg) {
668 Throw(std::logic_error(what_arg));
669}
670static inline void ThrowStdLogicError(const char* what_arg) {
671 Throw(std::logic_error(what_arg));
672}
673static inline void ThrowStdInvalidArgument(const std::string& what_arg) {
674 Throw(std::invalid_argument(what_arg));
675}
676static inline void ThrowStdInvalidArgument(const char* what_arg) {
677 Throw(std::invalid_argument(what_arg));
678}
679
680static inline void ThrowStdDomainError(const std::string& what_arg) {
681 Throw(std::domain_error(what_arg));
682}
683static inline void ThrowStdDomainError(const char* what_arg) {
684 Throw(std::domain_error(what_arg));
685}
686
687static inline void ThrowStdLengthError(const std::string& what_arg) {
688 Throw(std::length_error(what_arg));
689}
690static inline void ThrowStdLengthError(const char* what_arg) {
691 Throw(std::length_error(what_arg));
692}
693
694static inline void ThrowStdOutOfRange(const std::string& what_arg) {
695 Throw(std::out_of_range(what_arg));
696}
697static inline void ThrowStdOutOfRange(const char* what_arg) {
698 Throw(std::out_of_range(what_arg));
699}
700
701static inline void ThrowStdRuntimeError(const std::string& what_arg) {
702 Throw(std::runtime_error(what_arg));
703}
704static inline void ThrowStdRuntimeError(const char* what_arg) {
705 Throw(std::runtime_error(what_arg));
706}
707
708static inline void ThrowStdRangeError(const std::string& what_arg) {
709 Throw(std::range_error(what_arg));
710}
711static inline void ThrowStdRangeError(const char* what_arg) {
712 Throw(std::range_error(what_arg));
713}
714
715static inline void ThrowStdOverflowError(const std::string& what_arg) {
716 Throw(std::overflow_error(what_arg));
717}
718static inline void ThrowStdOverflowError(const char* what_arg) {
719 Throw(std::overflow_error(what_arg));
720}
721
722static inline void ThrowStdUnderflowError(const std::string& what_arg) {
723 Throw(std::underflow_error(what_arg));
724}
725static inline void ThrowStdUnderflowError(const char* what_arg) {
726 Throw(std::underflow_error(what_arg));
727}
728
729static inline void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
730
731static inline void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
732
733} // namespace base_internal
734} // namespace phmap
735
736// ----------- invoke.h
737
738namespace phmap {
739namespace base_internal {
740
741template <typename Derived>
743{
744 template <typename... Args>
745 struct Accept : Derived::template AcceptImpl<typename std::remove_cv<
746 typename std::remove_reference<Args>::type>::type...> {};
747};
748
749// (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
750// and t1 is an object of type T or a reference to an object of type T or a
751// reference to an object of a type derived from T.
752struct MemFunAndRef : StrippedAccept<MemFunAndRef>
753{
754 template <typename... Args>
755 struct AcceptImpl : std::false_type {};
756
757 template <typename R, typename C, typename... Params, typename Obj,
758 typename... Args>
759 struct AcceptImpl<R (C::*)(Params...), Obj, Args...>
760 : std::is_base_of<C, Obj> {};
761
762 template <typename R, typename C, typename... Params, typename Obj,
763 typename... Args>
764 struct AcceptImpl<R (C::*)(Params...) const, Obj, Args...>
765 : std::is_base_of<C, Obj> {};
766
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)...);
773 }
774};
775
776// ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
777// class T and t1 is not one of the types described in the previous item.
778struct MemFunAndPtr : StrippedAccept<MemFunAndPtr>
779{
780 template <typename... Args>
781 struct AcceptImpl : std::false_type {};
782
783 template <typename R, typename C, typename... Params, typename Ptr,
784 typename... Args>
785 struct AcceptImpl<R (C::*)(Params...), Ptr, Args...>
786 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
787
788 template <typename R, typename C, typename... Params, typename Ptr,
789 typename... Args>
790 struct AcceptImpl<R (C::*)(Params...) const, Ptr, Args...>
791 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
792
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)...);
799 }
800};
801
802// t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
803// an object of type T or a reference to an object of type T or a reference
804// to an object of a type derived from T.
805struct DataMemAndRef : StrippedAccept<DataMemAndRef>
806{
807 template <typename... Args>
808 struct AcceptImpl : std::false_type {};
809
810 template <typename R, typename C, typename Obj>
811 struct AcceptImpl<R C::*, Obj> : std::is_base_of<C, Obj> {};
812
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);
817 }
818};
819
820// (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
821// is not one of the types described in the previous item.
822struct DataMemAndPtr : StrippedAccept<DataMemAndPtr>
823{
824 template <typename... Args>
825 struct AcceptImpl : std::false_type {};
826
827 template <typename R, typename C, typename Ptr>
828 struct AcceptImpl<R C::*, Ptr>
829 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
830
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);
835 }
836};
837
838// f(t1, t2, ..., tN) in all other cases.
840{
841 // Callable doesn't have Accept because it's the last clause that gets picked
842 // when none of the previous clauses are applicable.
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)...);
847 }
848};
849
850// Resolves to the first matching clause.
851template <typename... Args>
852struct Invoker
853{
854 typedef typename std::conditional<
855 MemFunAndRef::Accept<Args...>::value, MemFunAndRef,
856 typename std::conditional<
857 MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr,
858 typename std::conditional<
859 DataMemAndRef::Accept<Args...>::value, DataMemAndRef,
860 typename std::conditional<DataMemAndPtr::Accept<Args...>::value,
863};
864
865// The result type of Invoke<F, Args...>.
866template <typename F, typename... Args>
868 std::declval<F>(), std::declval<Args>()...));
869
870// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
871// [func.require] of the C++ standard.
872template <typename F, typename... Args>
873InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
874 return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
875 std::forward<Args>(args)...);
876}
877} // namespace base_internal
878} // namespace phmap
879
880
881// ----------- utility.h
882
883namespace phmap {
884
885// integer_sequence
886//
887// Class template representing a compile-time integer sequence. An instantiation
888// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
889// type through its template arguments (which is a common need when
890// working with C++11 variadic templates). `phmap::integer_sequence` is designed
891// to be a drop-in replacement for C++14's `std::integer_sequence`.
892//
893// Example:
894//
895// template< class T, T... Ints >
896// void user_function(integer_sequence<T, Ints...>);
897//
898// int main()
899// {
900// // user_function's `T` will be deduced to `int` and `Ints...`
901// // will be deduced to `0, 1, 2, 3, 4`.
902// user_function(make_integer_sequence<int, 5>());
903// }
904template <typename T, T... Ints>
906{
907 using value_type = T;
908 static constexpr size_t size() noexcept { return sizeof...(Ints); }
909};
910
911// index_sequence
912//
913// A helper template for an `integer_sequence` of `size_t`,
914// `phmap::index_sequence` is designed to be a drop-in replacement for C++14's
915// `std::index_sequence`.
916template <size_t... Ints>
917using index_sequence = integer_sequence<size_t, Ints...>;
918
919namespace utility_internal {
920
921template <typename Seq, size_t SeqSize, size_t Rem>
922struct Extend;
923
924// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
925template <typename T, T... Ints, size_t SeqSize>
926struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> {
927 using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>;
928};
929
930template <typename T, T... Ints, size_t SeqSize>
931struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> {
932 using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>;
933};
934
935// Recursion helper for 'make_integer_sequence<T, N>'.
936// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
937template <typename T, size_t N>
938struct Gen {
939 using type =
940 typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type;
941};
942
943template <typename T>
944struct Gen<T, 0> {
946};
947
948} // namespace utility_internal
949
950// Compile-time sequences of integers
951
952// make_integer_sequence
953//
954// This template alias is equivalent to
955// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
956// replacement for C++14's `std::make_integer_sequence`.
957template <typename T, T N>
959
960// make_index_sequence
961//
962// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
963// and is designed to be a drop-in replacement for C++14's
964// `std::make_index_sequence`.
965template <size_t N>
967
968// index_sequence_for
969//
970// Converts a typename pack into an index sequence of the same length, and
971// is designed to be a drop-in replacement for C++14's
972// `std::index_sequence_for()`
973template <typename... Ts>
975
976// Tag types
977
978#ifdef PHMAP_HAVE_STD_OPTIONAL
979
980using std::in_place_t;
981using std::in_place;
982
983#else // PHMAP_HAVE_STD_OPTIONAL
984
985// in_place_t
986//
987// Tag type used to specify in-place construction, such as with
988// `phmap::optional`, designed to be a drop-in replacement for C++17's
989// `std::in_place_t`.
990struct in_place_t {};
991
993
994#endif // PHMAP_HAVE_STD_OPTIONAL
995
996#if defined(PHMAP_HAVE_STD_ANY) || defined(PHMAP_HAVE_STD_VARIANT)
997using std::in_place_type_t;
998#else
999
1000// in_place_type_t
1001//
1002// Tag type used for in-place construction when the type to construct needs to
1003// be specified, such as with `phmap::any`, designed to be a drop-in replacement
1004// for C++17's `std::in_place_type_t`.
1005template <typename T>
1007#endif // PHMAP_HAVE_STD_ANY || PHMAP_HAVE_STD_VARIANT
1008
1009#ifdef PHMAP_HAVE_STD_VARIANT
1010using std::in_place_index_t;
1011#else
1012
1013// in_place_index_t
1014//
1015// Tag type used for in-place construction when the type to construct needs to
1016// be specified, such as with `phmap::any`, designed to be a drop-in replacement
1017// for C++17's `std::in_place_index_t`.
1018template <size_t I>
1020#endif // PHMAP_HAVE_STD_VARIANT
1021
1022// Constexpr move and forward
1023
1024// move()
1025//
1026// A constexpr version of `std::move()`, designed to be a drop-in replacement
1027// for C++14's `std::move()`.
1028template <typename T>
1029constexpr phmap::remove_reference_t<T>&& move(T&& t) noexcept {
1030 return static_cast<phmap::remove_reference_t<T>&&>(t);
1031}
1032
1033// forward()
1034//
1035// A constexpr version of `std::forward()`, designed to be a drop-in replacement
1036// for C++14's `std::forward()`.
1037template <typename T>
1038constexpr T&& forward(
1039 phmap::remove_reference_t<T>& t) noexcept { // NOLINT(runtime/references)
1040 return static_cast<T&&>(t);
1041}
1042
1043namespace utility_internal {
1044// Helper method for expanding tuple into a called method.
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))...)) {
1051 phmap::forward<Functor>(functor),
1052 std::get<Indexes>(phmap::forward<Tuple>(t))...);
1053}
1054
1055} // namespace utility_internal
1056
1057// apply
1058//
1059// Invokes a Callable using elements of a tuple as its arguments.
1060// Each element of the tuple corresponds to an argument of the call (in order).
1061// Both the Callable argument and the tuple argument are perfect-forwarded.
1062// For member-function Callables, the first tuple element acts as the `this`
1063// pointer. `phmap::apply` is designed to be a drop-in replacement for C++17's
1064// `std::apply`. Unlike C++17's `std::apply`, this is not currently `constexpr`.
1065//
1066// Example:
1067//
1068// class Foo {
1069// public:
1070// void Bar(int);
1071// };
1072// void user_function1(int, std::string);
1073// void user_function2(std::unique_ptr<Foo>);
1074// auto user_lambda = [](int, int) {};
1075//
1076// int main()
1077// {
1078// std::tuple<int, std::string> tuple1(42, "bar");
1079// // Invokes the first user function on int, std::string.
1080// phmap::apply(&user_function1, tuple1);
1081//
1082// std::tuple<std::unique_ptr<Foo>> tuple2(phmap::make_unique<Foo>());
1083// // Invokes the user function that takes ownership of the unique
1084// // pointer.
1085// phmap::apply(&user_function2, std::move(tuple2));
1086//
1087// auto foo = phmap::make_unique<Foo>();
1088// std::tuple<Foo*, int> tuple3(foo.get(), 42);
1089// // Invokes the method Bar on foo with one argument, 42.
1090// phmap::apply(&Foo::Bar, tuple3);
1091//
1092// std::tuple<int, int> tuple4(8, 9);
1093// // Invokes a lambda.
1094// phmap::apply(user_lambda, tuple4);
1095// }
1096template <typename Functor, typename Tuple>
1097auto apply(Functor&& functor, Tuple&& t)
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>{})) {
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>{});
1106}
1107
1108#ifdef _MSC_VER
1109 #pragma warning(push)
1110 #pragma warning(disable : 4365) // '=': conversion from 'T' to 'T', signed/unsigned mismatch
1111#endif // _MSC_VER
1112
1113// exchange
1114//
1115// Replaces the value of `obj` with `new_value` and returns the old value of
1116// `obj`. `phmap::exchange` is designed to be a drop-in replacement for C++14's
1117// `std::exchange`.
1118//
1119// Example:
1120//
1121// Foo& operator=(Foo&& other) {
1122// ptr1_ = phmap::exchange(other.ptr1_, nullptr);
1123// int1_ = phmap::exchange(other.int1_, -1);
1124// return *this;
1125// }
1126template <typename T, typename U = T>
1127T exchange(T& obj, U&& new_value)
1128{
1129 T old_value = phmap::move(obj);
1130 obj = phmap::forward<U>(new_value);
1131 return old_value;
1132}
1133
1134#ifdef _MSC_VER
1135 #pragma warning(pop)
1136#endif // _MSC_VER
1137
1138
1139} // namespace phmap
1140
1141// -----------------------------------------------------------------------------
1142// memory.h
1143// -----------------------------------------------------------------------------
1144
1145namespace phmap {
1146
1147template <typename T>
1148std::unique_ptr<T> WrapUnique(T* ptr)
1149{
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);
1153}
1154
1155namespace memory_internal {
1156
1157// Traits to select proper overload and return type for `phmap::make_unique<>`.
1158template <typename T>
1160 using scalar = std::unique_ptr<T>;
1161};
1162template <typename T>
1163struct MakeUniqueResult<T[]> {
1164 using array = std::unique_ptr<T[]>;
1165};
1166template <typename T, size_t N>
1167struct MakeUniqueResult<T[N]> {
1168 using invalid = void;
1169};
1170
1171} // namespace memory_internal
1172
1173#if (__cplusplus > 201103L || defined(_MSC_VER)) && \
1174 !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8)
1175 using std::make_unique;
1176#else
1177
1178 template <typename T, typename... Args>
1180 Args&&... args) {
1181 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
1182 }
1183
1184 template <typename T>
1186 return std::unique_ptr<T>(new typename phmap::remove_extent_t<T>[n]());
1187 }
1188
1189 template <typename T, typename... Args>
1191 Args&&... /* args */) = delete;
1192#endif
1193
1194template <typename T>
1195auto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr))
1196{
1197 // ptr is a forwarding reference to support Ts with non-const operators.
1198 return (ptr != nullptr) ? std::addressof(*ptr) : nullptr;
1199}
1200
1201inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; }
1202
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>();
1206}
1207
1208template <typename T>
1209std::weak_ptr<T> WeakenPtr(const std::shared_ptr<T>& ptr) {
1210 return std::weak_ptr<T>(ptr);
1211}
1212
1213namespace memory_internal {
1214
1215// ExtractOr<E, O, D>::type evaluates to E<O> if possible. Otherwise, D.
1216template <template <typename> class Extract, typename Obj, typename Default,
1217 typename>
1219 using type = Default;
1220};
1221
1222template <template <typename> class Extract, typename Obj, typename Default>
1223struct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> {
1224 using type = Extract<Obj>;
1225};
1226
1227template <template <typename> class Extract, typename Obj, typename Default>
1229
1230// Extractors for the features of allocators.
1231template <typename T>
1232using GetPointer = typename T::pointer;
1233
1234template <typename T>
1235using GetConstPointer = typename T::const_pointer;
1236
1237template <typename T>
1238using GetVoidPointer = typename T::void_pointer;
1239
1240template <typename T>
1241using GetConstVoidPointer = typename T::const_void_pointer;
1242
1243template <typename T>
1244using GetDifferenceType = typename T::difference_type;
1245
1246template <typename T>
1247using GetSizeType = typename T::size_type;
1248
1249template <typename T>
1251 typename T::propagate_on_container_copy_assignment;
1252
1253template <typename T>
1255 typename T::propagate_on_container_move_assignment;
1256
1257template <typename T>
1258using GetPropagateOnContainerSwap = typename T::propagate_on_container_swap;
1259
1260template <typename T>
1261using GetIsAlwaysEqual = typename T::is_always_equal;
1262
1263template <typename T>
1265
1266template <template <typename...> class Class, typename T, typename... Args>
1267struct GetFirstArg<Class<T, Args...>> {
1268 using type = T;
1269};
1270
1271template <typename Ptr, typename = void>
1274};
1275
1276template <typename T>
1277struct ElementType<T, void_t<typename T::element_type>> {
1278 using type = typename T::element_type;
1279};
1280
1281template <typename T, typename U>
1283
1284template <template <typename...> class Class, typename T, typename... Args,
1285 typename U>
1286struct RebindFirstArg<Class<T, Args...>, U> {
1287 using type = Class<U, Args...>;
1288};
1289
1290template <typename T, typename U, typename = void>
1293};
1294
1295template <typename T, typename U>
1296struct RebindPtr<T, U, void_t<typename T::template rebind<U>>> {
1297 using type = typename T::template rebind<U>;
1298};
1299
1300template <typename T, typename U>
1301constexpr bool HasRebindAlloc(...) {
1302 return false;
1303}
1304
1305template <typename T, typename U>
1306constexpr bool HasRebindAlloc(typename std::allocator_traits<T>::template rebind_alloc<U>*) {
1307 return true;
1308}
1309
1310template <typename T, typename U, bool = HasRebindAlloc<T, U>(nullptr)>
1313};
1314
1315template <typename A, typename U>
1316struct RebindAlloc<A, U, true> {
1317 using type = typename std::allocator_traits<A>::template rebind_alloc<U>;
1318};
1319
1320
1321} // namespace memory_internal
1322
1323template <typename Ptr>
1325{
1326 using pointer = Ptr;
1327
1328 // element_type:
1329 // Ptr::element_type if present. Otherwise T if Ptr is a template
1330 // instantiation Template<T, Args...>
1332
1333 // difference_type:
1334 // Ptr::difference_type if present, otherwise std::ptrdiff_t
1337 std::ptrdiff_t>;
1338
1339 // rebind:
1340 // Ptr::rebind<U> if exists, otherwise Template<U, Args...> if Ptr is a
1341 // template instantiation Template<T, Args...>
1342 template <typename U>
1344
1345 // pointer_to:
1346 // Calls Ptr::pointer_to(r)
1347 static pointer pointer_to(element_type& r) { // NOLINT(runtime/references)
1348 return Ptr::pointer_to(r);
1349 }
1350};
1351
1352// Specialization for T*.
1353template <typename T>
1355{
1356 using pointer = T*;
1357 using element_type = T;
1358 using difference_type = std::ptrdiff_t;
1359
1360 template <typename U>
1361 using rebind = U*;
1362
1363 // pointer_to:
1364 // Calls std::addressof(r)
1366 element_type& r) noexcept { // NOLINT(runtime/references)
1367 return std::addressof(r);
1368 }
1369};
1370
1371// -----------------------------------------------------------------------------
1372// Class Template: allocator_traits
1373// -----------------------------------------------------------------------------
1374//
1375// A C++11 compatible implementation of C++17's std::allocator_traits.
1376//
1377template <typename Alloc>
1379{
1380 using allocator_type = Alloc;
1381
1382 // value_type:
1383 // Alloc::value_type
1384 using value_type = typename Alloc::value_type;
1385
1386 // pointer:
1387 // Alloc::pointer if present, otherwise value_type*
1389 Alloc, value_type*>;
1390
1391 // const_pointer:
1392 // Alloc::const_pointer if present, otherwise
1393 // phmap::pointer_traits<pointer>::rebind<const value_type>
1397 template rebind<const value_type>>;
1398
1399 // void_pointer:
1400 // Alloc::void_pointer if present, otherwise
1401 // phmap::pointer_traits<pointer>::rebind<void>
1404 typename phmap::pointer_traits<pointer>::template rebind<void>>;
1405
1406 // const_void_pointer:
1407 // Alloc::const_void_pointer if present, otherwise
1408 // phmap::pointer_traits<pointer>::rebind<const void>
1411 typename phmap::pointer_traits<pointer>::template rebind<const void>>;
1412
1413 // difference_type:
1414 // Alloc::difference_type if present, otherwise
1415 // phmap::pointer_traits<pointer>::difference_type
1419
1420 // size_type:
1421 // Alloc::size_type if present, otherwise
1422 // std::make_unsigned<difference_type>::type
1425 typename std::make_unsigned<difference_type>::type>;
1426
1427 // propagate_on_container_copy_assignment:
1428 // Alloc::propagate_on_container_copy_assignment if present, otherwise
1429 // std::false_type
1432 std::false_type>;
1433
1434 // propagate_on_container_move_assignment:
1435 // Alloc::propagate_on_container_move_assignment if present, otherwise
1436 // std::false_type
1439 std::false_type>;
1440
1441 // propagate_on_container_swap:
1442 // Alloc::propagate_on_container_swap if present, otherwise std::false_type
1445 Alloc, std::false_type>;
1446
1447 // is_always_equal:
1448 // Alloc::is_always_equal if present, otherwise std::is_empty<Alloc>::type
1451 typename std::is_empty<Alloc>::type>;
1452
1453 // rebind_alloc:
1454 // Alloc::rebind<T>::other if present, otherwise Alloc<T, Args> if this Alloc
1455 // is Alloc<U, Args>
1456 template <typename T>
1458
1459 // rebind_traits:
1460 // phmap::allocator_traits<rebind_alloc<T>>
1461 template <typename T>
1463
1464 // allocate(Alloc& a, size_type n):
1465 // Calls a.allocate(n)
1466 static pointer allocate(Alloc& a, // NOLINT(runtime/references)
1467 size_type n) {
1468 return a.allocate(n);
1469 }
1470
1471 // allocate(Alloc& a, size_type n, const_void_pointer hint):
1472 // Calls a.allocate(n, hint) if possible.
1473 // If not possible, calls a.allocate(n)
1474 static pointer allocate(Alloc& a, size_type n, // NOLINT(runtime/references)
1475 const_void_pointer hint) {
1476 return allocate_impl(0, a, n, hint);
1477 }
1478
1479 // deallocate(Alloc& a, pointer p, size_type n):
1480 // Calls a.deallocate(p, n)
1481 static void deallocate(Alloc& a, pointer p, // NOLINT(runtime/references)
1482 size_type n) {
1483 a.deallocate(p, n);
1484 }
1485
1486 // construct(Alloc& a, T* p, Args&&... args):
1487 // Calls a.construct(p, std::forward<Args>(args)...) if possible.
1488 // If not possible, calls
1489 // ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)
1490 template <typename T, typename... Args>
1491 static void construct(Alloc& a, T* p, // NOLINT(runtime/references)
1492 Args&&... args) {
1493 construct_impl(0, a, p, std::forward<Args>(args)...);
1494 }
1495
1496 // destroy(Alloc& a, T* p):
1497 // Calls a.destroy(p) if possible. If not possible, calls p->~T().
1498 template <typename T>
1499 static void destroy(Alloc& a, T* p) { // NOLINT(runtime/references)
1500 destroy_impl(0, a, p);
1501 }
1502
1503 // max_size(const Alloc& a):
1504 // Returns a.max_size() if possible. If not possible, returns
1505 // std::numeric_limits<size_type>::max() / sizeof(value_type)
1506 static size_type max_size(const Alloc& a) { return max_size_impl(0, a); }
1507
1508 // select_on_container_copy_construction(const Alloc& a):
1509 // Returns a.select_on_container_copy_construction() if possible.
1510 // If not possible, returns a.
1511 static Alloc select_on_container_copy_construction(const Alloc& a) {
1513 }
1514
1515private:
1516 template <typename A>
1517 static auto allocate_impl(int, A& a, // NOLINT(runtime/references)
1519 -> decltype(a.allocate(n, hint)) {
1520 return a.allocate(n, hint);
1521 }
1522 static pointer allocate_impl(char, Alloc& a, // NOLINT(runtime/references)
1524 return a.allocate(n);
1525 }
1526
1527 template <typename A, typename... Args>
1528 static auto construct_impl(int, A& a, // NOLINT(runtime/references)
1529 Args&&... args)
1530 -> decltype(std::allocator_traits<A>::construct(a, std::forward<Args>(args)...)) {
1531 std::allocator_traits<A>::construct(a, std::forward<Args>(args)...);
1532 }
1533
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)...);
1537 }
1538
1539 template <typename A, typename T>
1540 static auto destroy_impl(int, A& a, // NOLINT(runtime/references)
1541 T* p) -> decltype(std::allocator_traits<A>::destroy(a, p)) {
1542 std::allocator_traits<A>::destroy(a, p);
1543 }
1544 template <typename T>
1545 static void destroy_impl(char, Alloc&, T* p) {
1546 p->~T();
1547 }
1548
1549 template <typename A>
1550 static auto max_size_impl(int, const A& a) -> decltype(a.max_size()) {
1551 return a.max_size();
1552 }
1553 static size_type max_size_impl(char, const Alloc&) {
1554 return (std::numeric_limits<size_type>::max)() / sizeof(value_type);
1555 }
1556
1557 template <typename A>
1559 -> decltype(a.select_on_container_copy_construction()) {
1560 return a.select_on_container_copy_construction();
1561 }
1563 const Alloc& a) {
1564 return a;
1565 }
1566};
1567
1568namespace memory_internal {
1569
1570// This template alias transforms Alloc::is_nothrow into a metafunction with
1571// Alloc as a parameter so it can be used with ExtractOrT<>.
1572template <typename Alloc>
1573using GetIsNothrow = typename Alloc::is_nothrow;
1574
1575} // namespace memory_internal
1576
1577// PHMAP_ALLOCATOR_NOTHROW is a build time configuration macro for user to
1578// specify whether the default allocation function can throw or never throws.
1579// If the allocation function never throws, user should define it to a non-zero
1580// value (e.g. via `-DPHMAP_ALLOCATOR_NOTHROW`).
1581// If the allocation function can throw, user should leave it undefined or
1582// define it to zero.
1583//
1584// allocator_is_nothrow<Alloc> is a traits class that derives from
1585// Alloc::is_nothrow if present, otherwise std::false_type. It's specialized
1586// for Alloc = std::allocator<T> for any type T according to the state of
1587// PHMAP_ALLOCATOR_NOTHROW.
1588//
1589// default_allocator_is_nothrow is a class that derives from std::true_type
1590// when the default allocator (global operator new) never throws, and
1591// std::false_type when it can throw. It is a convenience shorthand for writing
1592// allocator_is_nothrow<std::allocator<T>> (T can be any type).
1593// NOTE: allocator_is_nothrow<std::allocator<T>> is guaranteed to derive from
1594// the same type for all T, because users should specialize neither
1595// allocator_is_nothrow nor std::allocator.
1596template <typename Alloc>
1598 : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc,
1599 std::false_type> {};
1600
1601#if defined(PHMAP_ALLOCATOR_NOTHROW) && PHMAP_ALLOCATOR_NOTHROW
1602 template <typename T>
1603 struct allocator_is_nothrow<std::allocator<T>> : std::true_type {};
1604 struct default_allocator_is_nothrow : std::true_type {};
1605#else
1606 struct default_allocator_is_nothrow : std::false_type {};
1607#endif
1608
1609namespace memory_internal {
1610template <typename Allocator, typename Iterator, typename... Args>
1611void ConstructRange(Allocator& alloc, Iterator first, Iterator last,
1612 const Args&... args)
1613{
1614 for (Iterator cur = first; cur != last; ++cur) {
1616 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
1617 args...);
1618 }
1620 while (cur != first) {
1621 --cur;
1622 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
1623 }
1625 }
1626 }
1627}
1628
1629template <typename Allocator, typename Iterator, typename InputIterator>
1630void CopyRange(Allocator& alloc, Iterator destination, InputIterator first,
1631 InputIterator last)
1632{
1633 for (Iterator cur = destination; first != last;
1634 static_cast<void>(++cur), static_cast<void>(++first)) {
1636 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
1637 *first);
1638 }
1640 while (cur != destination) {
1641 --cur;
1642 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
1643 }
1645 }
1646 }
1647}
1648} // namespace memory_internal
1649} // namespace phmap
1650
1651
1652// -----------------------------------------------------------------------------
1653// optional.h
1654// -----------------------------------------------------------------------------
1655#ifdef PHMAP_HAVE_STD_OPTIONAL
1656
1657#include <optional> // IWYU pragma: export
1658
1659namespace phmap {
1660using std::bad_optional_access;
1661using std::optional;
1662using std::make_optional;
1663using std::nullopt_t;
1664using std::nullopt;
1665} // namespace phmap
1666
1667#else
1668
1669#if defined(__clang__)
1670 #if __has_feature(cxx_inheriting_constructors)
1671 #define PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
1672 #endif
1673#elif (defined(__GNUC__) && \
1674 (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
1675 (__cpp_inheriting_constructors >= 200802) || \
1676 (defined(_MSC_VER) && _MSC_VER >= 1910)
1677
1678 #define PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
1679#endif
1680
1681namespace phmap {
1682
1683class bad_optional_access : public std::exception
1684{
1685public:
1688 const char* what() const noexcept override;
1689};
1690
1691template <typename T>
1692class optional;
1693
1694// --------------------------------
1696{
1697 struct init_t {};
1698 static init_t init;
1699
1700 explicit constexpr nullopt_t(init_t& /*unused*/) {}
1701};
1702
1704
1705namespace optional_internal {
1706
1707// throw delegator
1708[[noreturn]] void throw_bad_optional_access();
1709
1710
1712
1713// This class stores the data in optional<T>.
1714// It is specialized based on whether T is trivially destructible.
1715// This is the specialization for non trivially destructible type.
1716template <typename T, bool unused = std::is_trivially_destructible<T>::value>
1718{
1719 struct dummy_type {
1720 static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
1721 // Use an array to avoid GCC 6 placement-new warning.
1722 empty_struct data[sizeof(T) / sizeof(empty_struct)];
1723 };
1724
1725protected:
1726 // Whether there is data or not.
1728 // Data storage
1729 union {
1732 };
1733
1734 void destruct() noexcept {
1735 if (engaged_) {
1736 data_.~T();
1737 engaged_ = false;
1738 }
1739 }
1740
1741 // dummy_ must be initialized for constexpr constructor.
1742 constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
1743
1744 template <typename... Args>
1745 constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
1746 : engaged_(true), data_(phmap::forward<Args>(args)...) {}
1747
1749};
1750
1751// Specialization for trivially destructible type.
1752template <typename T>
1754{
1755 struct dummy_type {
1756 static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
1757 // Use array to avoid GCC 6 placement-new warning.
1758 empty_struct data[sizeof(T) / sizeof(empty_struct)];
1759 };
1760
1761protected:
1762 // Whether there is data or not.
1764 // Data storage
1765 union {
1766 dummy_type dummy_;
1768 };
1769 void destruct() noexcept { engaged_ = false; }
1770
1771 // dummy_ must be initialized for constexpr constructor.
1772 constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
1773
1774 template <typename... Args>
1775 constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
1776 : engaged_(true), data_(phmap::forward<Args>(args)...) {}
1777};
1778
1779template <typename T>
1781{
1782protected:
1784#if PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS
1785 using base::base;
1786#else
1788
1789 template <typename... Args>
1790 constexpr explicit optional_data_base(in_place_t t, Args&&... args)
1791 : base(t, phmap::forward<Args>(args)...) {}
1792#endif
1793
1794 template <typename... Args>
1795 void construct(Args&&... args) {
1796 // Use dummy_'s address to work around casting cv-qualified T* to void*.
1797 ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
1798 this->engaged_ = true;
1799 }
1800
1801 template <typename U>
1802 void assign(U&& u) {
1803 if (this->engaged_) {
1804 this->data_ = std::forward<U>(u);
1805 } else {
1806 construct(std::forward<U>(u));
1807 }
1808 }
1809};
1810
1811// TODO: Add another class using
1812// std::is_trivially_move_constructible trait when available to match
1813// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that
1814// have trivial move but nontrivial copy.
1815// Also, we should be checking is_trivially_copyable here, which is not
1816// supported now, so we use is_trivially_* traits instead.
1817template <typename T,
1819 phmap::is_trivially_copy_assignable<typename std::remove_cv<
1820 T>::type>::value&& std::is_trivially_destructible<T>::value>
1822
1823// Trivially copyable types
1824template <typename T>
1826{
1827protected:
1828#if PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS
1829 using optional_data_base<T>::optional_data_base;
1830#else
1831 optional_data() = default;
1832
1833 template <typename... Args>
1834 constexpr explicit optional_data(in_place_t t, Args&&... args)
1835 : optional_data_base<T>(t, phmap::forward<Args>(args)...) {}
1836#endif
1837};
1838
1839template <typename T>
1841{
1842protected:
1843#if PHMAP_OPTIONAL_USE_INHERITING_CONSTRUCTORS
1844 using optional_data_base<T>::optional_data_base;
1845#else
1846 template <typename... Args>
1847 constexpr explicit optional_data(in_place_t t, Args&&... args)
1848 : optional_data_base<T>(t, phmap::forward<Args>(args)...) {}
1849#endif
1850
1851 optional_data() = default;
1852
1854 if (rhs.engaged_) {
1855 this->construct(rhs.data_);
1856 }
1857 }
1858
1860 phmap::default_allocator_is_nothrow::value ||
1861 std::is_nothrow_move_constructible<T>::value)
1862 : optional_data_base<T>() {
1863 if (rhs.engaged_) {
1864 this->construct(std::move(rhs.data_));
1865 }
1866 }
1867
1869 if (rhs.engaged_) {
1870 this->assign(rhs.data_);
1871 } else {
1872 this->destruct();
1873 }
1874 return *this;
1875 }
1876
1878 std::is_nothrow_move_assignable<T>::value&&
1879 std::is_nothrow_move_constructible<T>::value) {
1880 if (rhs.engaged_) {
1881 this->assign(std::move(rhs.data_));
1882 } else {
1883 this->destruct();
1884 }
1885 return *this;
1886 }
1887};
1888
1889// Ordered by level of restriction, from low to high.
1890// Copyable implies movable.
1891enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
1892
1893// Base class for enabling/disabling copy/move constructor.
1894template <copy_traits>
1896
1897template <>
1907
1908template <>
1918
1919template <>
1929
1930// Base class for enabling/disabling copy/move assignment.
1931template <copy_traits>
1933
1934template <>
1944
1945template <>
1955
1956template <>
1966
1967template <typename T>
1969{
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;
1974}
1975
1976template <typename T>
1978{
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;
1986}
1987
1988// Whether T is constructible or convertible from optional<U>.
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> {};
2000
2001// Whether T is constructible or convertible or assignable from optional<U>.
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> {};
2010
2011// Helper function used by [optional.relops], [optional.comp_with_t],
2012// for checking whether an expression is convertible to bool.
2014
2015// Base class for std::hash<phmap::optional<T>>:
2016// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
2017// compute the hash; Otherwise, it is disabled.
2018// Reference N4659 23.14.15 [unord.hash].
2019template <typename T, typename = size_t>
2028
2029template <typename T>
2030struct optional_hash_base<T, decltype(std::hash<phmap::remove_const_t<T> >()(
2031 std::declval<phmap::remove_const_t<T> >()))>
2032{
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>>();
2037 if (opt) {
2038 return std::hash<phmap::remove_const_t<T> >()(*opt);
2039 } else {
2040 return static_cast<size_t>(0x297814aaad196e6dULL);
2041 }
2042 }
2043};
2044
2045} // namespace optional_internal
2046
2047
2048// -----------------------------------------------------------------------------
2049// phmap::optional class definition
2050// -----------------------------------------------------------------------------
2051
2052template <typename T>
2055 optional_internal::get_ctor_copy_traits<T>()>,
2057 optional_internal::get_assign_copy_traits<T>()>
2058{
2060
2061public:
2062 typedef T value_type;
2063
2064 // Constructors
2065
2066 // Constructs an `optional` holding an empty value, NOT a default constructed
2067 // `T`.
2068 constexpr optional() noexcept {}
2069
2070 // Constructs an `optional` initialized with `nullopt` to hold an empty value.
2071 constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit)
2072
2073 // Copy constructor, standard semantics
2074 optional(const optional& src) = default;
2075
2076 // Move constructor, standard semantics
2077 optional(optional&& src) = default;
2078
2079 // Constructs a non-empty `optional` direct-initialized value of type `T` from
2080 // the arguments `std::forward<Args>(args)...` within the `optional`.
2081 // (The `in_place_t` is a tag used to indicate that the contained object
2082 // should be constructed in-place.)
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)...) {}
2089
2090 // Constructs a non-empty `optional` direct-initialized value of type `T` from
2091 // the arguments of an initializer_list and `std::forward<Args>(args)...`.
2092 // (The `in_place_t` is a tag used to indicate that the contained object
2093 // should be constructed in-place.)
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,
2098 Args&&... args)
2099 : data_base(in_place_t(), il, phmap::forward<Args>(args)...) {
2100 }
2101
2102 // Value constructor (implicit)
2103 template <
2104 typename U = T,
2105 typename std::enable_if<
2107 in_place_t, typename std::decay<U>::type> >,
2108 phmap::negation<std::is_same<
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)) {}
2114
2115 // Value constructor (explicit)
2116 template <
2117 typename U = T,
2118 typename std::enable_if<
2120 in_place_t, typename std::decay<U>::type>>,
2121 phmap::negation<std::is_same<
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)) {}
2128
2129 // Converting copy constructor (implicit)
2130 template <typename U,
2131 typename std::enable_if<
2134 std::is_constructible<T, const U&>,
2136 optional_internal::
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) {
2141 if (rhs) {
2142 this->construct(*rhs);
2143 }
2144 }
2145
2146 // Converting copy constructor (explicit)
2147 template <typename U,
2148 typename std::enable_if<
2151 std::is_constructible<T, const U&>,
2153 optional_internal::
2154 is_constructible_convertible_from_optional<T, U>>,
2156 bool>::type = false>
2157 explicit optional(const optional<U>& rhs) {
2158 if (rhs) {
2159 this->construct(*rhs);
2160 }
2161 }
2162
2163 // Converting move constructor (implicit)
2164 template <typename U,
2165 typename std::enable_if<
2168 std::is_constructible<T, U&&>,
2170 optional_internal::
2171 is_constructible_convertible_from_optional<T, U> >,
2172 std::is_convertible<U&&, T> >::value,
2173 bool>::type = false>
2175 if (rhs) {
2176 this->construct(std::move(*rhs));
2177 }
2178 }
2179
2180 // Converting move constructor (explicit)
2181 template <
2182 typename U,
2183 typename std::enable_if<
2185 phmap::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
2188 T, U>>,
2190 bool>::type = false>
2191 explicit optional(optional<U>&& rhs) {
2192 if (rhs) {
2193 this->construct(std::move(*rhs));
2194 }
2195 }
2196
2197 // Destructor. Trivial if `T` is trivially destructible.
2198 ~optional() = default;
2199
2200 // Assignment Operators
2201
2202 // Assignment from `nullopt`
2203 //
2204 // Example:
2205 //
2206 // struct S { int value; };
2207 // optional<S> opt = phmap::nullopt; // Could also use opt = { };
2209 this->destruct();
2210 return *this;
2211 }
2212
2213 // Copy assignment operator, standard semantics
2214 optional& operator=(const optional& src) = default;
2215
2216 // Move assignment operator, standard semantics
2217 optional& operator=(optional&& src) = default;
2218
2219 // Value assignment operators
2220 template <
2221 typename U = T,
2222 typename = typename std::enable_if<phmap::conjunction<
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>
2230 this->assign(std::forward<U>(v));
2231 return *this;
2232 }
2233
2234 template <
2235 typename U,
2236 typename = typename std::enable_if<phmap::conjunction<
2238 std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>,
2240 optional_internal::
2241 is_constructible_convertible_assignable_from_optional<
2242 T, U>>>::value>::type>
2244 if (rhs) {
2245 this->assign(*rhs);
2246 } else {
2247 this->destruct();
2248 }
2249 return *this;
2250 }
2251
2252 template <typename U,
2253 typename = typename std::enable_if<phmap::conjunction<
2254 phmap::negation<std::is_same<T, U>>, std::is_constructible<T, U>,
2255 std::is_assignable<T&, U>,
2257 optional_internal::
2258 is_constructible_convertible_assignable_from_optional<
2259 T, U>>>::value>::type>
2261 if (rhs) {
2262 this->assign(std::move(*rhs));
2263 } else {
2264 this->destruct();
2265 }
2266 return *this;
2267 }
2268
2269 // Modifiers
2270
2271 // optional::reset()
2272 //
2273 // Destroys the inner `T` value of an `phmap::optional` if one is present.
2274 PHMAP_ATTRIBUTE_REINITIALIZES void reset() noexcept { this->destruct(); }
2275
2276 // optional::emplace()
2277 //
2278 // (Re)constructs the underlying `T` in-place with the given forwarded
2279 // arguments.
2280 //
2281 // Example:
2282 //
2283 // optional<Foo> opt;
2284 // opt.emplace(arg1,arg2,arg3); // Constructs Foo(arg1,arg2,arg3)
2285 //
2286 // If the optional is non-empty, and the `args` refer to subobjects of the
2287 // current object, then behaviour is undefined, because the current object
2288 // will be destructed before the new object is constructed with `args`.
2289 template <typename... Args,
2290 typename = typename std::enable_if<
2291 std::is_constructible<T, Args&&...>::value>::type>
2292 T& emplace(Args&&... args) {
2293 this->destruct();
2294 this->construct(std::forward<Args>(args)...);
2295 return reference();
2296 }
2297
2298 // Emplace reconstruction overload for an initializer list and the given
2299 // forwarded arguments.
2300 //
2301 // Example:
2302 //
2303 // struct Foo {
2304 // Foo(std::initializer_list<int>);
2305 // };
2306 //
2307 // optional<Foo> opt;
2308 // opt.emplace({1,2,3}); // Constructs Foo({1,2,3})
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) {
2313 this->destruct();
2314 this->construct(il, std::forward<Args>(args)...);
2315 return reference();
2316 }
2317
2318 // Swaps
2319
2320 // Swap, standard semantics
2321 void swap(optional& rhs) noexcept(
2322 std::is_nothrow_move_constructible<T>::value&&
2323 std::is_trivial<T>::value) {
2324 if (*this) {
2325 if (rhs) {
2326 using std::swap;
2327 swap(**this, *rhs);
2328 } else {
2329 rhs.construct(std::move(**this));
2330 this->destruct();
2331 }
2332 } else {
2333 if (rhs) {
2334 this->construct(std::move(*rhs));
2335 rhs.destruct();
2336 } else {
2337 // No effect (swap(disengaged, disengaged)).
2338 }
2339 }
2340 }
2341
2342 // Observers
2343
2344 // optional::operator->()
2345 //
2346 // Accesses the underlying `T` value's member `m` of an `optional`. If the
2347 // `optional` is empty, behavior is undefined.
2348 //
2349 // If you need myOpt->foo in constexpr, use (*myOpt).foo instead.
2350 const T* operator->() const {
2351 assert(this->engaged_);
2352 return std::addressof(this->data_);
2353 }
2355 assert(this->engaged_);
2356 return std::addressof(this->data_);
2357 }
2358
2359 // optional::operator*()
2360 //
2361 // Accesses the underlying `T` value of an `optional`. If the `optional` is
2362 // empty, behavior is undefined.
2363 constexpr const T& operator*() const & { return reference(); }
2364 T& operator*() & {
2365 assert(this->engaged_);
2366 return reference();
2367 }
2368 constexpr const T&& operator*() const && {
2369 return phmap::move(reference());
2370 }
2371 T&& operator*() && {
2372 assert(this->engaged_);
2373 return std::move(reference());
2374 }
2375
2376 // optional::operator bool()
2377 //
2378 // Returns false if and only if the `optional` is empty.
2379 //
2380 // if (opt) {
2381 // // do something with opt.value();
2382 // } else {
2383 // // opt is empty.
2384 // }
2385 //
2386 constexpr explicit operator bool() const noexcept { return this->engaged_; }
2387
2388 // optional::has_value()
2389 //
2390 // Determines whether the `optional` contains a value. Returns `false` if and
2391 // only if `*this` is empty.
2392 constexpr bool has_value() const noexcept { return this->engaged_; }
2393
2394// Suppress bogus warning on MSVC: MSVC complains call to reference() after
2395// throw_bad_optional_access() is unreachable.
2396#ifdef _MSC_VER
2397 #pragma warning(push)
2398 #pragma warning(disable : 4702)
2399#endif // _MSC_VER
2400 // optional::value()
2401 //
2402 // Returns a reference to an `optional`s underlying value. The constness
2403 // and lvalue/rvalue-ness of the `optional` is preserved to the view of
2404 // the `T` sub-object. Throws `phmap::bad_optional_access` when the `optional`
2405 // is empty.
2406 constexpr const T& value() const & {
2407 return static_cast<bool>(*this)
2408 ? reference()
2409 : (optional_internal::throw_bad_optional_access(), reference());
2410 }
2411 T& value() & {
2412 return static_cast<bool>(*this)
2413 ? reference()
2414 : (optional_internal::throw_bad_optional_access(), reference());
2415 }
2416 T&& value() && { // NOLINT(build/c++11)
2417 return std::move(
2418 static_cast<bool>(*this)
2419 ? reference()
2420 : (optional_internal::throw_bad_optional_access(), reference()));
2421 }
2422 constexpr const T&& value() const && { // NOLINT(build/c++11)
2423 return phmap::move(
2424 static_cast<bool>(*this)
2425 ? reference()
2426 : (optional_internal::throw_bad_optional_access(), reference()));
2427 }
2428#ifdef _MSC_VER
2429 #pragma warning(pop)
2430#endif // _MSC_VER
2431
2432 // optional::value_or()
2433 //
2434 // Returns either the value of `T` or a passed default `v` if the `optional`
2435 // is empty.
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)
2443 ? **this
2444 : static_cast<T>(phmap::forward<U>(v));
2445 }
2446 template <typename U>
2447 T value_or(U&& v) && { // NOLINT(build/c++11)
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));
2454 }
2455
2456private:
2457 // Private accessors for internal storage viewed as reference to T.
2458 constexpr const T& reference() const { return this->data_; }
2459 T& reference() { return this->data_; }
2460
2461 // T constraint checks. You can't have an optional of nullopt_t, in_place_t
2462 // or a reference.
2463 static_assert(
2464 !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value,
2465 "optional<nullopt_t> is not allowed.");
2466 static_assert(
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.");
2471};
2472
2473// Non-member functions
2474
2475// swap()
2476//
2477// Performs a swap between two `phmap::optional` objects, using standard
2478// semantics.
2479//
2480// NOTE: we assume `is_swappable()` is always `true`. A compile error will
2481// result if this is not the case.
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))) {
2486 a.swap(b);
2487}
2488
2489// make_optional()
2490//
2491// Creates a non-empty `optional<T>` where the type of `T` is deduced. An
2492// `phmap::optional` can also be explicitly instantiated with
2493// `make_optional<T>(v)`.
2494//
2495// Note: `make_optional()` constructions may be declared `constexpr` for
2496// trivially copyable types `T`. Non-trivial types require copy elision
2497// support in C++17 for `make_optional` to support `constexpr` on such
2498// non-trivial types.
2499//
2500// Example:
2501//
2502// constexpr phmap::optional<int> opt = phmap::make_optional(1);
2503// static_assert(opt.value() == 1, "");
2504template <typename T>
2506 return optional<typename std::decay<T>::type>(phmap::forward<T>(v));
2507}
2508
2509template <typename T, typename... Args>
2510constexpr optional<T> make_optional(Args&&... args) {
2511 return optional<T>(in_place_t(), phmap::forward<Args>(args)...);
2512}
2513
2514template <typename T, typename U, typename... Args>
2515constexpr optional<T> make_optional(std::initializer_list<U> il,
2516 Args&&... args) {
2517 return optional<T>(in_place_t(), il,
2518 phmap::forward<Args>(args)...);
2519}
2520
2521// Relational operators [optional.relops]
2522
2523// Empty optionals are considered equal to each other and less than non-empty
2524// optionals. Supports relations between optional<T> and optional<U>, between
2525// optional<T> and U, and between optional<T> and nullopt.
2526//
2527// Note: We're careful to support T having non-bool relationals.
2528
2529// Requires: The expression, e.g. "*x == *y" shall be well-formed and its result
2530// shall be convertible to bool.
2531// The C++17 (N4606) "Returns:" statements are translated into
2532// code in an obvious way here, and the original text retained as function docs.
2533// Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true;
2534// otherwise *x == *y.
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)
2539 ? false
2540 : static_cast<bool>(x) == false ? true
2541 : static_cast<bool>(*x == *y);
2542}
2543
2544// Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false;
2545// otherwise *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)
2550 ? true
2551 : static_cast<bool>(x) == false ? false
2552 : static_cast<bool>(*x != *y);
2553}
2554// Returns: If !y, false; otherwise, if !x, true; otherwise *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);
2559}
2560// Returns: If !x, false; otherwise, if !y, true; otherwise *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);
2565}
2566// Returns: If !x, true; otherwise, if !y, false; otherwise *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);
2571}
2572// Returns: If !y, true; otherwise, if !x, false; otherwise *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);
2577}
2578
2579// Comparison with nullopt [optional.nullops]
2580// The C++17 (N4606) "Returns:" statements are used directly here.
2581template <typename T>
2582constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
2583 return !x;
2584}
2585template <typename T>
2586constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
2587 return !x;
2588}
2589template <typename T>
2590constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
2591 return static_cast<bool>(x);
2592}
2593template <typename T>
2594constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
2595 return static_cast<bool>(x);
2596}
2597template <typename T>
2598constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
2599 return false;
2600}
2601template <typename T>
2602constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
2603 return static_cast<bool>(x);
2604}
2605template <typename T>
2606constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
2607 return !x;
2608}
2609template <typename T>
2610constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
2611 return true;
2612}
2613template <typename T>
2614constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
2615 return static_cast<bool>(x);
2616}
2617template <typename T>
2618constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
2619 return false;
2620}
2621template <typename T>
2622constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
2623 return true;
2624}
2625template <typename T>
2626constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
2627 return !x;
2628}
2629
2630// Comparison with T [optional.comp_with_t]
2631
2632// Requires: The expression, e.g. "*x == v" shall be well-formed and its result
2633// shall be convertible to bool.
2634// The C++17 (N4606) "Equivalent to:" statements are used directly here.
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;
2639}
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;
2644}
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;
2649}
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;
2654}
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;
2659}
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;
2664}
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;
2669}
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;
2674}
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;
2679}
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;
2684}
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;
2689}
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;
2694}
2695
2696} // namespace phmap
2697
2698namespace std {
2699
2700// std::hash specialization for phmap::optional.
2701template <typename T>
2702struct hash<phmap::optional<T> >
2704
2705} // namespace std
2706
2707#endif
2708
2709// -----------------------------------------------------------------------------
2710// common.h
2711// -----------------------------------------------------------------------------
2712namespace phmap {
2713namespace priv {
2714
2715template <class, class = void>
2716struct IsTransparent : std::false_type {};
2717template <class T>
2718struct IsTransparent<T, phmap::void_t<typename T::is_transparent>>
2719 : std::true_type {};
2720
2721template <bool is_transparent>
2722struct KeyArg
2723{
2724 // Transparent. Forward `K`.
2725 template <typename K, typename key_type>
2726 using type = K;
2727};
2728
2729template <>
2731{
2732 // Not transparent. Always use `key_type`.
2733 template <typename K, typename key_type>
2734 using type = key_type;
2735};
2736
2737#ifdef _MSC_VER
2738 #pragma warning(push)
2739 // warning C4820: '6' bytes padding added after data member
2740 #pragma warning(disable : 4820)
2741#endif
2742
2743// The node_handle concept from C++17.
2744// We specialize node_handle for sets and maps. node_handle_base holds the
2745// common API of both.
2746// -----------------------------------------------------------------------
2747template <typename PolicyTraits, typename Alloc>
2749{
2750protected:
2751 using slot_type = typename PolicyTraits::slot_type;
2752
2753public:
2754 using allocator_type = Alloc;
2755
2756 constexpr node_handle_base() {}
2757
2759 *this = std::move(other);
2760 }
2761
2763
2765 destroy();
2766 if (!other.empty()) {
2767 alloc_ = other.alloc_;
2768 PolicyTraits::transfer(alloc(), slot(), other.slot());
2769 other.reset();
2770 }
2771 return *this;
2772 }
2773
2774 bool empty() const noexcept { return !alloc_; }
2775 explicit operator bool() const noexcept { return !empty(); }
2777
2778protected:
2779 friend struct CommonAccess;
2780
2783 : alloc_(a) {
2784 PolicyTraits::transfer(alloc(), slot(), s);
2785 }
2786
2787 struct move_tag_t {};
2789 : alloc_(a) {
2790 PolicyTraits::construct(alloc(), slot(), s);
2791 }
2792
2794 PolicyTraits::transfer(alloc(), slot(), s);
2795 }
2796
2797 //node_handle_base(const node_handle_base&) = delete;
2798 //node_handle_base& operator=(const node_handle_base&) = delete;
2799
2800 void destroy() {
2801 if (!empty()) {
2802 PolicyTraits::destroy(alloc(), slot());
2803 reset();
2804 }
2805 }
2806
2807 void reset() {
2808 assert(alloc_.has_value());
2810 }
2811
2812 slot_type* slot() const {
2813 assert(!empty());
2814 return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
2815 }
2816
2817 allocator_type* alloc() { return std::addressof(*alloc_); }
2818
2819private:
2822};
2823
2824#ifdef _MSC_VER
2825 #pragma warning(pop)
2826#endif
2827
2828// For sets.
2829// ---------
2830template <typename Policy, typename PolicyTraits, typename Alloc,
2831 typename = void>
2832class node_handle : public node_handle_base<PolicyTraits, Alloc>
2833{
2835
2836public:
2837 using value_type = typename PolicyTraits::value_type;
2838
2839 constexpr node_handle() {}
2840
2841 value_type& value() const { return PolicyTraits::element(this->slot()); }
2842
2843 value_type& key() const { return PolicyTraits::element(this->slot()); }
2844
2845private:
2846 friend struct CommonAccess;
2847
2848 using Base::Base;
2849};
2850
2851// For maps.
2852// ---------
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>
2857{
2859 using slot_type = typename PolicyTraits::slot_type;
2860
2861public:
2862 using key_type = typename Policy::key_type;
2863 using mapped_type = typename Policy::mapped_type;
2864
2865 constexpr node_handle() {}
2866
2867 auto key() const -> decltype(PolicyTraits::key(this->slot())) {
2868 return PolicyTraits::key(this->slot());
2869 }
2870
2872 return PolicyTraits::value(&PolicyTraits::element(this->slot()));
2873 }
2874
2875private:
2876 friend struct CommonAccess;
2877
2878 using Base::Base;
2879};
2880
2881// Provide access to non-public node-handle functions.
2883{
2884 template <typename Node>
2885 static auto GetSlot(const Node& node) -> decltype(node.slot()) {
2886 return node.slot();
2887 }
2888
2889 template <typename Node>
2890 static void Destroy(Node* node) {
2891 node->destroy();
2892 }
2893
2894 template <typename Node>
2895 static void Reset(Node* node) {
2896 node->reset();
2897 }
2898
2899 template <typename T, typename... Args>
2900 static T Make(Args&&... args) {
2901 return T(std::forward<Args>(args)...);
2902 }
2903
2904 template <typename T, typename... Args>
2905 static T Transfer(Args&&... args) {
2906 return T(typename T::transfer_tag_t{}, std::forward<Args>(args)...);
2907 }
2908
2909 template <typename T, typename... Args>
2910 static T Move(Args&&... args) {
2911 return T(typename T::move_tag_t{}, std::forward<Args>(args)...);
2912 }
2913};
2914
2915// Implement the insert_return_type<> concept of C++17.
2916template <class Iterator, class NodeType>
2918{
2919 Iterator position;
2921 NodeType node;
2922};
2923
2924} // namespace priv
2925} // namespace phmap
2926
2927
2928#ifdef ADDRESS_SANITIZER
2929 #include <sanitizer/asan_interface.h>
2930#endif
2931
2932// ---------------------------------------------------------------------------
2933// span.h
2934// ---------------------------------------------------------------------------
2935
2936namespace phmap {
2937
2938template <typename T>
2939class Span;
2940
2941namespace span_internal {
2942// A constexpr min function
2943constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
2944
2945// Wrappers for access to container data pointers.
2946template <typename C>
2947constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
2948 -> decltype(c.data()) {
2949 return c.data();
2950}
2951
2952// Before C++17, std::string::data returns a const char* in all cases.
2953inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references)
2954 int) noexcept {
2955 return &s[0];
2956}
2957
2958template <typename C>
2959constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references)
2960 -> decltype(GetDataImpl(c, 0)) {
2961 return GetDataImpl(c, 0);
2962}
2963
2964// Detection idioms for size() and data().
2965template <typename C>
2966using HasSize =
2967 std::is_integral<phmap::decay_t<decltype(std::declval<C&>().size())>>;
2968
2969// We want to enable conversion from vector<T*> to Span<const T* const> but
2970// disable conversion from vector<Derived> to Span<Base>. Here we use
2971// the fact that U** is convertible to Q* const* if and only if Q is the same
2972// type or a more cv-qualified version of U. We also decay the result type of
2973// data() to avoid problems with classes which have a member function data()
2974// which returns a reference.
2975template <typename T, typename C>
2976using HasData =
2977 std::is_convertible<phmap::decay_t<decltype(GetData(std::declval<C&>()))>*,
2978 T* const*>;
2979
2980// Extracts value type from a Container
2981template <typename C>
2985
2986template <typename T, size_t N>
2987struct ElementType<T (&)[N]> {
2988 using type = T;
2989};
2990
2991template <typename C>
2993
2994template <typename T>
2996 typename std::enable_if<!std::is_const<T>::value, int>::type;
2997
2998template <typename T>
3000 static_assert(std::is_const<T>::value, "");
3001 return std::equal(a.begin(), a.end(), b.begin(), b.end());
3002}
3003
3004template <typename T>
3006 static_assert(std::is_const<T>::value, "");
3007 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
3008}
3009
3010// The `IsConvertible` classes here are needed because of the
3011// `std::is_convertible` bug in libcxx when compiled with GCC. This build
3012// configuration is used by Android NDK toolchain. Reference link:
3013// https://bugs.llvm.org/show_bug.cgi?id=27538.
3014template <typename From, typename To>
3016 static std::true_type testval(To);
3017 static std::false_type testval(...);
3018
3019 using type = decltype(testval(std::declval<From>()));
3020};
3021
3022template <typename From, typename To>
3023struct IsConvertible : IsConvertibleHelper<From, To>::type {};
3024
3025// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the
3026// older version of libcxx is not supported.
3027template <typename From, typename To>
3029 typename std::enable_if<IsConvertible<From, Span<const To>>::value>::type;
3030} // namespace span_internal
3031
3032//------------------------------------------------------------------------------
3033// Span
3034//------------------------------------------------------------------------------
3035//
3036// A `Span` is an "array view" type for holding a view of a contiguous data
3037// array; the `Span` object does not and cannot own such data itself. A span
3038// provides an easy way to provide overloads for anything operating on
3039// contiguous sequences without needing to manage pointers and array lengths
3040// manually.
3041
3042// A span is conceptually a pointer (ptr) and a length (size) into an already
3043// existing array of contiguous memory; the array it represents references the
3044// elements "ptr[0] .. ptr[size-1]". Passing a properly-constructed `Span`
3045// instead of raw pointers avoids many issues related to index out of bounds
3046// errors.
3047//
3048// Spans may also be constructed from containers holding contiguous sequences.
3049// Such containers must supply `data()` and `size() const` methods (e.g
3050// `std::vector<T>`, `phmap::InlinedVector<T, N>`). All implicit conversions to
3051// `phmap::Span` from such containers will create spans of type `const T`;
3052// spans which can mutate their values (of type `T`) must use explicit
3053// constructors.
3054//
3055// A `Span<T>` is somewhat analogous to an `phmap::string_view`, but for an array
3056// of elements of type `T`. A user of `Span` must ensure that the data being
3057// pointed to outlives the `Span` itself.
3058//
3059// You can construct a `Span<T>` in several ways:
3060//
3061// * Explicitly from a reference to a container type
3062// * Explicitly from a pointer and size
3063// * Implicitly from a container type (but only for spans of type `const T`)
3064// * Using the `MakeSpan()` or `MakeConstSpan()` factory functions.
3065//
3066// Examples:
3067//
3068// // Construct a Span explicitly from a container:
3069// std::vector<int> v = {1, 2, 3, 4, 5};
3070// auto span = phmap::Span<const int>(v);
3071//
3072// // Construct a Span explicitly from a C-style array:
3073// int a[5] = {1, 2, 3, 4, 5};
3074// auto span = phmap::Span<const int>(a);
3075//
3076// // Construct a Span implicitly from a container
3077// void MyRoutine(phmap::Span<const int> a) {
3078// ...
3079// }
3080// std::vector v = {1,2,3,4,5};
3081// MyRoutine(v) // convert to Span<const T>
3082//
3083// Note that `Span` objects, in addition to requiring that the memory they
3084// point to remains alive, must also ensure that such memory does not get
3085// reallocated. Therefore, to avoid undefined behavior, containers with
3086// associated span views should not invoke operations that may reallocate memory
3087// (such as resizing) or invalidate iterators into the container.
3088//
3089// One common use for a `Span` is when passing arguments to a routine that can
3090// accept a variety of array types (e.g. a `std::vector`, `phmap::InlinedVector`,
3091// a C-style array, etc.). Instead of creating overloads for each case, you
3092// can simply specify a `Span` as the argument to such a routine.
3093//
3094// Example:
3095//
3096// void MyRoutine(phmap::Span<const int> a) {
3097// ...
3098// }
3099//
3100// std::vector v = {1,2,3,4,5};
3101// MyRoutine(v);
3102//
3103// phmap::InlinedVector<int, 4> my_inline_vector;
3104// MyRoutine(my_inline_vector);
3105//
3106// // Explicit constructor from pointer,size
3107// int* my_array = new int[10];
3108// MyRoutine(phmap::Span<const int>(my_array, 10));
3109template <typename T>
3110class Span
3111{
3112private:
3113 // Used to determine whether a Span can be constructed from a container of
3114 // type C.
3115 template <typename C>
3117 typename std::enable_if<span_internal::HasData<T, C>::value &&
3119
3120 // Used to SFINAE-enable a function when the slice elements are const.
3121 template <typename U>
3123 typename std::enable_if<std::is_const<T>::value, U>::type;
3124
3125 // Used to SFINAE-enable a function when the slice elements are mutable.
3126 template <typename U>
3128 typename std::enable_if<!std::is_const<T>::value, U>::type;
3129
3130public:
3132 using pointer = T*;
3133 using const_pointer = const T*;
3134 using reference = T&;
3135 using const_reference = const T&;
3138 using reverse_iterator = std::reverse_iterator<iterator>;
3139 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
3140 using size_type = size_t;
3141 using difference_type = ptrdiff_t;
3142
3143 static const size_type npos = ~(size_type(0));
3144
3145 constexpr Span() noexcept : Span(nullptr, 0) {}
3146 constexpr Span(pointer array, size_type lgth) noexcept
3147 : ptr_(array), len_(lgth) {}
3148
3149 // Implicit conversion constructors
3150 template <size_t N>
3151 constexpr Span(T (&a)[N]) noexcept // NOLINT(runtime/explicit)
3152 : Span(a, N) {}
3153
3154 // Explicit reference constructor for a mutable `Span<T>` type. Can be
3155 // replaced with MakeSpan() to infer the type parameter.
3156 template <typename V, typename = EnableIfConvertibleFrom<V>,
3157 typename = EnableIfMutableView<V>>
3158 explicit Span(V& v) noexcept // NOLINT(runtime/references)
3159 : Span(span_internal::GetData(v), v.size()) {}
3160
3161 // Implicit reference constructor for a read-only `Span<const T>` type
3162 template <typename V, typename = EnableIfConvertibleFrom<V>,
3163 typename = EnableIfConstView<V>>
3164 constexpr Span(const V& v) noexcept // NOLINT(runtime/explicit)
3165 : Span(span_internal::GetData(v), v.size()) {}
3166
3167 // Implicit constructor from an initializer list, making it possible to pass a
3168 // brace-enclosed initializer list to a function expecting a `Span`. Such
3169 // spans constructed from an initializer list must be of type `Span<const T>`.
3170 //
3171 // void Process(phmap::Span<const int> x);
3172 // Process({1, 2, 3});
3173 //
3174 // Note that as always the array referenced by the span must outlive the span.
3175 // Since an initializer list constructor acts as if it is fed a temporary
3176 // array (cf. C++ standard [dcl.init.list]/5), it's safe to use this
3177 // constructor only when the `std::initializer_list` itself outlives the span.
3178 // In order to meet this requirement it's sufficient to ensure that neither
3179 // the span nor a copy of it is used outside of the expression in which it's
3180 // created:
3181 //
3182 // // Assume that this function uses the array directly, not retaining any
3183 // // copy of the span or pointer to any of its elements.
3184 // void Process(phmap::Span<const int> ints);
3185 //
3186 // // Okay: the std::initializer_list<int> will reference a temporary array
3187 // // that isn't destroyed until after the call to Process returns.
3188 // Process({ 17, 19 });
3189 //
3190 // // Not okay: the storage used by the std::initializer_list<int> is not
3191 // // allowed to be referenced after the first line.
3192 // phmap::Span<const int> ints = { 17, 19 };
3193 // Process(ints);
3194 //
3195 // // Not okay for the same reason as above: even when the elements of the
3196 // // initializer list expression are not temporaries the underlying array
3197 // // is, so the initializer list must still outlive the span.
3198 // const int foo = 17;
3199 // phmap::Span<const int> ints = { foo };
3200 // Process(ints);
3201 //
3202 template <typename LazyT = T,
3203 typename = EnableIfConstView<LazyT>>
3205 std::initializer_list<value_type> v) noexcept // NOLINT(runtime/explicit)
3206 : Span(v.begin(), v.size()) {}
3207
3208 // Accessors
3209
3210 // Span::data()
3211 //
3212 // Returns a pointer to the span's underlying array of data (which is held
3213 // outside the span).
3214 constexpr pointer data() const noexcept { return ptr_; }
3215
3216 // Span::size()
3217 //
3218 // Returns the size of this span.
3219 constexpr size_type size() const noexcept { return len_; }
3220
3221 // Span::length()
3222 //
3223 // Returns the length (size) of this span.
3224 constexpr size_type length() const noexcept { return size(); }
3225
3226 // Span::empty()
3227 //
3228 // Returns a boolean indicating whether or not this span is considered empty.
3229 constexpr bool empty() const noexcept { return size() == 0; }
3230
3231 // Span::operator[]
3232 //
3233 // Returns a reference to the i'th element of this span.
3234 constexpr reference operator[](size_type i) const noexcept {
3235 // MSVC 2015 accepts this as constexpr, but not ptr_[i]
3236 return *(data() + i);
3237 }
3238
3239 // Span::at()
3240 //
3241 // Returns a reference to the i'th element of this span.
3242 constexpr reference at(size_type i) const {
3243 return PHMAP_PREDICT_TRUE(i < size()) //
3244 ? *(data() + i)
3246 "Span::at failed bounds check"),
3247 *(data() + i));
3248 }
3249
3250 // Span::front()
3251 //
3252 // Returns a reference to the first element of this span.
3253 constexpr reference front() const noexcept {
3254 return PHMAP_ASSERT(size() > 0), *data();
3255 }
3256
3257 // Span::back()
3258 //
3259 // Returns a reference to the last element of this span.
3260 constexpr reference back() const noexcept {
3261 return PHMAP_ASSERT(size() > 0), *(data() + size() - 1);
3262 }
3263
3264 // Span::begin()
3265 //
3266 // Returns an iterator to the first element of this span.
3267 constexpr iterator begin() const noexcept { return data(); }
3268
3269 // Span::cbegin()
3270 //
3271 // Returns a const iterator to the first element of this span.
3272 constexpr const_iterator cbegin() const noexcept { return begin(); }
3273
3274 // Span::end()
3275 //
3276 // Returns an iterator to the last element of this span.
3277 constexpr iterator end() const noexcept { return data() + size(); }
3278
3279 // Span::cend()
3280 //
3281 // Returns a const iterator to the last element of this span.
3282 constexpr const_iterator cend() const noexcept { return end(); }
3283
3284 // Span::rbegin()
3285 //
3286 // Returns a reverse iterator starting at the last element of this span.
3287 constexpr reverse_iterator rbegin() const noexcept {
3288 return reverse_iterator(end());
3289 }
3290
3291 // Span::crbegin()
3292 //
3293 // Returns a reverse const iterator starting at the last element of this span.
3294 constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
3295
3296 // Span::rend()
3297 //
3298 // Returns a reverse iterator starting at the first element of this span.
3299 constexpr reverse_iterator rend() const noexcept {
3300 return reverse_iterator(begin());
3301 }
3302
3303 // Span::crend()
3304 //
3305 // Returns a reverse iterator starting at the first element of this span.
3306 constexpr const_reverse_iterator crend() const noexcept { return rend(); }
3307
3308 // Span mutations
3309
3310 // Span::remove_prefix()
3311 //
3312 // Removes the first `n` elements from the span.
3313 void remove_prefix(size_type n) noexcept {
3314 assert(size() >= n);
3315 ptr_ += n;
3316 len_ -= n;
3317 }
3318
3319 // Span::remove_suffix()
3320 //
3321 // Removes the last `n` elements from the span.
3322 void remove_suffix(size_type n) noexcept {
3323 assert(size() >= n);
3324 len_ -= n;
3325 }
3326
3327 // Span::subspan()
3328 //
3329 // Returns a `Span` starting at element `pos` and of length `len`. Both `pos`
3330 // and `len` are of type `size_type` and thus non-negative. Parameter `pos`
3331 // must be <= size(). Any `len` value that points past the end of the span
3332 // will be trimmed to at most size() - `pos`. A default `len` value of `npos`
3333 // ensures the returned subspan continues until the end of the span.
3334 //
3335 // Examples:
3336 //
3337 // std::vector<int> vec = {10, 11, 12, 13};
3338 // phmap::MakeSpan(vec).subspan(1, 2); // {11, 12}
3339 // phmap::MakeSpan(vec).subspan(2, 8); // {12, 13}
3340 // phmap::MakeSpan(vec).subspan(1); // {11, 12, 13}
3341 // phmap::MakeSpan(vec).subspan(4); // {}
3342 // phmap::MakeSpan(vec).subspan(5); // throws std::out_of_range
3343 constexpr Span subspan(size_type pos = 0, size_type len = npos) const {
3344 return (pos <= size())
3345 ? Span(data() + pos, span_internal::Min(size() - pos, len))
3346 : (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
3347 }
3348
3349 // Span::first()
3350 //
3351 // Returns a `Span` containing first `len` elements. Parameter `len` is of
3352 // type `size_type` and thus non-negative. `len` value must be <= size().
3353 //
3354 // Examples:
3355 //
3356 // std::vector<int> vec = {10, 11, 12, 13};
3357 // phmap::MakeSpan(vec).first(1); // {10}
3358 // phmap::MakeSpan(vec).first(3); // {10, 11, 12}
3359 // phmap::MakeSpan(vec).first(5); // throws std::out_of_range
3360 constexpr Span first(size_type len) const {
3361 return (len <= size())
3362 ? Span(data(), len)
3363 : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
3364 }
3365
3366 // Span::last()
3367 //
3368 // Returns a `Span` containing last `len` elements. Parameter `len` is of
3369 // type `size_type` and thus non-negative. `len` value must be <= size().
3370 //
3371 // Examples:
3372 //
3373 // std::vector<int> vec = {10, 11, 12, 13};
3374 // phmap::MakeSpan(vec).last(1); // {13}
3375 // phmap::MakeSpan(vec).last(3); // {11, 12, 13}
3376 // phmap::MakeSpan(vec).last(5); // throws std::out_of_range
3377 constexpr Span last(size_type len) const {
3378 return (len <= size())
3379 ? Span(size() - len + data(), len)
3380 : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
3381 }
3382
3383 // Support for phmap::Hash.
3384 template <typename H>
3385 friend H AbslHashValue(H h, Span v) {
3386 return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
3387 v.size());
3388 }
3389
3390private:
3393};
3394
3395template <typename T>
3396const typename Span<T>::size_type Span<T>::npos;
3397
3398// Span relationals
3399
3400// Equality is compared element-by-element, while ordering is lexicographical.
3401// We provide three overloads for each operator to cover any combination on the
3402// left or right hand side of mutable Span<T>, read-only Span<const T>, and
3403// convertible-to-read-only Span<T>.
3404// TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering
3405// template functions, 5 overloads per operator is needed as a workaround. We
3406// should update them to 3 overloads per operator using non-deduced context like
3407// string_view, i.e.
3408// - (Span<T>, Span<T>)
3409// - (Span<T>, non_deduced<Span<const T>>)
3410// - (non_deduced<Span<const T>>, Span<T>)
3411
3412// operator==
3413template <typename T>
3415 return span_internal::EqualImpl<const T>(a, b);
3416}
3417
3418template <typename T>
3419bool operator==(Span<const T> a, Span<T> b) {
3420 return span_internal::EqualImpl<const T>(a, b);
3421}
3422
3423template <typename T>
3424bool operator==(Span<T> a, Span<const T> b) {
3425 return span_internal::EqualImpl<const T>(a, b);
3426}
3427
3428template <typename T, typename U,
3429 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3430bool operator==(const U& a, Span<T> b) {
3431 return span_internal::EqualImpl<const T>(a, b);
3432}
3433
3434template <typename T, typename U,
3435 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3436bool operator==(Span<T> a, const U& b) {
3437 return span_internal::EqualImpl<const T>(a, b);
3438}
3439
3440// operator!=
3441template <typename T>
3443 return !(a == b);
3444}
3445
3446template <typename T>
3447bool operator!=(Span<const T> a, Span<T> b) {
3448 return !(a == b);
3449}
3450
3451template <typename T>
3452bool operator!=(Span<T> a, Span<const T> b) {
3453 return !(a == b);
3454}
3455
3456template <typename T, typename U,
3457 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3458bool operator!=(const U& a, Span<T> b) {
3459 return !(a == b);
3460}
3461
3462template <typename T, typename U,
3463 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3464bool operator!=(Span<T> a, const U& b) {
3465 return !(a == b);
3466}
3467
3468// operator<
3469template <typename T>
3471 return span_internal::LessThanImpl<const T>(a, b);
3472}
3473
3474template <typename T>
3475bool operator<(Span<const T> a, Span<T> b) {
3476 return span_internal::LessThanImpl<const T>(a, b);
3477}
3478
3479template <typename T>
3480bool operator<(Span<T> a, Span<const T> b) {
3481 return span_internal::LessThanImpl<const T>(a, b);
3482}
3483
3484template <typename T, typename U,
3485 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3486bool operator<(const U& a, Span<T> b) {
3487 return span_internal::LessThanImpl<const T>(a, b);
3488}
3489
3490template <typename T, typename U,
3491 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3492bool operator<(Span<T> a, const U& b) {
3493 return span_internal::LessThanImpl<const T>(a, b);
3494}
3495
3496// operator>
3497template <typename T>
3499 return b < a;
3500}
3501
3502template <typename T>
3503bool operator>(Span<const T> a, Span<T> b) {
3504 return b < a;
3505}
3506
3507template <typename T>
3508bool operator>(Span<T> a, Span<const T> b) {
3509 return b < a;
3510}
3511
3512template <typename T, typename U,
3513 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3514bool operator>(const U& a, Span<T> b) {
3515 return b < a;
3516}
3517
3518template <typename T, typename U,
3519 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3520bool operator>(Span<T> a, const U& b) {
3521 return b < a;
3522}
3523
3524// operator<=
3525template <typename T>
3527 return !(b < a);
3528}
3529
3530template <typename T>
3531bool operator<=(Span<const T> a, Span<T> b) {
3532 return !(b < a);
3533}
3534
3535template <typename T>
3536bool operator<=(Span<T> a, Span<const T> b) {
3537 return !(b < a);
3538}
3539
3540template <typename T, typename U,
3541 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3542bool operator<=(const U& a, Span<T> b) {
3543 return !(b < a);
3544}
3545
3546template <typename T, typename U,
3547 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3548bool operator<=(Span<T> a, const U& b) {
3549 return !(b < a);
3550}
3551
3552// operator>=
3553template <typename T>
3555 return !(a < b);
3556}
3557
3558template <typename T>
3559bool operator>=(Span<const T> a, Span<T> b) {
3560 return !(a < b);
3561}
3562
3563template <typename T>
3564bool operator>=(Span<T> a, Span<const T> b) {
3565 return !(a < b);
3566}
3567
3568template <typename T, typename U,
3569 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3570bool operator>=(const U& a, Span<T> b) {
3571 return !(a < b);
3572}
3573
3574template <typename T, typename U,
3575 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3576bool operator>=(Span<T> a, const U& b) {
3577 return !(a < b);
3578}
3579
3580// MakeSpan()
3581//
3582// Constructs a mutable `Span<T>`, deducing `T` automatically from either a
3583// container or pointer+size.
3584//
3585// Because a read-only `Span<const T>` is implicitly constructed from container
3586// types regardless of whether the container itself is a const container,
3587// constructing mutable spans of type `Span<T>` from containers requires
3588// explicit constructors. The container-accepting version of `MakeSpan()`
3589// deduces the type of `T` by the constness of the pointer received from the
3590// container's `data()` member. Similarly, the pointer-accepting version returns
3591// a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise.
3592//
3593// Examples:
3594//
3595// void MyRoutine(phmap::Span<MyComplicatedType> a) {
3596// ...
3597// };
3598// // my_vector is a container of non-const types
3599// std::vector<MyComplicatedType> my_vector;
3600//
3601// // Constructing a Span implicitly attempts to create a Span of type
3602// // `Span<const T>`
3603// MyRoutine(my_vector); // error, type mismatch
3604//
3605// // Explicitly constructing the Span is verbose
3606// MyRoutine(phmap::Span<MyComplicatedType>(my_vector));
3607//
3608// // Use MakeSpan() to make an phmap::Span<T>
3609// MyRoutine(phmap::MakeSpan(my_vector));
3610//
3611// // Construct a span from an array ptr+size
3612// phmap::Span<T> my_span() {
3613// return phmap::MakeSpan(&array[0], num_elements_);
3614// }
3615//
3616template <int&... ExplicitArgumentBarrier, typename T>
3617constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept {
3618 return Span<T>(ptr, size);
3619}
3620
3621template <int&... ExplicitArgumentBarrier, typename T>
3622Span<T> MakeSpan(T* begin, T* end) noexcept {
3623 return PHMAP_ASSERT(begin <= end), Span<T>(begin, end - begin);
3624}
3625
3626template <int&... ExplicitArgumentBarrier, typename C>
3627constexpr auto MakeSpan(C& c) noexcept // NOLINT(runtime/references)
3628 -> decltype(phmap::MakeSpan(span_internal::GetData(c), c.size())) {
3629 return MakeSpan(span_internal::GetData(c), c.size());
3630}
3631
3632template <int&... ExplicitArgumentBarrier, typename T, size_t N>
3633constexpr Span<T> MakeSpan(T (&array)[N]) noexcept {
3634 return Span<T>(array, N);
3635}
3636
3637// MakeConstSpan()
3638//
3639// Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically,
3640// but always returning a `Span<const T>`.
3641//
3642// Examples:
3643//
3644// void ProcessInts(phmap::Span<const int> some_ints);
3645//
3646// // Call with a pointer and size.
3647// int array[3] = { 0, 0, 0 };
3648// ProcessInts(phmap::MakeConstSpan(&array[0], 3));
3649//
3650// // Call with a [begin, end) pair.
3651// ProcessInts(phmap::MakeConstSpan(&array[0], &array[3]));
3652//
3653// // Call directly with an array.
3654// ProcessInts(phmap::MakeConstSpan(array));
3655//
3656// // Call with a contiguous container.
3657// std::vector<int> some_ints = ...;
3658// ProcessInts(phmap::MakeConstSpan(some_ints));
3659// ProcessInts(phmap::MakeConstSpan(std::vector<int>{ 0, 0, 0 }));
3660//
3661template <int&... ExplicitArgumentBarrier, typename T>
3662constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept {
3663 return Span<const T>(ptr, size);
3664}
3665
3666template <int&... ExplicitArgumentBarrier, typename T>
3667Span<const T> MakeConstSpan(T* begin, T* end) noexcept {
3668 return PHMAP_ASSERT(begin <= end), Span<const T>(begin, end - begin);
3669}
3670
3671template <int&... ExplicitArgumentBarrier, typename C>
3672constexpr auto MakeConstSpan(const C& c) noexcept -> decltype(MakeSpan(c)) {
3673 return MakeSpan(c);
3674}
3675
3676template <int&... ExplicitArgumentBarrier, typename T, size_t N>
3677constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept {
3678 return Span<const T>(array, N);
3679}
3680} // namespace phmap
3681
3682// ---------------------------------------------------------------------------
3683// layout.h
3684// ---------------------------------------------------------------------------
3685namespace phmap {
3686namespace priv {
3687
3688// A type wrapper that instructs `Layout` to use the specific alignment for the
3689// array. `Layout<..., Aligned<T, N>, ...>` has exactly the same API
3690// and behavior as `Layout<..., T, ...>` except that the first element of the
3691// array of `T` is aligned to `N` (the rest of the elements follow without
3692// padding).
3693//
3694// Requires: `N >= alignof(T)` and `N` is a power of 2.
3695template <class T, size_t N>
3696struct Aligned;
3697
3698namespace internal_layout {
3699
3700template <class T>
3701struct NotAligned {};
3702
3703template <class T, size_t N>
3704struct NotAligned<const Aligned<T, N>> {
3705 static_assert(sizeof(T) == 0, "Aligned<T, N> cannot be const-qualified");
3706};
3707
3708template <size_t>
3709using IntToSize = size_t;
3710
3711template <class>
3712using TypeToSize = size_t;
3713
3714template <class T>
3715struct Type : NotAligned<T> {
3716 using type = T;
3717};
3718
3719template <class T, size_t N>
3720struct Type<Aligned<T, N>> {
3721 using type = T;
3722};
3723
3724template <class T>
3725struct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {};
3726
3727template <class T, size_t N>
3728struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
3729
3730// Note: workaround for https://gcc.gnu.org/PR88115
3731template <class T>
3732struct AlignOf : NotAligned<T> {
3733 static constexpr size_t value = alignof(T);
3734};
3735
3736template <class T, size_t N>
3737struct AlignOf<Aligned<T, N>> {
3738 static_assert(N % alignof(T) == 0,
3739 "Custom alignment can't be lower than the type's alignment");
3740 static constexpr size_t value = N;
3741};
3742
3743// Does `Ts...` contain `T`?
3744template <class T, class... Ts>
3746
3747template <class From, class To>
3749 typename std::conditional<std::is_const<From>::value, const To, To>::type;
3750
3751// Note: We're not qualifying this with phmap:: because it doesn't compile under
3752// MSVC.
3753template <class T>
3755
3756// This namespace contains no types. It prevents functions defined in it from
3757// being found by ADL.
3758namespace adl_barrier {
3759
3760template <class Needle, class... Ts>
3761constexpr size_t Find(Needle, Needle, Ts...) {
3762 static_assert(!Contains<Needle, Ts...>(), "Duplicate element type");
3763 return 0;
3764}
3765
3766template <class Needle, class T, class... Ts>
3767constexpr size_t Find(Needle, T, Ts...) {
3768 return adl_barrier::Find(Needle(), Ts()...) + 1;
3769}
3770
3771constexpr bool IsPow2(size_t n) { return !(n & (n - 1)); }
3772
3773// Returns `q * m` for the smallest `q` such that `q * m >= n`.
3774// Requires: `m` is a power of two. It's enforced by IsLegalElementType below.
3775constexpr size_t Align(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); }
3776
3777constexpr size_t Min(size_t a, size_t b) { return b < a ? b : a; }
3778
3779constexpr size_t Max(size_t a) { return a; }
3780
3781template <class... Ts>
3782constexpr size_t Max(size_t a, size_t b, Ts... rest) {
3783 return adl_barrier::Max(b < a ? a : b, rest...);
3784}
3785
3786} // namespace adl_barrier
3787
3788template <bool C>
3789using EnableIf = typename std::enable_if<C, int>::type;
3790
3791// Can `T` be a template argument of `Layout`?
3792// ---------------------------------------------------------------------------
3793template <class T>
3794using IsLegalElementType = std::integral_constant<
3795 bool, !std::is_reference<T>::value && !std::is_volatile<T>::value &&
3796 !std::is_reference<typename Type<T>::type>::value &&
3797 !std::is_volatile<typename Type<T>::type>::value &&
3799
3800template <class Elements, class SizeSeq, class OffsetSeq>
3802
3803// ---------------------------------------------------------------------------
3804// Public base class of `Layout` and the result type of `Layout::Partial()`.
3805//
3806// `Elements...` contains all template arguments of `Layout` that created this
3807// instance.
3808//
3809// `SizeSeq...` is `[0, NumSizes)` where `NumSizes` is the number of arguments
3810// passed to `Layout::Partial()` or `Layout::Layout()`.
3811//
3812// `OffsetSeq...` is `[0, NumOffsets)` where `NumOffsets` is
3813// `Min(sizeof...(Elements), NumSizes + 1)` (the number of arrays for which we
3814// can compute offsets).
3815// ---------------------------------------------------------------------------
3816template <class... Elements, size_t... SizeSeq, size_t... OffsetSeq>
3817class LayoutImpl<std::tuple<Elements...>, phmap::index_sequence<SizeSeq...>,
3818 phmap::index_sequence<OffsetSeq...>>
3819{
3820private:
3821 static_assert(sizeof...(Elements) > 0, "At least one field is required");
3822 static_assert(phmap::conjunction<IsLegalElementType<Elements>...>::value,
3823 "Invalid element type (see IsLegalElementType)");
3824
3825 enum {
3826 NumTypes = sizeof...(Elements),
3827 NumSizes = sizeof...(SizeSeq),
3828 NumOffsets = sizeof...(OffsetSeq),
3829 };
3830
3831 // These are guaranteed by `Layout`.
3832 static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1),
3833 "Internal error");
3834 static_assert(NumTypes > 0, "Internal error");
3835
3836 // Returns the index of `T` in `Elements...`. Results in a compilation error
3837 // if `Elements...` doesn't contain exactly one instance of `T`.
3838 template <class T>
3839 static constexpr size_t ElementIndex() {
3841 "Type not found");
3842 return adl_barrier::Find(Type<T>(),
3843 Type<typename Type<Elements>::type>()...);
3844 }
3845
3846 template <size_t N>
3848 AlignOf<typename std::tuple_element<N, std::tuple<Elements...>>::type>;
3849
3850public:
3851 // Element types of all arrays packed in a tuple.
3852 using ElementTypes = std::tuple<typename Type<Elements>::type...>;
3853
3854 // Element type of the Nth array.
3855 template <size_t N>
3856 using ElementType = typename std::tuple_element<N, ElementTypes>::type;
3857
3858 constexpr explicit LayoutImpl(IntToSize<SizeSeq>... sizes)
3859 : size_{sizes...} {}
3860
3861 // Alignment of the layout, equal to the strictest alignment of all elements.
3862 // All pointers passed to the methods of layout must be aligned to this value.
3863 static constexpr size_t Alignment() {
3865 }
3866
3867 // Offset in bytes of the Nth array.
3868 //
3869 // // int[3], 4 bytes of padding, double[4].
3870 // Layout<int, double> x(3, 4);
3871 // assert(x.Offset<0>() == 0); // The ints starts from 0.
3872 // assert(x.Offset<1>() == 16); // The doubles starts from 16.
3873 //
3874 // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
3875 template <size_t N, EnableIf<N == 0> = 0>
3876 constexpr size_t Offset() const {
3877 return 0;
3878 }
3879
3880 template <size_t N, EnableIf<N != 0> = 0>
3881 constexpr size_t Offset() const {
3882 static_assert(N < NumOffsets, "Index out of bounds");
3883 return adl_barrier::Align(
3884 Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * size_[N - 1],
3886 }
3887
3888 // Offset in bytes of the array with the specified element type. There must
3889 // be exactly one such array and its zero-based index must be at most
3890 // `NumSizes`.
3891 //
3892 // // int[3], 4 bytes of padding, double[4].
3893 // Layout<int, double> x(3, 4);
3894 // assert(x.Offset<int>() == 0); // The ints starts from 0.
3895 // assert(x.Offset<double>() == 16); // The doubles starts from 16.
3896 template <class T>
3897 constexpr size_t Offset() const {
3898 return Offset<ElementIndex<T>()>();
3899 }
3900
3901 // Offsets in bytes of all arrays for which the offsets are known.
3902 constexpr std::array<size_t, NumOffsets> Offsets() const {
3903 return {{Offset<OffsetSeq>()...}};
3904 }
3905
3906 // The number of elements in the Nth array. This is the Nth argument of
3907 // `Layout::Partial()` or `Layout::Layout()` (zero-based).
3908 //
3909 // // int[3], 4 bytes of padding, double[4].
3910 // Layout<int, double> x(3, 4);
3911 // assert(x.Size<0>() == 3);
3912 // assert(x.Size<1>() == 4);
3913 //
3914 // Requires: `N < NumSizes`.
3915 template <size_t N>
3916 constexpr size_t Size() const {
3917 static_assert(N < NumSizes, "Index out of bounds");
3918 return size_[N];
3919 }
3920
3921 // The number of elements in the array with the specified element type.
3922 // There must be exactly one such array and its zero-based index must be
3923 // at most `NumSizes`.
3924 //
3925 // // int[3], 4 bytes of padding, double[4].
3926 // Layout<int, double> x(3, 4);
3927 // assert(x.Size<int>() == 3);
3928 // assert(x.Size<double>() == 4);
3929 template <class T>
3930 constexpr size_t Size() const {
3931 return Size<ElementIndex<T>()>();
3932 }
3933
3934 // The number of elements of all arrays for which they are known.
3935 constexpr std::array<size_t, NumSizes> Sizes() const {
3936 return {{Size<SizeSeq>()...}};
3937 }
3938
3939 // Pointer to the beginning of the Nth array.
3940 //
3941 // `Char` must be `[const] [signed|unsigned] char`.
3942 //
3943 // // int[3], 4 bytes of padding, double[4].
3944 // Layout<int, double> x(3, 4);
3945 // unsigned char* p = new unsigned char[x.AllocSize()];
3946 // int* ints = x.Pointer<0>(p);
3947 // double* doubles = x.Pointer<1>(p);
3948 //
3949 // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
3950 // Requires: `p` is aligned to `Alignment()`.
3951 template <size_t N, class Char>
3953 using C = typename std::remove_const<Char>::type;
3954 static_assert(
3955 std::is_same<C, char>() || std::is_same<C, unsigned char>() ||
3956 std::is_same<C, signed char>(),
3957 "The argument must be a pointer to [const] [signed|unsigned] char");
3958 constexpr size_t alignment = Alignment();
3959 (void)alignment;
3960 assert(reinterpret_cast<uintptr_t>(p) % alignment == 0);
3961 return reinterpret_cast<CopyConst<Char, ElementType<N>>*>(p + Offset<N>());
3962 }
3963
3964 // Pointer to the beginning of the array with the specified element type.
3965 // There must be exactly one such array and its zero-based index must be at
3966 // most `NumSizes`.
3967 //
3968 // `Char` must be `[const] [signed|unsigned] char`.
3969 //
3970 // // int[3], 4 bytes of padding, double[4].
3971 // Layout<int, double> x(3, 4);
3972 // unsigned char* p = new unsigned char[x.AllocSize()];
3973 // int* ints = x.Pointer<int>(p);
3974 // double* doubles = x.Pointer<double>(p);
3975 //
3976 // Requires: `p` is aligned to `Alignment()`.
3977 template <class T, class Char>
3978 CopyConst<Char, T>* Pointer(Char* p) const {
3979 return Pointer<ElementIndex<T>()>(p);
3980 }
3981
3982 // Pointers to all arrays for which pointers are known.
3983 //
3984 // `Char` must be `[const] [signed|unsigned] char`.
3985 //
3986 // // int[3], 4 bytes of padding, double[4].
3987 // Layout<int, double> x(3, 4);
3988 // unsigned char* p = new unsigned char[x.AllocSize()];
3989 //
3990 // int* ints;
3991 // double* doubles;
3992 // std::tie(ints, doubles) = x.Pointers(p);
3993 //
3994 // Requires: `p` is aligned to `Alignment()`.
3995 //
3996 // Note: We're not using ElementType alias here because it does not compile
3997 // under MSVC.
3998 template <class Char>
3999 std::tuple<CopyConst<
4000 Char, typename std::tuple_element<OffsetSeq, ElementTypes>::type>*...>
4001 Pointers(Char* p) const {
4002 return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(
4003 Pointer<OffsetSeq>(p)...);
4004 }
4005
4006 // The Nth array.
4007 //
4008 // `Char` must be `[const] [signed|unsigned] char`.
4009 //
4010 // // int[3], 4 bytes of padding, double[4].
4011 // Layout<int, double> x(3, 4);
4012 // unsigned char* p = new unsigned char[x.AllocSize()];
4013 // Span<int> ints = x.Slice<0>(p);
4014 // Span<double> doubles = x.Slice<1>(p);
4015 //
4016 // Requires: `N < NumSizes`.
4017 // Requires: `p` is aligned to `Alignment()`.
4018 template <size_t N, class Char>
4020 return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>());
4021 }
4022
4023 // The array with the specified element type. There must be exactly one
4024 // such array and its zero-based index must be less than `NumSizes`.
4025 //
4026 // `Char` must be `[const] [signed|unsigned] char`.
4027 //
4028 // // int[3], 4 bytes of padding, double[4].
4029 // Layout<int, double> x(3, 4);
4030 // unsigned char* p = new unsigned char[x.AllocSize()];
4031 // Span<int> ints = x.Slice<int>(p);
4032 // Span<double> doubles = x.Slice<double>(p);
4033 //
4034 // Requires: `p` is aligned to `Alignment()`.
4035 template <class T, class Char>
4037 return Slice<ElementIndex<T>()>(p);
4038 }
4039
4040 // All arrays with known sizes.
4041 //
4042 // `Char` must be `[const] [signed|unsigned] char`.
4043 //
4044 // // int[3], 4 bytes of padding, double[4].
4045 // Layout<int, double> x(3, 4);
4046 // unsigned char* p = new unsigned char[x.AllocSize()];
4047 //
4048 // Span<int> ints;
4049 // Span<double> doubles;
4050 // std::tie(ints, doubles) = x.Slices(p);
4051 //
4052 // Requires: `p` is aligned to `Alignment()`.
4053 //
4054 // Note: We're not using ElementType alias here because it does not compile
4055 // under MSVC.
4056 template <class Char>
4057 std::tuple<SliceType<CopyConst<
4058 Char, typename std::tuple_element<SizeSeq, ElementTypes>::type>>...>
4059 Slices(Char* p) const {
4060 // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63875 (fixed
4061 // in 6.1).
4062 (void)p;
4063 return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
4064 Slice<SizeSeq>(p)...);
4065 }
4066
4067 // The size of the allocation that fits all arrays.
4068 //
4069 // // int[3], 4 bytes of padding, double[4].
4070 // Layout<int, double> x(3, 4);
4071 // unsigned char* p = new unsigned char[x.AllocSize()]; // 48 bytes
4072 //
4073 // Requires: `NumSizes == sizeof...(Ts)`.
4074 constexpr size_t AllocSize() const {
4075 static_assert(NumTypes == NumSizes, "You must specify sizes of all fields");
4076 return Offset<NumTypes - 1>() +
4077 SizeOf<ElementType<NumTypes - 1>>::value * size_[NumTypes - 1];
4078 }
4079
4080 // If built with --config=asan, poisons padding bytes (if any) in the
4081 // allocation. The pointer must point to a memory block at least
4082 // `AllocSize()` bytes in length.
4083 //
4084 // `Char` must be `[const] [signed|unsigned] char`.
4085 //
4086 // Requires: `p` is aligned to `Alignment()`.
4087 template <class Char, size_t N = NumOffsets - 1, EnableIf<N == 0> = 0>
4088 void PoisonPadding(const Char* p) const {
4089 Pointer<0>(p); // verify the requirements on `Char` and `p`
4090 }
4091
4092 template <class Char, size_t N = NumOffsets - 1, EnableIf<N != 0> = 0>
4093 void PoisonPadding(const Char* p) const {
4094 static_assert(N < NumOffsets, "Index out of bounds");
4095 (void)p;
4096#ifdef ADDRESS_SANITIZER
4097 PoisonPadding<Char, N - 1>(p);
4098 // The `if` is an optimization. It doesn't affect the observable behaviour.
4100 size_t start =
4101 Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * size_[N - 1];
4102 ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
4103 }
4104#endif
4105 }
4106
4107private:
4108 // Arguments of `Layout::Partial()` or `Layout::Layout()`.
4109 size_t size_[NumSizes > 0 ? NumSizes : 1];
4110};
4111
4112template <size_t NumSizes, class... Ts>
4114 std::tuple<Ts...>, phmap::make_index_sequence<NumSizes>,
4115 phmap::make_index_sequence<adl_barrier::Min(sizeof...(Ts), NumSizes + 1)>>;
4116
4117} // namespace internal_layout
4118
4119// ---------------------------------------------------------------------------
4120// Descriptor of arrays of various types and sizes laid out in memory one after
4121// another. See the top of the file for documentation.
4122//
4123// Check out the public API of internal_layout::LayoutImpl above. The type is
4124// internal to the library but its methods are public, and they are inherited
4125// by `Layout`.
4126// ---------------------------------------------------------------------------
4127template <class... Ts>
4128class Layout : public internal_layout::LayoutType<sizeof...(Ts), Ts...>
4129{
4130public:
4131 static_assert(sizeof...(Ts) > 0, "At least one field is required");
4132 static_assert(
4134 "Invalid element type (see IsLegalElementType)");
4135
4136 template <size_t NumSizes>
4138
4139 template <class... Sizes>
4140 static constexpr PartialType<sizeof...(Sizes)> Partial(Sizes&&... sizes) {
4141 static_assert(sizeof...(Sizes) <= sizeof...(Ts), "");
4142 return PartialType<sizeof...(Sizes)>(phmap::forward<Sizes>(sizes)...);
4143 }
4144
4145 // Creates a layout with the sizes of all arrays specified. If you know
4146 // only the sizes of the first N arrays (where N can be zero), you can use
4147 // `Partial()` defined above. The constructor is essentially equivalent to
4148 // calling `Partial()` and passing in all array sizes; the constructor is
4149 // provided as a convenient abbreviation.
4150 //
4151 // Note: The sizes of the arrays must be specified in number of elements,
4152 // not in bytes.
4153 constexpr explicit Layout(internal_layout::TypeToSize<Ts>... sizes)
4154 : internal_layout::LayoutType<sizeof...(Ts), Ts...>(sizes...) {}
4155};
4156
4157} // namespace priv
4158} // namespace phmap
4159
4160// ---------------------------------------------------------------------------
4161// compressed_tuple.h
4162// ---------------------------------------------------------------------------
4163
4164#ifdef _MSC_VER
4165 // We need to mark these classes with this declspec to ensure that
4166 // CompressedTuple happens.
4167 #define PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
4168#else // _MSC_VER
4169 #define PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
4170#endif // _MSC_VER
4171
4172namespace phmap {
4173namespace priv {
4174
4175template <typename... Ts>
4176class CompressedTuple;
4177
4178namespace internal_compressed_tuple {
4179
4180template <typename D, size_t I>
4181struct Elem;
4182template <typename... B, size_t I>
4183struct Elem<CompressedTuple<B...>, I>
4184 : std::tuple_element<I, std::tuple<B...>> {};
4185template <typename D, size_t I>
4186using ElemT = typename Elem<D, I>::type;
4187
4188// ---------------------------------------------------------------------------
4189// Use the __is_final intrinsic if available. Where it's not available, classes
4190// declared with the 'final' specifier cannot be used as CompressedTuple
4191// elements.
4192// TODO(sbenza): Replace this with std::is_final in C++14.
4193// ---------------------------------------------------------------------------
4194template <typename T>
4195constexpr bool IsFinal() {
4196#if defined(__clang__) || defined(__GNUC__)
4197 return __is_final(T);
4198#else
4199 return false;
4200#endif
4201}
4202
4203template <typename T>
4204constexpr bool ShouldUseBase() {
4205#ifdef __INTEL_COMPILER
4206 // avoid crash in Intel compiler
4207 // assertion failed at: "shared/cfe/edgcpfe/lower_init.c", line 7013
4208 return false;
4209#else
4210 return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>();
4211#endif
4212}
4213
4214// The storage class provides two specializations:
4215// - For empty classes, it stores T as a base class.
4216// - For everything else, it stores T as a member.
4217// ------------------------------------------------
4218template <typename D, size_t I, bool = ShouldUseBase<ElemT<D, I>>()>
4219struct Storage
4220{
4223 constexpr Storage() = default;
4224 explicit constexpr Storage(T&& v) : value(phmap::forward<T>(v)) {}
4225 constexpr const T& get() const& { return value; }
4226 T& get() & { return value; }
4227 constexpr const T&& get() const&& { return phmap::move(*this).value; }
4228 T&& get() && { return std::move(*this).value; }
4229};
4230
4231template <typename D, size_t I>
4233 : ElemT<D, I>
4234{
4236 constexpr Storage() = default;
4237 explicit constexpr Storage(T&& v) : T(phmap::forward<T>(v)) {}
4238 constexpr const T& get() const& { return *this; }
4239 T& get() & { return *this; }
4240 constexpr const T&& get() const&& { return phmap::move(*this); }
4241 T&& get() && { return std::move(*this); }
4242};
4243
4244template <typename D, typename I>
4246
4247template <typename... Ts, size_t... I>
4250 // We use the dummy identity function through std::integral_constant to
4251 // convince MSVC of accepting and expanding I in that context. Without it
4252 // you would get:
4253 // error C3548: 'I': parameter pack cannot be used in this context
4254 : Storage<CompressedTuple<Ts...>,
4255 std::integral_constant<size_t, I>::value>...
4256{
4257 constexpr CompressedTupleImpl() = default;
4258 explicit constexpr CompressedTupleImpl(Ts&&... args)
4259 : Storage<CompressedTuple<Ts...>, I>(phmap::forward<Ts>(args))... {}
4260};
4261
4262} // namespace internal_compressed_tuple
4263
4264// ---------------------------------------------------------------------------
4265// Helper class to perform the Empty Base Class Optimization.
4266// Ts can contain classes and non-classes, empty or not. For the ones that
4267// are empty classes, we perform the CompressedTuple. If all types in Ts are
4268// empty classes, then CompressedTuple<Ts...> is itself an empty class.
4269//
4270// To access the members, use member .get<N>() function.
4271//
4272// Eg:
4273// phmap::priv::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
4274// t3);
4275// assert(value.get<0>() == 7);
4276// T1& t1 = value.get<1>();
4277// const T2& t2 = value.get<2>();
4278// ...
4279//
4280// https://en.cppreference.com/w/cpp/language/ebo
4281// ---------------------------------------------------------------------------
4282template <typename... Ts>
4284 : private internal_compressed_tuple::CompressedTupleImpl<
4285 CompressedTuple<Ts...>, phmap::index_sequence_for<Ts...>>
4286{
4287private:
4288 template <int I>
4290
4291public:
4292 constexpr CompressedTuple() = default;
4293 explicit constexpr CompressedTuple(Ts... base)
4294 : CompressedTuple::CompressedTupleImpl(phmap::forward<Ts>(base)...) {}
4295
4296 template <int I>
4300
4301 template <int I>
4302 constexpr const ElemT<I>& get() const& {
4304 }
4305
4306 template <int I>
4307 ElemT<I>&& get() && {
4308 return std::move(*this)
4309 .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
4310 }
4311
4312 template <int I>
4313 constexpr const ElemT<I>&& get() const&& {
4314 return phmap::move(*this)
4315 .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
4316 }
4317};
4318
4319// Explicit specialization for a zero-element tuple
4320// (needed to avoid ambiguous overloads for the default constructor).
4321// ---------------------------------------------------------------------------
4322template <>
4324
4325} // namespace priv
4326} // namespace phmap
4327
4328
4329namespace phmap {
4330namespace priv {
4331
4332#ifdef _MSC_VER
4333 #pragma warning(push)
4334 // warning warning C4324: structure was padded due to alignment specifier
4335 #pragma warning(disable : 4324)
4336#endif
4337
4338
4339// ----------------------------------------------------------------------------
4340// Allocates at least n bytes aligned to the specified alignment.
4341// Alignment must be a power of 2. It must be positive.
4342//
4343// Note that many allocators don't honor alignment requirements above certain
4344// threshold (usually either alignof(std::max_align_t) or alignof(void*)).
4345// Allocate() doesn't apply alignment corrections. If the underlying allocator
4346// returns insufficiently alignment pointer, that's what you are going to get.
4347// ----------------------------------------------------------------------------
4348template <size_t Alignment, class Alloc>
4349void* Allocate(Alloc* alloc, size_t n) {
4350 static_assert(Alignment > 0, "");
4351 assert(n && "n must be positive");
4352 struct alignas(Alignment) M {};
4353 using A = typename phmap::allocator_traits<Alloc>::template rebind_alloc<M>;
4354 using AT = typename phmap::allocator_traits<Alloc>::template rebind_traits<M>;
4355 A mem_alloc(*alloc);
4356 void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
4357 assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
4358 "allocator does not respect alignment");
4359 return p;
4360}
4361
4362// ----------------------------------------------------------------------------
4363// The pointer must have been previously obtained by calling
4364// Allocate<Alignment>(alloc, n).
4365// ----------------------------------------------------------------------------
4366template <size_t Alignment, class Alloc>
4367void Deallocate(Alloc* alloc, void* p, size_t n) {
4368 static_assert(Alignment > 0, "");
4369 assert(n && "n must be positive");
4370 struct alignas(Alignment) M {};
4371 using A = typename phmap::allocator_traits<Alloc>::template rebind_alloc<M>;
4372 using AT = typename phmap::allocator_traits<Alloc>::template rebind_traits<M>;
4373 A mem_alloc(*alloc);
4374 AT::deallocate(mem_alloc, static_cast<M*>(p),
4375 (n + sizeof(M) - 1) / sizeof(M));
4376}
4377
4378#ifdef _MSC_VER
4379 #pragma warning(pop)
4380#endif
4381
4382// Helper functions for asan and msan.
4383// ----------------------------------------------------------------------------
4384inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
4385#ifdef ADDRESS_SANITIZER
4386 ASAN_POISON_MEMORY_REGION(m, s);
4387#endif
4388#ifdef MEMORY_SANITIZER
4389 __msan_poison(m, s);
4390#endif
4391 (void)m;
4392 (void)s;
4393}
4394
4395inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {
4396#ifdef ADDRESS_SANITIZER
4397 ASAN_UNPOISON_MEMORY_REGION(m, s);
4398#endif
4399#ifdef MEMORY_SANITIZER
4400 __msan_unpoison(m, s);
4401#endif
4402 (void)m;
4403 (void)s;
4404}
4405
4406template <typename T>
4407inline void SanitizerPoisonObject(const T* object) {
4408 SanitizerPoisonMemoryRegion(object, sizeof(T));
4409}
4410
4411template <typename T>
4412inline void SanitizerUnpoisonObject(const T* object) {
4413 SanitizerUnpoisonMemoryRegion(object, sizeof(T));
4414}
4415
4416} // namespace priv
4417} // namespace phmap
4418
4419
4420// ---------------------------------------------------------------------------
4421// thread_annotations.h
4422// ---------------------------------------------------------------------------
4423
4424#if defined(__clang__)
4425 #define PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
4426#else
4427 #define PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
4428#endif
4429
4430#define PHMAP_GUARDED_BY(x) PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
4431#define PHMAP_PT_GUARDED_BY(x) PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
4432
4433#define PHMAP_ACQUIRED_AFTER(...) \
4434 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
4435
4436#define PHMAP_ACQUIRED_BEFORE(...) \
4437 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
4438
4439#define PHMAP_EXCLUSIVE_LOCKS_REQUIRED(...) \
4440 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
4441
4442#define PHMAP_SHARED_LOCKS_REQUIRED(...) \
4443 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
4444
4445#define PHMAP_LOCKS_EXCLUDED(...) \
4446 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
4447
4448#define PHMAP_LOCK_RETURNED(x) \
4449 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
4450
4451#define PHMAP_LOCKABLE \
4452 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(lockable)
4453
4454#define PHMAP_SCOPED_LOCKABLE \
4455 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
4456
4457#define PHMAP_EXCLUSIVE_LOCK_FUNCTION(...) \
4458 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
4459
4460#define PHMAP_SHARED_LOCK_FUNCTION(...) \
4461 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
4462
4463#define PHMAP_UNLOCK_FUNCTION(...) \
4464 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
4465
4466#define PHMAP_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
4467 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
4468
4469#define PHMAP_SHARED_TRYLOCK_FUNCTION(...) \
4470 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
4471
4472#define PHMAP_ASSERT_EXCLUSIVE_LOCK(...) \
4473 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
4474
4475#define PHMAP_ASSERT_SHARED_LOCK(...) \
4476 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
4477
4478#define PHMAP_NO_THREAD_SAFETY_ANALYSIS \
4479 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
4480
4481//------------------------------------------------------------------------------
4482// Tool-Supplied Annotations
4483//------------------------------------------------------------------------------
4484
4485// TS_UNCHECKED should be placed around lock expressions that are not valid
4486// C++ syntax, but which are present for documentation purposes. These
4487// annotations will be ignored by the analysis.
4488#define PHMAP_TS_UNCHECKED(x) ""
4489
4490// TS_FIXME is used to mark lock expressions that are not valid C++ syntax.
4491// It is used by automated tools to mark and disable invalid expressions.
4492// The annotation should either be fixed, or changed to TS_UNCHECKED.
4493#define PHMAP_TS_FIXME(x) ""
4494
4495// Like NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body of
4496// a particular function. However, this attribute is used to mark functions
4497// that are incorrect and need to be fixed. It is used by automated tools to
4498// avoid breaking the build when the analysis is updated.
4499// Code owners are expected to eventually fix the routine.
4500#define PHMAP_NO_THREAD_SAFETY_ANALYSIS_FIXME PHMAP_NO_THREAD_SAFETY_ANALYSIS
4501
4502// Similar to NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a GUARDED_BY
4503// annotation that needs to be fixed, because it is producing thread safety
4504// warning. It disables the GUARDED_BY.
4505#define PHMAP_GUARDED_BY_FIXME(x)
4506
4507// Disables warnings for a single read operation. This can be used to avoid
4508// warnings when it is known that the read is not actually involved in a race,
4509// but the compiler cannot confirm that.
4510#define PHMAP_TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x)
4511
4512
4513namespace phmap {
4514namespace thread_safety_analysis {
4515
4516// Takes a reference to a guarded data member, and returns an unguarded
4517// reference.
4518template <typename T>
4520 return v;
4521}
4522
4523template <typename T>
4525 return v;
4526}
4527
4528} // namespace thread_safety_analysis
4529
4530namespace priv {
4531
4532namespace memory_internal {
4533
4534// ----------------------------------------------------------------------------
4535// If Pair is a standard-layout type, OffsetOf<Pair>::kFirst and
4536// OffsetOf<Pair>::kSecond are equivalent to offsetof(Pair, first) and
4537// offsetof(Pair, second) respectively. Otherwise they are -1.
4538//
4539// The purpose of OffsetOf is to avoid calling offsetof() on non-standard-layout
4540// type, which is non-portable.
4541// ----------------------------------------------------------------------------
4542template <class Pair, class = std::true_type>
4543struct OffsetOf {
4544 static constexpr size_t kFirst = (size_t)-1;
4545 static constexpr size_t kSecond = (size_t)-1;
4546};
4547
4548template <class Pair>
4549struct OffsetOf<Pair, typename std::is_standard_layout<Pair>::type>
4550{
4551 static constexpr size_t kFirst = offsetof(Pair, first);
4552 static constexpr size_t kSecond = offsetof(Pair, second);
4553};
4554
4555// ----------------------------------------------------------------------------
4556template <class K, class V>
4558{
4559private:
4560 struct Pair {
4563 };
4564
4565 // Is P layout-compatible with Pair?
4566 template <class P>
4567 static constexpr bool LayoutCompatible() {
4568 return std::is_standard_layout<P>() && sizeof(P) == sizeof(Pair) &&
4569 alignof(P) == alignof(Pair) &&
4574 }
4575
4576public:
4577 // Whether pair<const K, V> and pair<K, V> are layout-compatible. If they are,
4578 // then it is safe to store them in a union and read from either.
4579 static constexpr bool value = std::is_standard_layout<K>() &&
4580 std::is_standard_layout<Pair>() &&
4582 LayoutCompatible<std::pair<K, V>>() &&
4583 LayoutCompatible<std::pair<const K, V>>();
4584};
4585
4586} // namespace memory_internal
4587
4588// ----------------------------------------------------------------------------
4589// The internal storage type for key-value containers like flat_hash_map.
4590//
4591// It is convenient for the value_type of a flat_hash_map<K, V> to be
4592// pair<const K, V>; the "const K" prevents accidental modification of the key
4593// when dealing with the reference returned from find() and similar methods.
4594// However, this creates other problems; we want to be able to emplace(K, V)
4595// efficiently with move operations, and similarly be able to move a
4596// pair<K, V> in insert().
4597//
4598// The solution is this union, which aliases the const and non-const versions
4599// of the pair. This also allows flat_hash_map<const K, V> to work, even though
4600// that has the same efficiency issues with move in emplace() and insert() -
4601// but people do it anyway.
4602//
4603// If kMutableKeys is false, only the value member can be accessed.
4604//
4605// If kMutableKeys is true, key can be accessed through all slots while value
4606// and mutable_value must be accessed only via INITIALIZED slots. Slots are
4607// created and destroyed via mutable_value so that the key can be moved later.
4608//
4609// Accessing one of the union fields while the other is active is safe as
4610// long as they are layout-compatible, which is guaranteed by the definition of
4611// kMutableKeys. For C++11, the relevant section of the standard is
4612// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)
4613// ----------------------------------------------------------------------------
4614template <class K, class V>
4616{
4618 ~map_slot_type() = delete;
4621
4622 using value_type = std::pair<const K, V>;
4623 using mutable_value_type = std::pair<K, V>;
4624
4628};
4629
4630// ----------------------------------------------------------------------------
4631// ----------------------------------------------------------------------------
4632template <class K, class V>
4634{
4636 using value_type = std::pair<const K, V>;
4637 using mutable_value_type = std::pair<K, V>;
4638
4639private:
4640 static void emplace(slot_type* slot) {
4641 // The construction of union doesn't do anything at runtime but it allows us
4642 // to access its members without violating aliasing rules.
4643 new (slot) slot_type;
4644 }
4645 // If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one
4646 // or the other via slot_type. We are also free to access the key via
4647 // slot_type::key in this case.
4649
4650public:
4651 static value_type& element(slot_type* slot) { return slot->value; }
4652 static const value_type& element(const slot_type* slot) {
4653 return slot->value;
4654 }
4655
4656 static const K& key(const slot_type* slot) {
4657 return kMutableKeys::value ? slot->key : slot->value.first;
4658 }
4659
4660 template <class Allocator, class... Args>
4661 static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
4662 emplace(slot);
4663 if (kMutableKeys::value) {
4665 std::forward<Args>(args)...);
4666 } else {
4668 std::forward<Args>(args)...);
4669 }
4670 }
4671
4672 // Construct this slot by moving from another slot.
4673 template <class Allocator>
4674 static void construct(Allocator* alloc, slot_type* slot, slot_type* other) {
4675 emplace(slot);
4676 if (kMutableKeys::value) {
4678 *alloc, &slot->mutable_value, std::move(other->mutable_value));
4679 } else {
4681 std::move(other->value));
4682 }
4683 }
4684
4685 template <class Allocator>
4686 static void destroy(Allocator* alloc, slot_type* slot) {
4687 if (kMutableKeys::value) {
4689 } else {
4691 }
4692 }
4693
4694 template <class Allocator>
4695 static void transfer(Allocator* alloc, slot_type* new_slot,
4696 slot_type* old_slot) {
4697 emplace(new_slot);
4698 if (kMutableKeys::value) {
4700 *alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));
4701 } else {
4703 std::move(old_slot->value));
4704 }
4705 destroy(alloc, old_slot);
4706 }
4707
4708 template <class Allocator>
4709 static void swap(Allocator* alloc, slot_type* a, slot_type* b) {
4710 if (kMutableKeys::value) {
4711 using std::swap;
4712 swap(a->mutable_value, b->mutable_value);
4713 } else {
4714 value_type tmp = std::move(a->value);
4717 std::move(b->value));
4720 std::move(tmp));
4721 }
4722 }
4723
4724 template <class Allocator>
4725 static void move(Allocator* alloc, slot_type* src, slot_type* dest) {
4726 if (kMutableKeys::value) {
4727 dest->mutable_value = std::move(src->mutable_value);
4728 } else {
4731 std::move(src->value));
4732 }
4733 }
4734
4735 template <class Allocator>
4736 static void move(Allocator* alloc, slot_type* first, slot_type* last,
4737 slot_type* result) {
4738 for (slot_type *src = first, *dest = result; src != last; ++src, ++dest)
4739 move(alloc, src, dest);
4740 }
4741};
4742
4743} // namespace priv
4744} // phmap
4745
4746
4747namespace phmap {
4748
4749#ifdef BOOST_THREAD_LOCK_OPTIONS_HPP
4750 using defer_lock_t = boost::defer_lock_t;
4751 using try_to_lock_t = boost::try_to_lock_t;
4752 using adopt_lock_t = boost::adopt_lock_t;
4753#else
4754 struct adopt_lock_t { explicit adopt_lock_t() = default; };
4755 struct defer_lock_t { explicit defer_lock_t() = default; };
4756 struct try_to_lock_t { explicit try_to_lock_t() = default; };
4757#endif
4758
4759// -----------------------------------------------------------------------------
4760// NullMutex
4761// -----------------------------------------------------------------------------
4762// A class that implements the Mutex interface, but does nothing. This is to be
4763// used as a default template parameters for classes who provide optional
4764// internal locking (like phmap::parallel_flat_hash_map).
4765// -----------------------------------------------------------------------------
4767public:
4770 void lock() {}
4771 void unlock() {}
4772 bool try_lock() { return true; }
4773 void lock_shared() {}
4775 bool try_lock_shared() { return true; }
4776};
4777
4778// ------------------------ lockable object used internally -------------------------
4779template <class MutexType>
4781{
4782public:
4783 // ----------------------------------------------------
4785 {
4786 using mutex_type = MutexType;
4787 DoNothing() noexcept {}
4788 explicit DoNothing(mutex_type& ) noexcept {}
4789 explicit DoNothing(mutex_type& , mutex_type&) noexcept {}
4793 template<class T> explicit DoNothing(T&&) {}
4794 DoNothing& operator=(const DoNothing&) { return *this; }
4795 DoNothing& operator=(DoNothing&&) { return *this; }
4796 void swap(DoNothing &) {}
4797 bool owns_lock() const noexcept { return true; }
4798 };
4799
4800 // ----------------------------------------------------
4802 {
4803 public:
4804 using mutex_type = MutexType;
4805
4806 WriteLock() : m_(nullptr), locked_(false) {}
4807
4808 explicit WriteLock(mutex_type &m) : m_(&m) {
4809 m_->lock();
4810 locked_ = true;
4811 }
4812
4814 m_(&m), locked_(true)
4815 {}
4816
4818 m_(&m), locked_(false)
4819 {}
4820
4822 m_(&m), locked_(false) {
4823 m_->try_lock();
4824 }
4825
4827 m_(std::move(o.m_)), locked_(std::move(o.locked_)) {
4828 o.locked_ = false;
4829 o.m_ = nullptr;
4830 }
4831
4833 WriteLock temp(std::move(other));
4834 swap(temp);
4835 return *this;
4836 }
4837
4839 if (locked_)
4840 m_->unlock();
4841 }
4842
4843 void lock() {
4844 if (!locked_) {
4845 m_->lock();
4846 locked_ = true;
4847 }
4848 }
4849
4850 void unlock() {
4851 if (locked_) {
4852 m_->unlock();
4853 locked_ = false;
4854 }
4855 }
4856
4857 bool try_lock() {
4858 if (locked_)
4859 return true;
4860 locked_ = m_->try_lock();
4861 return locked_;
4862 }
4863
4864 bool owns_lock() const noexcept { return locked_; }
4865
4866 void swap(WriteLock &o) noexcept {
4867 std::swap(m_, o.m_);
4868 std::swap(locked_, o.locked_);
4869 }
4870
4871 mutex_type *mutex() const noexcept { return m_; }
4872
4873 private:
4876 };
4877
4878 // ----------------------------------------------------
4880 {
4881 public:
4882 using mutex_type = MutexType;
4883
4884 ReadLock() : m_(nullptr), locked_(false) {}
4885
4886 explicit ReadLock(mutex_type &m) : m_(&m) {
4887 m_->lock_shared();
4888 locked_ = true;
4889 }
4890
4892 m_(&m), locked_(true)
4893 {}
4894
4896 m_(&m), locked_(false)
4897 {}
4898
4900 m_(&m), locked_(false) {
4901 m_->try_lock_shared();
4902 }
4903
4905 m_(std::move(o.m_)), locked_(std::move(o.locked_)) {
4906 o.locked_ = false;
4907 o.m_ = nullptr;
4908 }
4909
4911 ReadLock temp(std::move(other));
4912 swap(temp);
4913 return *this;
4914 }
4915
4917 if (locked_)
4918 m_->unlock_shared();
4919 }
4920
4921 void lock() {
4922 if (!locked_) {
4923 m_->lock_shared();
4924 locked_ = true;
4925 }
4926 }
4927
4928 void unlock() {
4929 if (locked_) {
4930 m_->unlock_shared();
4931 locked_ = false;
4932 }
4933 }
4934
4935 bool try_lock() {
4936 if (locked_)
4937 return true;
4938 locked_ = m_->try_lock_shared();
4939 return locked_;
4940 }
4941
4942 bool owns_lock() const noexcept { return locked_; }
4943
4944 void swap(ReadLock &o) noexcept {
4945 std::swap(m_, o.m_);
4946 std::swap(locked_, o.locked_);
4947 }
4948
4949 mutex_type *mutex() const noexcept { return m_; }
4950
4951 private:
4954 };
4955
4956 // ----------------------------------------------------
4958 {
4959 public:
4960 using mutex_type = MutexType;
4961
4962 explicit WriteLocks(mutex_type& m1, mutex_type& m2) :
4963 _m1(m1), _m2(m2)
4964 {
4965 std::lock(m1, m2);
4966 }
4967
4969 _m1(m1), _m2(m2)
4970 { // adopt means we already own the mutexes
4971 }
4972
4974 {
4975 _m1.unlock();
4976 _m2.unlock();
4977 }
4978
4979 WriteLocks(WriteLocks const&) = delete;
4981 private:
4984 };
4985
4986 // ----------------------------------------------------
4988 {
4989 public:
4990 using mutex_type = MutexType;
4991
4992 explicit ReadLocks(mutex_type& m1, mutex_type& m2) :
4993 _m1(m1), _m2(m2)
4994 {
4995 _m1.lock_shared();
4996 _m2.lock_shared();
4997 }
4998
5000 _m1(m1), _m2(m2)
5001 { // adopt means we already own the mutexes
5002 }
5003
5005 {
5006 _m1.unlock_shared();
5007 _m2.unlock_shared();
5008 }
5009
5010 ReadLocks(ReadLocks const&) = delete;
5011 ReadLocks& operator=(ReadLocks const&) = delete;
5012 private:
5015 };
5016};
5017
5018// ------------------------ holds a mutex ------------------------------------
5019// Default implementation for Lockable, should work fine for std::mutex
5020// -----------------------------------
5021// use as:
5022// using Lockable = phmap::LockableImpl<mutex_type>;
5023// Lockable m;
5024//
5025// Lockable::UpgradeLock read_lock(m); // take a upgradable lock
5026//
5027// {
5028// Lockable::UpgradeToUnique unique_lock(read_lock);
5029// // now locked for write
5030// }
5031//
5032// ---------------------------------------------------------------------------
5033// Generic mutex support (always write locks)
5034// --------------------------------------------------------------------------
5035template <class Mtx_>
5036class LockableImpl : public Mtx_
5037{
5038public:
5039 using mutex_type = Mtx_;
5041 using SharedLock = typename Base::WriteLock;
5043 using UniqueLock = typename Base::WriteLock;
5046 using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
5047};
5048
5049// ---------------------------------------------------------------------------
5050// Null mutex (no-op) - when we don't want internal synchronization
5051// ---------------------------------------------------------------------------
5052template <>
5065
5066// --------------------------------------------------------------------------
5067// Abseil Mutex support (read and write lock support)
5068// --------------------------------------------------------------------------
5069#ifdef ABSL_SYNCHRONIZATION_MUTEX_H_
5070
5071 struct AbslMutex : protected absl::Mutex
5072 {
5073 void lock() { this->Lock(); }
5074 void unlock() { this->Unlock(); }
5075 void try_lock() { this->TryLock(); }
5076 void lock_shared() { this->ReaderLock(); }
5077 void unlock_shared() { this->ReaderUnlock(); }
5078 void try_lock_shared() { this->ReaderTryLock(); }
5079 };
5080
5081 template <>
5082 class LockableImpl<absl::Mutex> : public AbslMutex
5083 {
5084 public:
5085 using mutex_type = phmap::AbslMutex;
5086 using Base = LockableBaseImpl<phmap::AbslMutex>;
5087 using SharedLock = typename Base::ReadLock;
5088 using UpgradeLock = typename Base::WriteLock;
5089 using UniqueLock = typename Base::WriteLock;
5090 using SharedLocks = typename Base::ReadLocks;
5091 using UniqueLocks = typename Base::WriteLocks;
5092 using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
5093 };
5094
5095#endif
5096
5097// --------------------------------------------------------------------------
5098// Boost shared_mutex support (read and write lock support)
5099// --------------------------------------------------------------------------
5100#ifdef BOOST_THREAD_SHARED_MUTEX_HPP
5101
5102#if 1
5103 // ---------------------------------------------------------------------------
5104 template <>
5105 class LockableImpl<boost::shared_mutex> : public boost::shared_mutex
5106 {
5107 public:
5108 using mutex_type = boost::shared_mutex;
5109 using Base = LockableBaseImpl<boost::shared_mutex>;
5110 using SharedLock = boost::shared_lock<mutex_type>;
5111 using UpgradeLock = boost::unique_lock<mutex_type>; // assume can't upgrade
5112 using UniqueLock = boost::unique_lock<mutex_type>;
5113 using SharedLocks = typename Base::ReadLocks;
5114 using UniqueLocks = typename Base::WriteLocks;
5115 using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
5116 };
5117#else
5118 // ---------------------------------------------------------------------------
5119 template <>
5120 class LockableImpl<boost::upgrade_mutex> : public boost::upgrade_mutex
5121 {
5122 public:
5123 using mutex_type = boost::upgrade_mutex;
5124 using SharedLock = boost::shared_lock<mutex_type>;
5125 using UpgradeLock = boost::upgrade_lock<mutex_type>;
5126 using UniqueLock = boost::unique_lock<mutex_type>;
5127 using SharedLocks = typename Base::ReadLocks;
5128 using UniqueLocks = typename Base::WriteLocks;
5129 using UpgradeToUnique = boost::upgrade_to_unique_lock<mutex_type>;
5130 };
5131#endif
5132
5133#endif // BOOST_THREAD_SHARED_MUTEX_HPP
5134
5135// --------------------------------------------------------------------------
5136// std::shared_mutex support (read and write lock support)
5137// --------------------------------------------------------------------------
5138#ifdef PHMAP_HAVE_SHARED_MUTEX
5139
5140 // ---------------------------------------------------------------------------
5141 template <>
5142 class LockableImpl<std::shared_mutex> : public std::shared_mutex
5143 {
5144 public:
5145 using mutex_type = std::shared_mutex;
5146 using Base = LockableBaseImpl<std::shared_mutex>;
5147 using SharedLock = std::shared_lock<mutex_type>;
5148 using UpgradeLock = std::unique_lock<mutex_type>; // assume can't upgrade
5149 using UniqueLock = std::unique_lock<mutex_type>;
5150 using SharedLocks = typename Base::ReadLocks;
5151 using UniqueLocks = typename Base::WriteLocks;
5152 using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
5153 };
5154#endif // PHMAP_HAVE_SHARED_MUTEX
5155
5156
5157} // phmap
5158
5159#ifdef _MSC_VER
5160 #pragma warning(pop)
5161#endif
5162
5163
5164#endif // phmap_base_h_guard_
Definition phmap_base.h:4880
ReadLock(mutex_type &m)
Definition phmap_base.h:4886
bool locked_
Definition phmap_base.h:4953
mutex_type * mutex() const noexcept
Definition phmap_base.h:4949
ReadLock & operator=(ReadLock &&other)
Definition phmap_base.h:4910
ReadLock()
Definition phmap_base.h:4884
ReadLock(mutex_type &m, defer_lock_t) noexcept
Definition phmap_base.h:4895
~ReadLock()
Definition phmap_base.h:4916
ReadLock(mutex_type &m, adopt_lock_t) noexcept
Definition phmap_base.h:4891
bool try_lock()
Definition phmap_base.h:4935
void swap(ReadLock &o) noexcept
Definition phmap_base.h:4944
void unlock()
Definition phmap_base.h:4928
void lock()
Definition phmap_base.h:4921
ReadLock(mutex_type &m, try_to_lock_t)
Definition phmap_base.h:4899
ReadLock(ReadLock &&o)
Definition phmap_base.h:4904
mutex_type * m_
Definition phmap_base.h:4952
MutexType mutex_type
Definition phmap_base.h:4882
bool owns_lock() const noexcept
Definition phmap_base.h:4942
Definition phmap_base.h:4988
MutexType mutex_type
Definition phmap_base.h:4990
~ReadLocks()
Definition phmap_base.h:5004
ReadLocks(ReadLocks const &)=delete
ReadLocks(adopt_lock_t, mutex_type &m1, mutex_type &m2)
Definition phmap_base.h:4999
ReadLocks & operator=(ReadLocks const &)=delete
mutex_type & _m2
Definition phmap_base.h:5014
mutex_type & _m1
Definition phmap_base.h:5013
ReadLocks(mutex_type &m1, mutex_type &m2)
Definition phmap_base.h:4992
Definition phmap_base.h:4802
bool owns_lock() const noexcept
Definition phmap_base.h:4864
void swap(WriteLock &o) noexcept
Definition phmap_base.h:4866
WriteLock(mutex_type &m, defer_lock_t) noexcept
Definition phmap_base.h:4817
bool try_lock()
Definition phmap_base.h:4857
WriteLock()
Definition phmap_base.h:4806
bool locked_
Definition phmap_base.h:4875
WriteLock(mutex_type &m, adopt_lock_t) noexcept
Definition phmap_base.h:4813
WriteLock & operator=(WriteLock &&other)
Definition phmap_base.h:4832
WriteLock(WriteLock &&o)
Definition phmap_base.h:4826
void unlock()
Definition phmap_base.h:4850
mutex_type * m_
Definition phmap_base.h:4874
WriteLock(mutex_type &m, try_to_lock_t)
Definition phmap_base.h:4821
MutexType mutex_type
Definition phmap_base.h:4804
void lock()
Definition phmap_base.h:4843
mutex_type * mutex() const noexcept
Definition phmap_base.h:4871
~WriteLock()
Definition phmap_base.h:4838
WriteLock(mutex_type &m)
Definition phmap_base.h:4808
Definition phmap_base.h:4958
WriteLocks(adopt_lock_t, mutex_type &m1, mutex_type &m2)
Definition phmap_base.h:4968
mutex_type & _m1
Definition phmap_base.h:4982
MutexType mutex_type
Definition phmap_base.h:4960
WriteLocks(mutex_type &m1, mutex_type &m2)
Definition phmap_base.h:4962
~WriteLocks()
Definition phmap_base.h:4973
WriteLocks(WriteLocks const &)=delete
WriteLocks & operator=(WriteLocks const &)=delete
mutex_type & _m2
Definition phmap_base.h:4983
Definition phmap_base.h:4781
typename Base::DoNothing UpgradeToUnique
Definition phmap_base.h:5061
typename Base::DoNothing UniqueLocks
Definition phmap_base.h:5063
typename Base::DoNothing UniqueLock
Definition phmap_base.h:5060
typename Base::DoNothing UpgradeLock
Definition phmap_base.h:5059
typename Base::DoNothing SharedLock
Definition phmap_base.h:5058
typename Base::DoNothing SharedLocks
Definition phmap_base.h:5062
Definition phmap_base.h:5037
typename Base::WriteLock UpgradeLock
Definition phmap_base.h:5042
typename Base::WriteLock SharedLock
Definition phmap_base.h:5041
typename Base::DoNothing UpgradeToUnique
Definition phmap_base.h:5046
typename Base::WriteLocks UniqueLocks
Definition phmap_base.h:5045
typename Base::WriteLocks SharedLocks
Definition phmap_base.h:5044
Mtx_ mutex_type
Definition phmap_base.h:5039
typename Base::WriteLock UniqueLock
Definition phmap_base.h:5043
Definition phmap_base.h:4766
~NullMutex()
Definition phmap_base.h:4769
void unlock_shared()
Definition phmap_base.h:4774
NullMutex()
Definition phmap_base.h:4768
void unlock()
Definition phmap_base.h:4771
void lock_shared()
Definition phmap_base.h:4773
bool try_lock_shared()
Definition phmap_base.h:4775
void lock()
Definition phmap_base.h:4770
bool try_lock()
Definition phmap_base.h:4772
Definition phmap_base.h:3111
constexpr pointer data() const noexcept
Definition phmap_base.h:3214
constexpr Span(pointer array, size_type lgth) noexcept
Definition phmap_base.h:3146
constexpr Span subspan(size_type pos=0, size_type len=npos) const
Definition phmap_base.h:3343
pointer iterator
Definition phmap_base.h:3136
static const size_type npos
Definition phmap_base.h:3143
constexpr size_type length() const noexcept
Definition phmap_base.h:3224
std::reverse_iterator< iterator > reverse_iterator
Definition phmap_base.h:3138
ptrdiff_t difference_type
Definition phmap_base.h:3141
constexpr reference back() const noexcept
Definition phmap_base.h:3260
const T & const_reference
Definition phmap_base.h:3135
T * pointer
Definition phmap_base.h:3132
constexpr iterator begin() const noexcept
Definition phmap_base.h:3267
constexpr bool empty() const noexcept
Definition phmap_base.h:3229
constexpr Span(const V &v) noexcept
Definition phmap_base.h:3164
constexpr const_reverse_iterator crbegin() const noexcept
Definition phmap_base.h:3294
Span(std::initializer_list< value_type > v) noexcept
Definition phmap_base.h:3204
constexpr const_reverse_iterator crend() const noexcept
Definition phmap_base.h:3306
phmap::remove_cv_t< T > value_type
Definition phmap_base.h:3131
typename std::enable_if< span_internal::HasData< T, C >::value && span_internal::HasSize< C >::value >::type EnableIfConvertibleFrom
Definition phmap_base.h:3116
constexpr Span first(size_type len) const
Definition phmap_base.h:3360
const_pointer const_iterator
Definition phmap_base.h:3137
constexpr reference operator[](size_type i) const noexcept
Definition phmap_base.h:3234
constexpr reference front() const noexcept
Definition phmap_base.h:3253
constexpr Span() noexcept
Definition phmap_base.h:3145
void remove_prefix(size_type n) noexcept
Definition phmap_base.h:3313
typename std::enable_if< std::is_const< T >::value, U >::type EnableIfConstView
Definition phmap_base.h:3122
typename std::enable_if<!std::is_const< T >::value, U >::type EnableIfMutableView
Definition phmap_base.h:3127
const T * const_pointer
Definition phmap_base.h:3133
constexpr iterator end() const noexcept
Definition phmap_base.h:3277
T & reference
Definition phmap_base.h:3134
Span(V &v) noexcept
Definition phmap_base.h:3158
size_type len_
Definition phmap_base.h:3392
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition phmap_base.h:3139
size_t size_type
Definition phmap_base.h:3140
constexpr reverse_iterator rend() const noexcept
Definition phmap_base.h:3299
pointer ptr_
Definition phmap_base.h:3391
constexpr const_iterator cend() const noexcept
Definition phmap_base.h:3282
constexpr reverse_iterator rbegin() const noexcept
Definition phmap_base.h:3287
constexpr Span last(size_type len) const
Definition phmap_base.h:3377
constexpr size_type size() const noexcept
Definition phmap_base.h:3219
constexpr reference at(size_type i) const
Definition phmap_base.h:3242
friend H AbslHashValue(H h, Span v)
Definition phmap_base.h:3385
constexpr Span(T(&a)[N]) noexcept
Definition phmap_base.h:3151
constexpr const_iterator cbegin() const noexcept
Definition phmap_base.h:3272
void remove_suffix(size_type n) noexcept
Definition phmap_base.h:3322
Definition phmap_base.h:1684
const char * what() const noexcept override
optional_assign_base & operator=(const optional_assign_base &)=default
optional_assign_base & operator=(optional_assign_base &&)=default
optional_assign_base & operator=(const optional_assign_base &)=delete
optional_assign_base & operator=(optional_assign_base &&)=default
optional_assign_base & operator=(optional_assign_base &&)=delete
optional_assign_base & operator=(const optional_assign_base &)=delete
optional_ctor_base & operator=(optional_ctor_base &&)=default
optional_ctor_base & operator=(const optional_ctor_base &)=default
optional_ctor_base & operator=(optional_ctor_base &&)=default
optional_ctor_base & operator=(const optional_ctor_base &)=default
optional_ctor_base & operator=(const optional_ctor_base &)=default
optional_ctor_base & operator=(optional_ctor_base &&)=default
optional_data(optional_data &&rhs) noexcept(phmap::default_allocator_is_nothrow::value||std::is_nothrow_move_constructible< T >::value)
Definition phmap_base.h:1859
optional_data & operator=(optional_data &&rhs) noexcept(std::is_nothrow_move_assignable< T >::value &&std::is_nothrow_move_constructible< T >::value)
Definition phmap_base.h:1877
optional_data(const optional_data &rhs)
Definition phmap_base.h:1853
optional_data & operator=(const optional_data &rhs)
Definition phmap_base.h:1868
constexpr optional_data(in_place_t t, Args &&... args)
Definition phmap_base.h:1847
constexpr optional_data(in_place_t t, Args &&... args)
Definition phmap_base.h:1834
void construct(Args &&... args)
Definition phmap_base.h:1795
void assign(U &&u)
Definition phmap_base.h:1802
constexpr optional_data_base(in_place_t t, Args &&... args)
Definition phmap_base.h:1790
void destruct() noexcept
Definition phmap_base.h:1769
constexpr optional_data_dtor_base() noexcept
Definition phmap_base.h:1772
constexpr optional_data_dtor_base(in_place_t, Args &&... args)
Definition phmap_base.h:1775
constexpr optional_data_dtor_base(in_place_t, Args &&... args)
Definition phmap_base.h:1745
~optional_data_dtor_base()
Definition phmap_base.h:1748
dummy_type dummy_
Definition phmap_base.h:1730
bool engaged_
Definition phmap_base.h:1727
constexpr optional_data_dtor_base() noexcept
Definition phmap_base.h:1742
void destruct() noexcept
Definition phmap_base.h:1734
Definition phmap_base.h:1821
Definition phmap_base.h:2058
T & value() &
Definition phmap_base.h:2411
constexpr optional() noexcept
Definition phmap_base.h:2068
const T * operator->() const
Definition phmap_base.h:2350
optional & operator=(nullopt_t) noexcept
Definition phmap_base.h:2208
T & emplace(std::initializer_list< U > il, Args &&... args)
Definition phmap_base.h:2312
constexpr T value_or(U &&v) const &
Definition phmap_base.h:2437
constexpr optional(InPlaceT, Args &&... args)
Definition phmap_base.h:2087
T && operator*() &&
Definition phmap_base.h:2371
constexpr const T && operator*() const &&
Definition phmap_base.h:2368
void swap(optional &rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&std::is_trivial< T >::value)
Definition phmap_base.h:2321
optional & operator=(optional< U > &&rhs)
Definition phmap_base.h:2260
T value_type
Definition phmap_base.h:2062
~optional()=default
T & reference()
Definition phmap_base.h:2459
optional & operator=(optional &&src)=default
constexpr const T && value() const &&
Definition phmap_base.h:2422
optional & operator=(const optional &src)=default
T && value() &&
Definition phmap_base.h:2416
T & operator*() &
Definition phmap_base.h:2364
constexpr const T & operator*() const &
Definition phmap_base.h:2363
PHMAP_ATTRIBUTE_REINITIALIZES void reset() noexcept
Definition phmap_base.h:2274
optional(const optional< U > &rhs)
Definition phmap_base.h:2140
constexpr optional(nullopt_t) noexcept
Definition phmap_base.h:2071
optional & operator=(U &&v)
Definition phmap_base.h:2229
optional(optional< U > &&rhs)
Definition phmap_base.h:2174
T & emplace(Args &&... args)
Definition phmap_base.h:2292
T * operator->()
Definition phmap_base.h:2354
constexpr bool has_value() const noexcept
Definition phmap_base.h:2392
constexpr const T & value() const &
Definition phmap_base.h:2406
T value_or(U &&v) &&
Definition phmap_base.h:2447
constexpr const T & reference() const
Definition phmap_base.h:2458
optional(const optional &src)=default
optional & operator=(const optional< U > &rhs)
Definition phmap_base.h:2243
constexpr optional(in_place_t, std::initializer_list< U > il, Args &&... args)
Definition phmap_base.h:2097
optional(optional &&src)=default
constexpr optional(U &&v)
Definition phmap_base.h:2113
Definition phmap_base.h:4286
constexpr const ElemT< I > & get() const &
Definition phmap_base.h:4302
constexpr CompressedTuple(Ts... base)
Definition phmap_base.h:4293
constexpr const ElemT< I > && get() const &&
Definition phmap_base.h:4313
ElemT< I > && get() &&
Definition phmap_base.h:4307
internal_compressed_tuple::ElemT< CompressedTuple, I > ElemT
Definition phmap_base.h:4289
ElemT< I > & get() &
Definition phmap_base.h:4297
constexpr CompressedTuple()=default
Definition phmap_base.h:4129
static constexpr PartialType< sizeof...(Sizes)> Partial(Sizes &&... sizes)
Definition phmap_base.h:4140
constexpr Layout(internal_layout::TypeToSize< Ts >... sizes)
Definition phmap_base.h:4153
std::tuple< SliceType< CopyConst< Char, typename std::tuple_element< SizeSeq, ElementTypes >::type > >... > Slices(Char *p) const
Definition phmap_base.h:4059
std::tuple< CopyConst< Char, typename std::tuple_element< OffsetSeq, ElementTypes >::type > *... > Pointers(Char *p) const
Definition phmap_base.h:4001
Definition phmap_base.h:3801
auto key() const -> decltype(PolicyTraits::key(this->slot()))
Definition phmap_base.h:2867
Definition phmap_base.h:2749
phmap::optional< allocator_type > alloc_
Definition phmap_base.h:2820
allocator_type * alloc()
Definition phmap_base.h:2817
node_handle_base(node_handle_base &&other) noexcept
Definition phmap_base.h:2758
typename PolicyTraits::slot_type slot_type
Definition phmap_base.h:2751
allocator_type get_allocator() const
Definition phmap_base.h:2776
constexpr node_handle_base()
Definition phmap_base.h:2756
node_handle_base(const allocator_type &a, slot_type *s)
Definition phmap_base.h:2793
~node_handle_base()
Definition phmap_base.h:2762
Alloc allocator_type
Definition phmap_base.h:2754
node_handle_base(move_tag_t, const allocator_type &a, slot_type *s)
Definition phmap_base.h:2788
node_handle_base(transfer_tag_t, const allocator_type &a, slot_type *s)
Definition phmap_base.h:2782
bool empty() const noexcept
Definition phmap_base.h:2774
void destroy()
Definition phmap_base.h:2800
node_handle_base & operator=(node_handle_base &&other) noexcept
Definition phmap_base.h:2764
void reset()
Definition phmap_base.h:2807
phmap::aligned_storage_t< sizeof(slot_type), alignof(slot_type)> slot_space_
Definition phmap_base.h:2821
slot_type * slot() const
Definition phmap_base.h:2812
Definition phmap_base.h:2833
value_type & key() const
Definition phmap_base.h:2843
constexpr node_handle()
Definition phmap_base.h:2839
value_type & value() const
Definition phmap_base.h:2841
typename PolicyTraits::value_type value_type
Definition phmap_base.h:2837
static void ThrowStdRuntimeError(const std::string &what_arg)
Definition phmap_base.h:701
static void ThrowStdInvalidArgument(const std::string &what_arg)
Definition phmap_base.h:673
static void ThrowStdRangeError(const std::string &what_arg)
Definition phmap_base.h:708
static void ThrowStdOverflowError(const std::string &what_arg)
Definition phmap_base.h:715
static void ThrowStdDomainError(const std::string &what_arg)
Definition phmap_base.h:680
static void ThrowStdLengthError(const std::string &what_arg)
Definition phmap_base.h:687
static void ThrowStdUnderflowError(const std::string &what_arg)
Definition phmap_base.h:722
static void ThrowStdLogicError(const std::string &what_arg)
Definition phmap_base.h:667
InvokeT< F, Args... > Invoke(F &&f, Args &&... args)
Definition phmap_base.h:873
decltype(Invoker< F, Args... >::type::Invoke( std::declval< F >(), std::declval< Args >()...)) InvokeT
Definition phmap_base.h:867
static void ThrowStdBadAlloc()
Definition phmap_base.h:731
static void ThrowStdBadFunctionCall()
Definition phmap_base.h:729
static void ThrowStdOutOfRange(const std::string &what_arg)
Definition phmap_base.h:694
typename identity< T >::type identity_t
Definition phmap_base.h:601
constexpr bool HasRebindAlloc(...)
Definition phmap_base.h:1301
typename T::void_pointer GetVoidPointer
Definition phmap_base.h:1238
typename T::pointer GetPointer
Definition phmap_base.h:1232
void CopyRange(Allocator &alloc, Iterator destination, InputIterator first, InputIterator last)
Definition phmap_base.h:1630
typename T::propagate_on_container_copy_assignment GetPropagateOnContainerCopyAssignment
Definition phmap_base.h:1250
void ConstructRange(Allocator &alloc, Iterator first, Iterator last, const Args &... args)
Definition phmap_base.h:1611
typename T::const_void_pointer GetConstVoidPointer
Definition phmap_base.h:1241
typename T::const_pointer GetConstPointer
Definition phmap_base.h:1235
typename T::propagate_on_container_swap GetPropagateOnContainerSwap
Definition phmap_base.h:1258
typename T::size_type GetSizeType
Definition phmap_base.h:1247
typename T::propagate_on_container_move_assignment GetPropagateOnContainerMoveAssignment
Definition phmap_base.h:1254
typename T::is_always_equal GetIsAlwaysEqual
Definition phmap_base.h:1261
typename Alloc::is_nothrow GetIsNothrow
Definition phmap_base.h:1573
typename ExtractOr< Extract, Obj, Default, void >::type ExtractOrT
Definition phmap_base.h:1228
typename T::difference_type GetDifferenceType
Definition phmap_base.h:1244
constexpr copy_traits get_ctor_copy_traits()
Definition phmap_base.h:1968
constexpr copy_traits get_assign_copy_traits()
Definition phmap_base.h:1977
bool convertible_to_bool(bool)
copy_traits
Definition phmap_base.h:1891
constexpr bool ShouldUseBase()
Definition phmap_base.h:4204
constexpr bool IsFinal()
Definition phmap_base.h:4195
typename Elem< D, I >::type ElemT
Definition phmap_base.h:4186
struct PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl
Definition phmap_base.h:4245
constexpr bool IsPow2(size_t n)
Definition phmap_base.h:3771
constexpr size_t Max(size_t a)
Definition phmap_base.h:3779
constexpr size_t Align(size_t n, size_t m)
Definition phmap_base.h:3775
constexpr size_t Min(size_t a, size_t b)
Definition phmap_base.h:3777
constexpr size_t Find(Needle, Needle, Ts...)
Definition phmap_base.h:3761
typename std::enable_if< C, int >::type EnableIf
Definition phmap_base.h:3789
typename std::conditional< std::is_const< From >::value, const To, To >::type CopyConst
Definition phmap_base.h:3748
size_t TypeToSize
Definition phmap_base.h:3712
size_t IntToSize
Definition phmap_base.h:3709
std::integral_constant< bool, !std::is_reference< T >::value &&!std::is_volatile< T >::value && !std::is_reference< typename Type< T >::type >::value && !std::is_volatile< typename Type< T >::type >::value && adl_barrier::IsPow2(AlignOf< T >::value)> IsLegalElementType
Definition phmap_base.h:3794
void Deallocate(Alloc *alloc, void *p, size_t n)
Definition phmap_base.h:4367
typename phmap::Pair< T1, T2 > Pair
Definition phmap_fwd_decl.h:65
void SanitizerPoisonObject(const T *object)
Definition phmap_base.h:4407
void * Allocate(Alloc *alloc, size_t n)
Definition phmap_base.h:4349
void SanitizerUnpoisonObject(const T *object)
Definition phmap_base.h:4412
typename phmap::Allocator< T > Allocator
Definition phmap_fwd_decl.h:61
void SanitizerPoisonMemoryRegion(const void *m, size_t s)
Definition phmap_base.h:4384
void SanitizerUnpoisonMemoryRegion(const void *m, size_t s)
Definition phmap_base.h:4395
bool LessThanImpl(Span< T > a, Span< T > b)
Definition phmap_base.h:3005
constexpr size_t Min(size_t a, size_t b) noexcept
Definition phmap_base.h:2943
typename std::enable_if< IsConvertible< From, Span< const To > >::value >::type EnableIfConvertibleToSpanConst
Definition phmap_base.h:3028
bool EqualImpl(Span< T > a, Span< T > b)
Definition phmap_base.h:2999
std::is_integral< phmap::decay_t< decltype(std::declval< C & >().size())> > HasSize
Definition phmap_base.h:2966
typename ElementType< C >::type ElementT
Definition phmap_base.h:2992
constexpr auto GetDataImpl(C &c, char) noexcept -> decltype(c.data())
Definition phmap_base.h:2947
constexpr auto GetData(C &c) noexcept -> decltype(GetDataImpl(c, 0))
Definition phmap_base.h:2959
typename std::enable_if<!std::is_const< T >::value, int >::type EnableIfMutable
Definition phmap_base.h:2995
std::is_convertible< phmap::decay_t< decltype(GetData(std::declval< C & >()))> *, T *const * > HasData
Definition phmap_base.h:2976
const T & ts_unchecked_read(const T &v) PHMAP_NO_THREAD_SAFETY_ANALYSIS
Definition phmap_base.h:4519
decltype(std::declval< T & >()=std::declval< T && >()) IsMoveAssignableImpl
Definition phmap_base.h:157
decltype(std::declval< T & >()=std::declval< const T & >()) IsCopyAssignableImpl
Definition phmap_base.h:153
void AssertHashEnabled()
Definition phmap_base.h:405
auto apply_helper(Functor &&functor, Tuple &&t, index_sequence< Indexes... >) -> decltype(phmap::base_internal::Invoke(phmap::forward< Functor >(functor), std::get< Indexes >(phmap::forward< Tuple >(t))...))
Definition phmap_base.h:1046
Definition btree.h:77
typename std::add_volatile< T >::type add_volatile_t
Definition phmap_base.h:282
typename std::remove_const< T >::type remove_const_t
Definition phmap_base.h:270
typename std::remove_volatile< T >::type remove_volatile_t
Definition phmap_base.h:273
typename std::decay< T >::type decay_t
Definition phmap_base.h:316
auto apply(Functor &&functor, Tuple &&t) -> decltype(utility_internal::apply_helper(phmap::forward< Functor >(functor), phmap::forward< Tuple >(t), phmap::make_index_sequence< std::tuple_size< typename std::remove_reference< Tuple >::type >::value >{}))
Definition phmap_base.h:1097
auto RawPtr(T &&ptr) -> decltype(std::addressof(*ptr))
Definition phmap_base.h:1195
constexpr T && forward(phmap::remove_reference_t< T > &t) noexcept
Definition phmap_base.h:1038
typename std::allocator< T > Allocator
Definition phmap_base.h:70
typename std::underlying_type< T >::type underlying_type_t
Definition phmap_base.h:329
typename std::aligned_storage< Len, Align >::type aligned_storage_t
Definition phmap_base.h:313
typename std::remove_cv< T >::type remove_cv_t
Definition phmap_base.h:267
std::shared_ptr< T > ShareUniquePtr(std::unique_ptr< T, D > &&ptr)
Definition phmap_base.h:1204
constexpr auto operator<=(const optional< T > &x, const optional< U > &y) -> decltype(optional_internal::convertible_to_bool(*x<= *y))
Definition phmap_base.h:2568
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition btree.h:134
T exchange(T &obj, U &&new_value)
Definition phmap_base.h:1127
constexpr Span< T > MakeSpan(T *ptr, size_t size) noexcept
Definition phmap_base.h:3617
typename std::common_type< T... >::type common_type_t
Definition phmap_base.h:326
typename std::add_const< T >::type add_const_t
Definition phmap_base.h:279
std::unique_ptr< T > WrapUnique(T *ptr)
Definition phmap_base.h:1148
typename std::remove_extent< T >::type remove_extent_t
Definition phmap_base.h:306
constexpr Span< const T > MakeConstSpan(T *ptr, size_t size) noexcept
Definition phmap_base.h:3662
typename std::pair< T1, T2 > Pair
Definition phmap_base.h:72
typename std::add_pointer< T >::type add_pointer_t
Definition phmap_base.h:297
void swap(btree_set< K, C, A > &x, btree_set< K, C, A > &y)
Definition btree.h:3882
constexpr nullopt_t nullopt(nullopt_t::init)
memory_internal::MakeUniqueResult< T >::scalar make_unique(Args &&... args)
Definition phmap_base.h:1179
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition phmap_base.h:958
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition phmap_base.h:974
constexpr phmap::remove_reference_t< T > && move(T &&t) noexcept
Definition phmap_base.h:1029
typename std::remove_pointer< T >::type remove_pointer_t
Definition phmap_base.h:294
std::weak_ptr< T > WeakenPtr(const std::shared_ptr< T > &ptr)
Definition phmap_base.h:1209
typename std::make_signed< T >::type make_signed_t
Definition phmap_base.h:300
typename std::enable_if< B, T >::type enable_if_t
Definition phmap_base.h:319
typename std::add_rvalue_reference< T >::type add_rvalue_reference_t
Definition phmap_base.h:291
typename std::add_lvalue_reference< T >::type add_lvalue_reference_t
Definition phmap_base.h:288
constexpr auto operator!=(const optional< T > &x, const optional< U > &y) -> decltype(optional_internal::convertible_to_bool(*x != *y))
Definition phmap_base.h:2547
constexpr optional< typename std::decay< T >::type > make_optional(T &&v)
Definition phmap_base.h:2505
constexpr auto operator==(const optional< T > &x, const optional< U > &y) -> decltype(optional_internal::convertible_to_bool(*x== *y))
Definition phmap_base.h:2536
typename std::result_of< F(ArgTypes...)>::type invoke_result_t
Definition phmap_base.h:335
typename std::remove_all_extents< T >::type remove_all_extents_t
Definition phmap_base.h:309
typename std::make_unsigned< T >::type make_unsigned_t
Definition phmap_base.h:303
typename std::conditional< B, T, F >::type conditional_t
Definition phmap_base.h:322
constexpr auto operator>(const optional< T > &x, const optional< U > &y) -> decltype(optional_internal::convertible_to_bool(*x > *y))
Definition phmap_base.h:2562
constexpr auto operator<(const optional< T > &x, const optional< U > &y) -> decltype(optional_internal::convertible_to_bool(*x< *y))
Definition phmap_base.h:2556
make_integer_sequence< size_t, N > make_index_sequence
Definition phmap_base.h:966
constexpr auto operator>=(const optional< T > &x, const optional< U > &y) -> decltype(optional_internal::convertible_to_bool(*x >= *y))
Definition phmap_base.h:2574
typename std::remove_reference< T >::type remove_reference_t
Definition phmap_base.h:285
typename std::add_cv< T >::type add_cv_t
Definition phmap_base.h:276
STL namespace
#define PHMAP_INTERNAL_INLINE_CONSTEXPR(var_type, name, init)
Definition phmap_base.h:631
#define PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
Definition phmap_base.h:4169
#define PHMAP_NO_THREAD_SAFETY_ANALYSIS
Definition phmap_base.h:4478
#define PHMAP_PREDICT_TRUE(x)
Definition phmap_bits.h:252
#define PHMAP_ASSERT(expr)
Definition phmap_config.h:773
#define PHMAP_INTERNAL_CATCH_ANY
Definition phmap_config.h:780
#define PHMAP_INTERNAL_TRY
Definition phmap_config.h:779
#define PHMAP_ATTRIBUTE_REINITIALIZES
Definition phmap_config.h:604
#define PHMAP_INTERNAL_RETHROW
Definition phmap_config.h:781
#define true
Definition stdbool.h:30
#define false
Definition stdbool.h:33
unsigned char bool
Definition stdbool.h:25
Definition phmap_base.h:76
bool operator()(const T &a, const T &b) const
Definition phmap_base.h:77
Definition phmap_base.h:85
bool operator()(const T &a, const T &b) const
Definition phmap_base.h:86
Definition phmap_base.h:4785
DoNothing(T &&)
Definition phmap_base.h:4793
void swap(DoNothing &)
Definition phmap_base.h:4796
DoNothing(mutex_type &, mutex_type &) noexcept
Definition phmap_base.h:4789
DoNothing(mutex_type &) noexcept
Definition phmap_base.h:4788
DoNothing(mutex_type &, phmap::defer_lock_t) noexcept
Definition phmap_base.h:4791
DoNothing() noexcept
Definition phmap_base.h:4787
DoNothing(mutex_type &, phmap::adopt_lock_t) noexcept
Definition phmap_base.h:4790
DoNothing(mutex_type &, phmap::try_to_lock_t)
Definition phmap_base.h:4792
DoNothing & operator=(DoNothing &&)
Definition phmap_base.h:4795
MutexType mutex_type
Definition phmap_base.h:4786
bool owns_lock() const noexcept
Definition phmap_base.h:4797
DoNothing & operator=(const DoNothing &)
Definition phmap_base.h:4794
Definition phmap_base.h:4754
adopt_lock_t()=default
Definition phmap_base.h:1599
Definition phmap_base.h:1379
typename memory_internal::RebindAlloc< Alloc, T >::type rebind_alloc
Definition phmap_base.h:1457
typename Alloc::value_type value_type
Definition phmap_base.h:1384
static size_type max_size(const Alloc &a)
Definition phmap_base.h:1506
static auto max_size_impl(int, const A &a) -> decltype(a.max_size())
Definition phmap_base.h:1550
static auto destroy_impl(int, A &a, T *p) -> decltype(std::allocator_traits< A >::destroy(a, p))
Definition phmap_base.h:1540
memory_internal::ExtractOrT< memory_internal::GetVoidPointer, Alloc, typename phmap::pointer_traits< pointer >::template rebind< void > > void_pointer
Definition phmap_base.h:1402
static void construct(Alloc &a, T *p, Args &&... args)
Definition phmap_base.h:1491
memory_internal::ExtractOrT< memory_internal::GetPropagateOnContainerCopyAssignment, Alloc, std::false_type > propagate_on_container_copy_assignment
Definition phmap_base.h:1430
static void construct_impl(char, Alloc &, T *p, Args &&... args)
Definition phmap_base.h:1535
memory_internal::ExtractOrT< memory_internal::GetPropagateOnContainerMoveAssignment, Alloc, std::false_type > propagate_on_container_move_assignment
Definition phmap_base.h:1437
memory_internal::ExtractOrT< memory_internal::GetSizeType, Alloc, typename std::make_unsigned< difference_type >::type > size_type
Definition phmap_base.h:1423
static auto allocate_impl(int, A &a, size_type n, const_void_pointer hint) -> decltype(a.allocate(n, hint))
Definition phmap_base.h:1517
static auto construct_impl(int, A &a, Args &&... args) -> decltype(std::allocator_traits< A >::construct(a, std::forward< Args >(args)...))
Definition phmap_base.h:1528
static void destroy_impl(char, Alloc &, T *p)
Definition phmap_base.h:1545
memory_internal::ExtractOrT< memory_internal::GetDifferenceType, Alloc, typename phmap::pointer_traits< pointer >::difference_type > difference_type
Definition phmap_base.h:1416
static size_type max_size_impl(char, const Alloc &)
Definition phmap_base.h:1553
memory_internal::ExtractOrT< memory_internal::GetPropagateOnContainerSwap, Alloc, std::false_type > propagate_on_container_swap
Definition phmap_base.h:1443
memory_internal::ExtractOrT< memory_internal::GetConstVoidPointer, Alloc, typename phmap::pointer_traits< pointer >::template rebind< const void > > const_void_pointer
Definition phmap_base.h:1409
static void destroy(Alloc &a, T *p)
Definition phmap_base.h:1499
static pointer allocate_impl(char, Alloc &a, size_type n, const_void_pointer)
Definition phmap_base.h:1522
static Alloc select_on_container_copy_construction_impl(char, const Alloc &a)
Definition phmap_base.h:1562
Alloc allocator_type
Definition phmap_base.h:1380
static auto select_on_container_copy_construction_impl(int, const A &a) -> decltype(a.select_on_container_copy_construction())
Definition phmap_base.h:1558
static pointer allocate(Alloc &a, size_type n, const_void_pointer hint)
Definition phmap_base.h:1474
static void deallocate(Alloc &a, pointer p, size_type n)
Definition phmap_base.h:1481
static Alloc select_on_container_copy_construction(const Alloc &a)
Definition phmap_base.h:1511
memory_internal::ExtractOrT< memory_internal::GetIsAlwaysEqual, Alloc, typename std::is_empty< Alloc >::type > is_always_equal
Definition phmap_base.h:1449
memory_internal::ExtractOrT< memory_internal::GetConstPointer, Alloc, typename phmap::pointer_traits< pointer >:: template rebind< const value_type > > const_pointer
Definition phmap_base.h:1394
static pointer allocate(Alloc &a, size_type n)
Definition phmap_base.h:1466
memory_internal::ExtractOrT< memory_internal::GetPointer, Alloc, value_type * > pointer
Definition phmap_base.h:1388
Definition phmap_base.h:840
static decltype(std::declval< F >()(std::declval< Args >()...)) Invoke(F &&f, Args &&... args)
Definition phmap_base.h:844
Definition phmap_base.h:823
static decltype((*std::declval< Ptr >()).*std::declval< DataMem >()) Invoke(DataMem &&data_mem, Ptr &&ptr)
Definition phmap_base.h:832
Definition phmap_base.h:806
static decltype(std::declval< Ref >().*std::declval< DataMem >()) Invoke(DataMem &&data_mem, Ref &&ref)
Definition phmap_base.h:814
Definition phmap_base.h:853
std::conditional< MemFunAndRef::Accept< Args... >::value, MemFunAndRef, typenamestd::conditional< MemFunAndPtr::Accept< Args... >::value, MemFunAndPtr, typenamestd::conditional< DataMemAndRef::Accept< Args... >::value, DataMemAndRef, typenamestd::conditional< DataMemAndPtr::Accept< Args... >::value, DataMemAndPtr, Callable >::type >::type >::type >::type type
Definition phmap_base.h:862
Definition phmap_base.h:779
static decltype(((*std::declval< Ptr >()).*std::declval< MemFun >())(std::declval< Args >()...)) Invoke(MemFun &&mem_fun, Ptr &&ptr, Args &&... args)
Definition phmap_base.h:796
Definition phmap_base.h:753
static decltype((std::declval< Obj >().*std::declval< MemFun >())(std::declval< Args >()...)) Invoke(MemFun &&mem_fun, Obj &&obj, Args &&... args)
Definition phmap_base.h:770
Definition phmap_base.h:743
Definition phmap_base.h:200
Definition phmap_base.h:1606
Definition phmap_base.h:4755
defer_lock_t()=default
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
static constexpr size_t size() noexcept
Definition phmap_base.h:908
T value_type
Definition phmap_base.h:907
Definition phmap_base.h:596
T type
Definition phmap_base.h:597
Definition phmap_base.h:163
Definition phmap_base.h:168
Definition phmap_base.h:260
Definition phmap_base.h:254
Definition phmap_base.h:242
typename T::element_type type
Definition phmap_base.h:1278
Definition phmap_base.h:1272
typename GetFirstArg< Ptr >::type type
Definition phmap_base.h:1273
Definition phmap_base.h:1218
Default type
Definition phmap_base.h:1219
Definition phmap_base.h:1264
std::unique_ptr< T[]> array
Definition phmap_base.h:1164
void invalid
Definition phmap_base.h:1168
Definition phmap_base.h:1159
std::unique_ptr< T > scalar
Definition phmap_base.h:1160
typename std::allocator_traits< A >::template rebind_alloc< U > type
Definition phmap_base.h:1317
Definition phmap_base.h:1311
typename RebindFirstArg< T, U >::type type
Definition phmap_base.h:1312
Class< U, Args... > type
Definition phmap_base.h:1287
Definition phmap_base.h:1282
typename T::template rebind< U > type
Definition phmap_base.h:1297
Definition phmap_base.h:1291
typename RebindFirstArg< T, U >::type type
Definition phmap_base.h:1292
Definition phmap_base.h:237
Definition phmap_base.h:1697
Definition phmap_base.h:1696
constexpr nullopt_t(init_t &)
Definition phmap_base.h:1700
static init_t init
Definition phmap_base.h:1698
Definition phmap_base.h:1711
optional_hash_base & operator=(optional_hash_base &&)=delete
optional_hash_base(optional_hash_base &&)=delete
optional_hash_base & operator=(const optional_hash_base &)=delete
optional_hash_base(const optional_hash_base &)=delete
U * rebind
Definition phmap_base.h:1361
static pointer pointer_to(element_type &r) noexcept
Definition phmap_base.h:1365
T * pointer
Definition phmap_base.h:1356
T element_type
Definition phmap_base.h:1357
std::ptrdiff_t difference_type
Definition phmap_base.h:1358
Definition phmap_base.h:1325
typename memory_internal::RebindPtr< Ptr, U >::type rebind
Definition phmap_base.h:1343
typename memory_internal::ElementType< Ptr >::type element_type
Definition phmap_base.h:1331
Ptr pointer
Definition phmap_base.h:1326
memory_internal::ExtractOrT< memory_internal::GetDifferenceType, Ptr, std::ptrdiff_t > difference_type
Definition phmap_base.h:1335
static pointer pointer_to(element_type &r)
Definition phmap_base.h:1347
Definition phmap_base.h:3696
Definition phmap_base.h:2883
static T Transfer(Args &&... args)
Definition phmap_base.h:2905
static T Move(Args &&... args)
Definition phmap_base.h:2910
static void Reset(Node *node)
Definition phmap_base.h:2895
static auto GetSlot(const Node &node) -> decltype(node.slot())
Definition phmap_base.h:2885
static T Make(Args &&... args)
Definition phmap_base.h:2900
static void Destroy(Node *node)
Definition phmap_base.h:2890
Definition phmap_base.h:2918
Iterator position
Definition phmap_base.h:2919
bool inserted
Definition phmap_base.h:2920
NodeType node
Definition phmap_base.h:2921
Definition phmap_base.h:2716
key_type type
Definition phmap_base.h:2734
Definition phmap_base.h:2723
K type
Definition phmap_base.h:2726
Key operator()(Key &&k, const Args &...) const
Definition phmap_base.h:434
Definition phmap_base.h:425
typename std::remove_reference< reference >::type value_type
Definition phmap_base.h:460
typename std::remove_reference< reference >::type * pointer
Definition phmap_base.h:459
static auto key(slot_type *slot) -> decltype(P::apply(ReturnKey(), element(slot)))
Definition phmap_base.h:554
static size_t space_used(const slot_type *slot)
Definition phmap_base.h:512
static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot)
Definition phmap_base.h:494
static auto element(slot_type *slot) -> decltype(P::element(slot))
Definition phmap_base.h:501
typename Policy::init_type init_type
Definition phmap_base.h:456
static void construct(Alloc *alloc, slot_type *slot, Args &&... args)
Definition phmap_base.h:471
static auto apply(F &&f, Ts &&... ts) -> decltype(P::apply(std::forward< F >(f), std::forward< Ts >(ts)...))
Definition phmap_base.h:546
decltype(Policy::element(std::declval< slot_type * >())) reference
Definition phmap_base.h:458
static void destroy(Alloc *alloc, slot_type *slot)
Definition phmap_base.h:478
typename Policy::slot_type slot_type
Definition phmap_base.h:448
typename Policy::key_type key_type
Definition phmap_base.h:451
static auto value(T *elem) -> decltype(P::value(elem))
Definition phmap_base.h:562
static void transfer_impl(Alloc *alloc, slot_type *new_slot, slot_type *old_slot, char)
Definition phmap_base.h:577
static auto transfer_impl(Alloc *alloc, slot_type *new_slot, slot_type *old_slot, int) -> decltype((void) P::transfer(alloc, new_slot, old_slot))
Definition phmap_base.h:570
constexpr const T & get() const &
Definition phmap_base.h:4238
constexpr Storage(T &&v)
Definition phmap_base.h:4237
constexpr const T && get() const &&
Definition phmap_base.h:4240
internal_compressed_tuple::ElemT< D, I > T
Definition phmap_base.h:4235
T & get() &
Definition phmap_base.h:4226
constexpr const T & get() const &
Definition phmap_base.h:4225
constexpr Storage(T &&v)
Definition phmap_base.h:4224
constexpr const T && get() const &&
Definition phmap_base.h:4227
ElemT< D, I > T
Definition phmap_base.h:4221
T && get() &&
Definition phmap_base.h:4228
Definition phmap_base.h:3732
static constexpr size_t value
Definition phmap_base.h:3733
Definition phmap_base.h:3701
Definition phmap_base.h:3725
Definition phmap_base.h:3715
T type
Definition phmap_base.h:3716
Definition phmap_base.h:4634
static value_type & element(slot_type *slot)
Definition phmap_base.h:4651
static void destroy(Allocator *alloc, slot_type *slot)
Definition phmap_base.h:4686
static void move(Allocator *alloc, slot_type *src, slot_type *dest)
Definition phmap_base.h:4725
static void emplace(slot_type *slot)
Definition phmap_base.h:4640
static const K & key(const slot_type *slot)
Definition phmap_base.h:4656
static void transfer(Allocator *alloc, slot_type *new_slot, slot_type *old_slot)
Definition phmap_base.h:4695
static void construct(Allocator *alloc, slot_type *slot, slot_type *other)
Definition phmap_base.h:4674
static const value_type & element(const slot_type *slot)
Definition phmap_base.h:4652
static void construct(Allocator *alloc, slot_type *slot, Args &&... args)
Definition phmap_base.h:4661
std::pair< const K, V > value_type
Definition phmap_base.h:4636
std::pair< K, V > mutable_value_type
Definition phmap_base.h:4637
static void swap(Allocator *alloc, slot_type *a, slot_type *b)
Definition phmap_base.h:4709
static void move(Allocator *alloc, slot_type *first, slot_type *last, slot_type *result)
Definition phmap_base.h:4736
static constexpr bool LayoutCompatible()
Definition phmap_base.h:4567
Definition phmap_base.h:4543
Definition phmap_base.h:2787
T type
Definition phmap_base.h:2988
Definition phmap_base.h:2982
typename phmap::remove_reference_t< C >::value_type type
Definition phmap_base.h:2983
Definition phmap_base.h:3015
decltype(testval(std::declval< From >())) type
Definition phmap_base.h:3019
static std::false_type testval(...)
Definition phmap_base.h:3023
Definition phmap_base.h:4756
static void Sink(...)
Definition phmap_base.h:369
static auto GetReturnType(int) -> decltype(std::declval< std::hash< Key > >()(std::declval< Key const & >()))
friend void AssertHashEnabled()
Definition phmap_base.h:405
static std::nullptr_t DoIt()
Definition phmap_base.h:379
Definition phmap_base.h:357
Definition phmap_base.h:95
void type
Definition phmap_base.h:96
std::false_type type
Definition phmap_base.h:138
std::false_type type
Definition phmap_base.h:125
Definition phmap_base.h:134
Definition phmap_base.h:922
Definition phmap_base.h:938
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition phmap_base.h:939
Definition phmap_base.h:4616
map_slot_type()
Definition phmap_base.h:4617
std::pair< const K, V > value_type
Definition phmap_base.h:4622
value_type value
Definition phmap_base.h:4625
map_slot_type(const map_slot_type &)=delete
K key
Definition phmap_base.h:4627
map_slot_type & operator=(const map_slot_type &)=delete
std::pair< K, V > mutable_value_type
Definition phmap_base.h:4623
mutable_value_type mutable_value
Definition phmap_base.h:4626